gus.c revision 1.20
1218885Sdim/* $NetBSD: gus.c,v 1.20 1997/03/19 19:54:44 mycroft Exp $ */ 2218885Sdim 3218885Sdim/*- 4218885Sdim * Copyright (c) 1996 The NetBSD Foundation, Inc. 5218885Sdim * All rights reserved. 6218885Sdim * 7218885Sdim * This code is derived from software contributed to The NetBSD Foundation 8218885Sdim * by Ken Hornstein and John Kohl. 9218885Sdim * 10218885Sdim * Redistribution and use in source and binary forms, with or without 11218885Sdim * modification, are permitted provided that the following conditions 12218885Sdim * are met: 13218885Sdim * 1. Redistributions of source code must retain the above copyright 14218885Sdim * notice, this list of conditions and the following disclaimer. 15218885Sdim * 2. Redistributions in binary form must reproduce the above copyright 16218885Sdim * notice, this list of conditions and the following disclaimer in the 17218885Sdim * documentation and/or other materials provided with the distribution. 18218885Sdim * 3. All advertising materials mentioning features or use of this software 19218885Sdim * must display the following acknowledgement: 20218885Sdim * This product includes software developed by the NetBSD 21218885Sdim * Foundation, Inc. and its contributors. 22218885Sdim * 4. Neither the name of The NetBSD Foundation nor the names of its 23218885Sdim * contributors may be used to endorse or promote products derived 24218885Sdim * from this software without specific prior written permission. 25218885Sdim * 26218885Sdim * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 27218885Sdim * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 28218885Sdim * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 29218885Sdim * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE 30218885Sdim * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 31218885Sdim * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 32218885Sdim * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 33218885Sdim * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 34219077Sdim * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 35219077Sdim * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 36219077Sdim * POSSIBILITY OF SUCH DAMAGE. 37219077Sdim */ 38219077Sdim 39218885Sdim/* 40218885Sdim * 41218885Sdim * TODO: 42218885Sdim * . figure out why mixer activity while sound is playing causes problems 43218885Sdim * (phantom interrupts?) 44218885Sdim * . figure out a better deinterleave strategy that avoids sucking up 45218885Sdim * CPU, memory and cache bandwidth. (Maybe a special encoding? 46239462Sdim * Maybe use the double-speed sampling/hardware deinterleave trick 47218885Sdim * from the GUS SDK?) A 486/33 isn't quite fast enough to keep 48218885Sdim * up with 44.1kHz 16-bit stereo output without some drop-outs. 49239462Sdim * . use CS4231 for 16-bit sampling, for a-law and mu-law playback. 50218885Sdim * . actually test full-duplex sampling(recording) and playback. 51249423Sdim */ 52218885Sdim 53249423Sdim/* 54249423Sdim * Gravis UltraSound driver 55249423Sdim * 56249423Sdim * For more detailed information, see the GUS developers' kit 57239462Sdim * available on the net at: 58239462Sdim * 59218885Sdim * ftp://freedom.nmsu.edu/pub/ultrasound/gravis/util/ 60218885Sdim * gusdkXXX.zip (developers' kit--get rev 2.22 or later) 61218885Sdim * See ultrawrd.doc inside--it's MS Word (ick), but it's the bible 62218885Sdim * 63218885Sdim */ 64218885Sdim 65218885Sdim/* 66218885Sdim * The GUS Max has a slightly strange set of connections between the CS4231 67249423Sdim * and the GF1 and the DMA interconnects. It's set up so that the CS4231 can 68249423Sdim * be playing while the GF1 is loading patches from the system. 69249423Sdim * 70249423Sdim * Here's a recreation of the DMA interconnect diagram: 71249423Sdim * 72249423Sdim * GF1 73249423Sdim * +---------+ digital 74249423Sdim * | | record ASIC 75249423Sdim * | |--------------+ 76249423Sdim * | | | +--------+ 77249423Sdim * | | play (dram) | +----+ | | 78249423Sdim * | |--------------(------|-\ | | +-+ | 79249423Sdim * +---------+ | | >-|----|---|C|--|------ dma chan 1 80249423Sdim * | +---|-/ | | +-+ | 81249423Sdim * | | +----+ | | | 82249423Sdim * | | +----+ | | | 83249423Sdim * +---------+ +-+ +--(---|-\ | | | | 84263508Sdim * | | play |8| | | >-|----|----+---|------ dma chan 2 85249423Sdim * | ---C----|--------|/|------(---|-/ | | | 86249423Sdim * | ^ |record |1| | +----+ | | 87249423Sdim * | | | /----|6|------+ +--------+ 88249423Sdim * | ---+----|--/ +-+ 89249423Sdim * +---------+ 90249423Sdim * CS4231 8-to-16 bit bus conversion, if needed 91249423Sdim * 92249423Sdim * 93249423Sdim * "C" is an optional combiner. 94249423Sdim * 95249423Sdim */ 96249423Sdim 97249423Sdim#include "gus.h" 98249423Sdim#if NGUS > 0 99249423Sdim 100249423Sdim#include <sys/param.h> 101249423Sdim#include <sys/systm.h> 102249423Sdim#include <sys/errno.h> 103249423Sdim#include <sys/ioctl.h> 104249423Sdim#include <sys/syslog.h> 105249423Sdim#include <sys/device.h> 106249423Sdim#include <sys/proc.h> 107249423Sdim#include <sys/buf.h> 108249423Sdim#include <sys/fcntl.h> 109249423Sdim#include <sys/malloc.h> 110249423Sdim#include <sys/kernel.h> 111249423Sdim 112249423Sdim#include <machine/cpu.h> 113249423Sdim#include <machine/intr.h> 114263508Sdim#include <machine/pio.h> 115249423Sdim#include <machine/cpufunc.h> 116249423Sdim#include <sys/audioio.h> 117249423Sdim#include <dev/audio_if.h> 118249423Sdim#include <dev/mulaw.h> 119249423Sdim 120249423Sdim#include <dev/isa/isavar.h> 121249423Sdim#include <dev/isa/isadmavar.h> 122249423Sdim#include <i386/isa/icu.h> 123249423Sdim 124249423Sdim#include <dev/ic/ics2101reg.h> 125249423Sdim#include <dev/ic/cs4231reg.h> 126249423Sdim#include <dev/ic/ad1848reg.h> 127249423Sdim#include <dev/isa/ics2101var.h> 128249423Sdim#include <dev/isa/ad1848var.h> 129249423Sdim#include <dev/isa/cs4231var.h> 130249423Sdim#include "gusreg.h" 131249423Sdim 132218885Sdim#ifdef AUDIO_DEBUG 133218885Sdim#define STATIC /* empty; for debugging symbols */ 134243830Sdim#else 135218885Sdim#define STATIC static 136218885Sdim#endif 137218885Sdim 138249423Sdim/* 139218885Sdim * Software state of a single "voice" on the GUS 140218885Sdim */ 141218885Sdim 142218885Sdimstruct gus_voice { 143249423Sdim 144218885Sdim /* 145218885Sdim * Various control bits 146218885Sdim */ 147218885Sdim 148218885Sdim unsigned char voccntl; /* State of voice control register */ 149218885Sdim unsigned char volcntl; /* State of volume control register */ 150218885Sdim unsigned char pan_pos; /* Position of volume panning (4 bits) */ 151218885Sdim int rate; /* Sample rate of voice being played back */ 152221345Sdim 153218885Sdim /* 154218885Sdim * Address of the voice data into the GUS's DRAM. 20 bits each 155218885Sdim */ 156218885Sdim 157218885Sdim u_long start_addr; /* Starting address of voice data loop area */ 158218885Sdim u_long end_addr; /* Ending address of voice data loop */ 159218885Sdim u_long current_addr; /* Beginning address of voice data 160218885Sdim (start playing here) */ 161218885Sdim 162221345Sdim /* 163218885Sdim * linear volume values for the GUS's volume ramp. 0-511 (9 bits). 164218885Sdim * These values must be translated into the logarithmic values using 165218885Sdim * gus_log_volumes[] 166218885Sdim */ 167218885Sdim 168218885Sdim int start_volume; /* Starting position of volume ramp */ 169218885Sdim int current_volume; /* Current position of volume on volume ramp */ 170218885Sdim int end_volume; /* Ending position of volume on volume ramp */ 171218885Sdim}; 172218885Sdim 173218885Sdim/* 174218885Sdim * Software state of GUS 175218885Sdim */ 176218885Sdim 177218885Sdimstruct gus_softc { 178218885Sdim struct device sc_dev; /* base device */ 179218885Sdim struct isadev sc_id; /* ISA device */ 180249423Sdim void *sc_ih; /* interrupt vector */ 181218885Sdim 182249423Sdim int sc_iobase; /* I/O base address */ 183249423Sdim int sc_irq; /* IRQ used */ 184249423Sdim int sc_drq; /* DMA channel for play */ 185249423Sdim int sc_recdrq; /* DMA channel for recording */ 186249423Sdim 187249423Sdim int sc_flags; /* Various flags about the GUS */ 188249423Sdim#define GUS_MIXER_INSTALLED 0x01 /* An ICS mixer is installed */ 189249423Sdim#define GUS_LOCKED 0x02 /* GUS is busy doing multi-phase DMA */ 190249423Sdim#define GUS_CODEC_INSTALLED 0x04 /* CS4231 installed/MAX */ 191249423Sdim#define GUS_PLAYING 0x08 /* GUS is playing a voice */ 192249423Sdim#define GUS_DMAOUT_ACTIVE 0x10 /* GUS is busy doing audio DMA */ 193249423Sdim#define GUS_DMAIN_ACTIVE 0x20 /* GUS is busy sampling */ 194249423Sdim#define GUS_OPEN 0x100 /* GUS is open */ 195249423Sdim int sc_dsize; /* Size of GUS DRAM */ 196249423Sdim int sc_voices; /* Number of active voices */ 197249423Sdim u_char sc_revision; /* Board revision of GUS */ 198249423Sdim u_char sc_mixcontrol; /* Value of GUS_MIX_CONTROL register */ 199249423Sdim 200249423Sdim u_long sc_orate; /* Output sampling rate */ 201249423Sdim u_long sc_irate; /* Input sampling rate */ 202249423Sdim 203249423Sdim int sc_encoding; /* Current data encoding type */ 204249423Sdim int sc_precision; /* # of bits of precision */ 205249423Sdim int sc_channels; /* Number of active channels */ 206249423Sdim int sc_blocksize; /* Current blocksize */ 207249423Sdim int sc_chanblocksize; /* Current blocksize for each in-use 208218885Sdim channel */ 209218885Sdim short sc_nbufs; /* how many on-GUS bufs per-channel */ 210218885Sdim short sc_bufcnt; /* how many need to be played */ 211218885Sdim void *sc_deintr_buf; /* deinterleave buffer for stereo */ 212218885Sdim 213218885Sdim int sc_ogain; /* Output gain control */ 214218885Sdim u_char sc_out_port; /* Current out port (generic only) */ 215218885Sdim u_char sc_in_port; /* keep track of it when no codec */ 216218885Sdim 217218885Sdim void (*sc_dmaoutintr) __P((void*)); /* DMA completion intr handler */ 218218885Sdim void *sc_outarg; /* argument for sc_dmaoutintr() */ 219218885Sdim u_char *sc_dmaoutaddr; /* for isa_dmadone */ 220218885Sdim u_long sc_gusaddr; /* where did we just put it? */ 221249423Sdim int sc_dmaoutcnt; /* for isa_dmadone */ 222218885Sdim 223218885Sdim void (*sc_dmainintr) __P((void*)); /* DMA completion intr handler */ 224218885Sdim void *sc_inarg; /* argument for sc_dmaoutintr() */ 225218885Sdim u_char *sc_dmainaddr; /* for isa_dmadone */ 226218885Sdim int sc_dmaincnt; /* for isa_dmadone */ 227223017Sdim 228218885Sdim struct stereo_dma_intr { 229218885Sdim void (*intr)__P((void *)); 230218885Sdim void *arg; 231243830Sdim u_char *buffer; 232243830Sdim u_long dmabuf; 233218885Sdim int size; 234221345Sdim int flags; 235218885Sdim } sc_stereo; 236221345Sdim 237218885Sdim /* 238218885Sdim * State information for linear audio layer 239218885Sdim */ 240221345Sdim 241218885Sdim int sc_dmabuf; /* Which ring buffer we're DMA'ing to */ 242218885Sdim int sc_playbuf; /* Which ring buffer we're playing */ 243218885Sdim 244221345Sdim /* 245218885Sdim * Voice information array. All voice-specific information is stored 246218885Sdim * here 247218885Sdim */ 248221345Sdim 249218885Sdim struct gus_voice sc_voc[32]; /* Voice data for each voice */ 250218885Sdim union { 251221345Sdim struct ics2101_softc sc_mixer_u; 252218885Sdim struct ad1848_softc sc_codec_u; 253243830Sdim } u; 254218885Sdim#define sc_mixer u.sc_mixer_u 255218885Sdim#define sc_codec u.sc_codec_u 256221345Sdim}; 257218885Sdim 258221345Sdimstruct ics2101_volume { 259218885Sdim u_char left; 260218885Sdim u_char right; 261218885Sdim}; 262223017Sdim 263223017Sdim#define HAS_CODEC(sc) ((sc)->sc_flags & GUS_CODEC_INSTALLED) 264243830Sdim#define HAS_MIXER(sc) ((sc)->sc_flags & GUS_MIXER_INSTALLED) 265243830Sdim 266223017Sdim/* 267243830Sdim * Mixer devices for ICS2101 268243830Sdim */ 269223017Sdim/* MIC IN mute, line in mute, line out mute are first since they can be done 270223017Sdim even if no ICS mixer. */ 271249423Sdim#define GUSICS_MIC_IN_MUTE 0 272249423Sdim#define GUSICS_LINE_IN_MUTE 1 273249423Sdim#define GUSICS_MASTER_MUTE 2 274249423Sdim#define GUSICS_CD_MUTE 3 275249423Sdim#define GUSICS_DAC_MUTE 4 276221345Sdim#define GUSICS_MIC_IN_LVL 5 277263508Sdim#define GUSICS_LINE_IN_LVL 6 278263508Sdim#define GUSICS_CD_LVL 7 279263508Sdim#define GUSICS_DAC_LVL 8 280263508Sdim#define GUSICS_MASTER_LVL 9 281263508Sdim 282249423Sdim#define GUSICS_RECORD_SOURCE 10 283249423Sdim 284249423Sdim/* Classes */ 285249423Sdim#define GUSICS_INPUT_CLASS 11 286249423Sdim#define GUSICS_OUTPUT_CLASS 12 287249423Sdim#define GUSICS_RECORD_CLASS 13 288249423Sdim 289249423Sdim/* 290249423Sdim * Mixer & MUX devices for CS4231 291249423Sdim */ 292249423Sdim#define GUSMAX_MIX_IN 0 /* input to MUX from mixer output */ 293249423Sdim#define GUSMAX_MONO_LVL 1 /* mic input to MUX; 294249423Sdim also mono mixer input */ 295249423Sdim#define GUSMAX_DAC_LVL 2 /* input to MUX; also mixer input */ 296249423Sdim#define GUSMAX_LINE_IN_LVL 3 /* input to MUX; also mixer input */ 297249423Sdim#define GUSMAX_CD_LVL 4 /* mixer input only */ 298249423Sdim#define GUSMAX_MONITOR_LVL 5 /* digital mix (?) */ 299249423Sdim#define GUSMAX_OUT_LVL 6 /* output level. (?) */ 300249423Sdim#define GUSMAX_SPEAKER_LVL 7 /* pseudo-device for mute */ 301249423Sdim#define GUSMAX_LINE_IN_MUTE 8 /* pre-mixer */ 302249423Sdim#define GUSMAX_DAC_MUTE 9 /* pre-mixer */ 303249423Sdim#define GUSMAX_CD_MUTE 10 /* pre-mixer */ 304249423Sdim#define GUSMAX_MONO_MUTE 11 /* pre-mixer--microphone/mono */ 305249423Sdim#define GUSMAX_MONITOR_MUTE 12 /* post-mixer level/mute */ 306249423Sdim#define GUSMAX_SPEAKER_MUTE 13 /* speaker mute */ 307249423Sdim 308249423Sdim#define GUSMAX_REC_LVL 14 /* post-MUX gain */ 309249423Sdim 310249423Sdim#define GUSMAX_RECORD_SOURCE 15 311249423Sdim 312249423Sdim/* Classes */ 313249423Sdim#define GUSMAX_INPUT_CLASS 16 314249423Sdim#define GUSMAX_RECORD_CLASS 17 315243830Sdim#define GUSMAX_MONITOR_CLASS 18 316243830Sdim#define GUSMAX_OUTPUT_CLASS 19 317263508Sdim 318249423Sdim#ifdef AUDIO_DEBUG 319249423Sdim#define GUSPLAYDEBUG /*XXX*/ 320249423Sdimextern void Dprintf __P((const char *, ...)); 321249423Sdim#define DPRINTF(x) if (gusdebug) Dprintf x 322249423Sdim#define DMAPRINTF(x) if (gusdmadebug) Dprintf x 323249423Sdimint gusdebug = 0; 324224145Sdimint gusdmadebug = 0; 325224145Sdim#else 326249423Sdim#define DPRINTF(x) 327249423Sdim#define DMAPRINTF(x) 328249423Sdim#endif 329218885Sdimint gus_dostereo = 1; 330249423Sdim 331249423Sdim#define NDMARECS 2048 332249423Sdim#ifdef GUSPLAYDEBUG 333249423Sdimint gusstats = 0; 334249423Sdimstruct dma_record { 335249423Sdim struct timeval tv; 336249423Sdim u_long gusaddr; 337249423Sdim caddr_t bsdaddr; 338249423Sdim u_short count; 339249423Sdim u_char channel; 340249423Sdim u_char direction; 341249423Sdim} dmarecords[NDMARECS]; 342263508Sdim 343249423Sdimint dmarecord_index = 0; 344249423Sdim#endif 345249423Sdim 346249423Sdim/* 347249423Sdim * local routines 348249423Sdim */ 349249423Sdim 350249423Sdimint gusopen __P((dev_t, int)); 351249423Sdimvoid gusclose __P((void *)); 352249423Sdimvoid gusmax_close __P((void *)); 353249423Sdimint gusintr __P((void *)); 354249423Sdimint gus_set_in_gain __P((caddr_t, u_int, u_char)); 355249423Sdimint gus_get_in_gain __P((caddr_t)); 356249423Sdimint gus_set_out_gain __P((caddr_t, u_int, u_char)); 357249423Sdimint gus_get_out_gain __P((caddr_t)); 358249423Sdimint gus_set_in_sr __P((void *, u_long)); 359249423Sdimu_long gus_get_in_sr __P((void *)); 360249423Sdimint gusmax_set_in_sr __P((void *, u_long)); 361249423Sdimu_long gusmax_get_in_sr __P((void *)); 362249423Sdimint gus_set_out_sr __P((void *, u_long)); 363249423Sdimu_long gus_get_out_sr __P((void *)); 364249423Sdimint gusmax_set_out_sr __P((void *, u_long)); 365249423Sdimu_long gusmax_get_out_sr __P((void *)); 366249423Sdimint gus_set_encoding __P((void *, u_int)); 367249423Sdimint gus_get_encoding __P((void *)); 368249423Sdimint gusmax_set_encoding __P((void *, u_int)); 369249423Sdimint gusmax_get_encoding __P((void *)); 370249423Sdimint gus_set_precision __P((void *, u_int)); 371249423Sdimint gus_get_precision __P((void *)); 372249423Sdimint gusmax_set_precision __P((void *, u_int)); 373249423Sdimint gusmax_get_precision __P((void *)); 374249423Sdimint gus_set_channels __P((void *, int)); 375249423Sdimint gus_get_channels __P((void *)); 376249423Sdimint gusmax_set_channels __P((void *, int)); 377249423Sdimint gusmax_get_channels __P((void *)); 378249423Sdimint gus_round_blocksize __P((void *, int)); 379249423Sdimint gus_set_out_port __P((void *, int)); 380249423Sdimint gus_get_out_port __P((void *)); 381249423Sdimint gus_set_in_port __P((void *, int)); 382249423Sdimint gus_get_in_port __P((void *)); 383249423Sdimint gus_commit_settings __P((void *)); 384249423Sdimint gus_dma_output __P((void *, void *, int, void (*)(void *), void *)); 385249423Sdimint gus_dma_input __P((void *, void *, int, void (*)(void *), void *)); 386249423Sdimint gus_halt_out_dma __P((void *)); 387249423Sdimint gus_halt_in_dma __P((void *)); 388249423Sdimint gus_cont_out_dma __P((void *)); 389249423Sdimint gus_cont_in_dma __P((void *)); 390249423Sdimint gus_speaker_ctl __P((void *, int)); 391249423Sdimint gusmax_set_precision __P((void *, u_int)); 392249423Sdimint gusmax_get_precision __P((void *)); 393249423Sdimint gusmax_round_blocksize __P((void *, int)); 394249423Sdimint gusmax_commit_settings __P((void *)); 395249423Sdimint gusmax_dma_output __P((void *, void *, int, void (*)(void *), void *)); 396249423Sdimint gusmax_dma_input __P((void *, void *, int, void (*)(void *), void *)); 397249423Sdimint gusmax_halt_out_dma __P((void *)); 398249423Sdimint gusmax_halt_in_dma __P((void *)); 399249423Sdimint gusmax_cont_out_dma __P((void *)); 400249423Sdimint gusmax_cont_in_dma __P((void *)); 401249423Sdimint gusmax_speaker_ctl __P((void *, int)); 402249423Sdimint gusmax_set_out_port __P((void *, int)); 403249423Sdimint gusmax_get_out_port __P((void *)); 404249423Sdimint gusmax_set_in_port __P((void *, int)); 405249423Sdimint gusmax_get_in_port __P((void *)); 406249423Sdimint gus_getdev __P((void *, struct audio_device *)); 407249423Sdim 408249423SdimSTATIC void gus_deinterleave __P((struct gus_softc *, void *, int)); 409249423SdimSTATIC void gus_expand __P((void *, int, u_char *, int)); 410249423SdimSTATIC void gusmax_expand __P((void *, int, u_char *, int)); 411249423Sdim 412249423SdimSTATIC int gus_mic_ctl __P((void *, int)); 413249423SdimSTATIC int gus_linein_ctl __P((void *, int)); 414249423SdimSTATIC int gus_test_iobase __P((int)); 415249423SdimSTATIC void guspoke __P((int, long, u_char)); 416249423SdimSTATIC void gusdmaout __P((struct gus_softc *, int, u_long, caddr_t, int)); 417249423SdimSTATIC void gus_init_cs4231 __P((struct gus_softc *)); 418249423SdimSTATIC void gus_init_ics2101 __P((struct gus_softc *)); 419249423Sdim 420249423SdimSTATIC void gus_set_chan_addrs __P((struct gus_softc *)); 421249423SdimSTATIC void gusreset __P((struct gus_softc *, int)); 422249423SdimSTATIC void gus_set_voices __P((struct gus_softc *, int)); 423249423SdimSTATIC void gus_set_volume __P((struct gus_softc *, int, int)); 424249423SdimSTATIC void gus_set_samprate __P((struct gus_softc *, int, int)); 425249423SdimSTATIC void gus_set_recrate __P((struct gus_softc *, u_long)); 426249423SdimSTATIC void gus_start_voice __P((struct gus_softc *, int, int)); 427249423SdimSTATIC void gus_stop_voice __P((struct gus_softc *, int, int)); 428249423SdimSTATIC void gus_set_endaddr __P((struct gus_softc *, int, u_long)); 429249423Sdim#ifdef GUSPLAYDEBUG 430249423SdimSTATIC void gus_set_curaddr __P((struct gus_softc *, int, u_long)); 431249423SdimSTATIC u_long gus_get_curaddr __P((struct gus_softc *, int)); 432249423Sdim#endif 433249423SdimSTATIC int gus_dmaout_intr __P((struct gus_softc *)); 434249423SdimSTATIC void gus_dmaout_dointr __P((struct gus_softc *)); 435249423SdimSTATIC void gus_dmaout_timeout __P((void *)); 436249423SdimSTATIC int gus_dmain_intr __P((struct gus_softc *)); 437249423SdimSTATIC int gus_voice_intr __P((struct gus_softc *)); 438249423SdimSTATIC void gus_start_playing __P((struct gus_softc *, int)); 439249423SdimSTATIC int gus_continue_playing __P((struct gus_softc *, int)); 440249423SdimSTATIC u_char guspeek __P((int, u_long)); 441249423SdimSTATIC u_long convert_to_16bit __P((u_long)); 442249423SdimSTATIC int gus_setfd __P((void *, int)); 443249423SdimSTATIC int gus_mixer_set_port __P((void *, mixer_ctrl_t *)); 444249423SdimSTATIC int gus_mixer_get_port __P((void *, mixer_ctrl_t *)); 445249423SdimSTATIC int gusmax_mixer_set_port __P((void *, mixer_ctrl_t *)); 446249423SdimSTATIC int gusmax_mixer_get_port __P((void *, mixer_ctrl_t *)); 447249423SdimSTATIC int gus_mixer_query_devinfo __P((void *, mixer_devinfo_t *)); 448249423SdimSTATIC int gusmax_mixer_query_devinfo __P((void *, mixer_devinfo_t *)); 449249423SdimSTATIC int gus_query_encoding __P((void *, struct audio_encoding *)); 450249423Sdim 451249423SdimSTATIC void gusics_master_mute __P((struct ics2101_softc *, int)); 452249423SdimSTATIC void gusics_dac_mute __P((struct ics2101_softc *, int)); 453249423SdimSTATIC void gusics_mic_mute __P((struct ics2101_softc *, int)); 454249423SdimSTATIC void gusics_linein_mute __P((struct ics2101_softc *, int)); 455249423SdimSTATIC void gusics_cd_mute __P((struct ics2101_softc *, int)); 456249423Sdim 457249423SdimSTATIC __inline int gus_to_vol __P((mixer_ctrl_t *, struct ad1848_volume *)); 458249423SdimSTATIC __inline int gus_from_vol __P((mixer_ctrl_t *, struct ad1848_volume *)); 459249423Sdim 460249423Sdimvoid stereo_dmaintr __P((void *)); 461249423Sdim 462249423Sdim/* 463249423Sdim * ISA bus driver routines 464249423Sdim */ 465249423Sdim 466249423Sdimint gusprobe __P((struct device *, void *, void *)); 467249423Sdimvoid gusattach __P((struct device *, struct device *, void *)); 468249423Sdim 469249423Sdimstruct cfattach gus_ca = { 470249423Sdim sizeof(struct gus_softc), gusprobe, gusattach, 471249423Sdim}; 472249423Sdim 473249423Sdimstruct cfdriver gus_cd = { 474249423Sdim NULL, "gus", DV_DULL 475249423Sdim}; 476249423Sdim 477249423Sdim 478249423Sdim/* 479249423Sdim * A mapping from IRQ/DRQ values to the values used in the GUS's internal 480249423Sdim * registers. A zero means that the referenced IRQ/DRQ is invalid 481249423Sdim */ 482249423Sdim 483249423Sdimstatic int gus_irq_map[] = { 484249423Sdim IRQUNK, IRQUNK, 1, 3, IRQUNK, 2, IRQUNK, 4, IRQUNK, 1, IRQUNK, 5, 6, 485249423Sdim IRQUNK, IRQUNK, 7 486249423Sdim}; 487249423Sdimstatic int gus_drq_map[] = { 488249423Sdim DRQUNK, 1, DRQUNK, 2, DRQUNK, 3, 4, 5 489249423Sdim}; 490249423Sdim 491249423Sdim/* 492249423Sdim * A list of valid base addresses for the GUS 493249423Sdim */ 494249423Sdim 495249423Sdimstatic int gus_base_addrs[] = { 496249423Sdim 0x210, 0x220, 0x230, 0x240, 0x250, 0x260 497249423Sdim}; 498249423Sdimstatic int gus_addrs = sizeof(gus_base_addrs) / sizeof(gus_base_addrs[0]); 499249423Sdim 500249423Sdim/* 501249423Sdim * Maximum frequency values of the GUS based on the number of currently active 502249423Sdim * voices. Since the GUS samples a voice every 1.6 us, the maximum frequency 503249423Sdim * is dependent on the number of active voices. Yes, it is pretty weird. 504249423Sdim */ 505249423Sdim 506249423Sdimstatic int gus_max_frequency[] = { 507263508Sdim 44100, /* 14 voices */ 508249423Sdim 41160, /* 15 voices */ 509249423Sdim 38587, /* 16 voices */ 510249423Sdim 36317, /* 17 voices */ 511249423Sdim 34300, /* 18 voices */ 512249423Sdim 32494, /* 19 voices */ 513249423Sdim 30870, /* 20 voices */ 514249423Sdim 29400, /* 21 voices */ 515249423Sdim 28063, /* 22 voices */ 516249423Sdim 26843, /* 23 voices */ 517249423Sdim 25725, /* 24 voices */ 518249423Sdim 24696, /* 25 voices */ 519249423Sdim 23746, /* 26 voices */ 520249423Sdim 22866, /* 27 voices */ 521249423Sdim 22050, /* 28 voices */ 522249423Sdim 21289, /* 29 voices */ 523249423Sdim 20580, /* 30 voices */ 524249423Sdim 19916, /* 31 voices */ 525249423Sdim 19293 /* 32 voices */ 526249423Sdim}; 527249423Sdim/* 528249423Sdim * A mapping of linear volume levels to the logarithmic volume values used 529249423Sdim * by the GF1 chip on the GUS. From GUS SDK vol1.c. 530249423Sdim */ 531249423Sdim 532249423Sdimstatic unsigned short gus_log_volumes[512] = { 533249423Sdim 0x0000, 534249423Sdim 0x0700, 0x07ff, 0x0880, 0x08ff, 0x0940, 0x0980, 0x09c0, 0x09ff, 0x0a20, 535249423Sdim 0x0a40, 0x0a60, 0x0a80, 0x0aa0, 0x0ac0, 0x0ae0, 0x0aff, 0x0b10, 0x0b20, 536249423Sdim 0x0b30, 0x0b40, 0x0b50, 0x0b60, 0x0b70, 0x0b80, 0x0b90, 0x0ba0, 0x0bb0, 537249423Sdim 0x0bc0, 0x0bd0, 0x0be0, 0x0bf0, 0x0bff, 0x0c08, 0x0c10, 0x0c18, 0x0c20, 538249423Sdim 0x0c28, 0x0c30, 0x0c38, 0x0c40, 0x0c48, 0x0c50, 0x0c58, 0x0c60, 0x0c68, 539249423Sdim 0x0c70, 0x0c78, 0x0c80, 0x0c88, 0x0c90, 0x0c98, 0x0ca0, 0x0ca8, 0x0cb0, 540249423Sdim 0x0cb8, 0x0cc0, 0x0cc8, 0x0cd0, 0x0cd8, 0x0ce0, 0x0ce8, 0x0cf0, 0x0cf8, 541249423Sdim 0x0cff, 0x0d04, 0x0d08, 0x0d0c, 0x0d10, 0x0d14, 0x0d18, 0x0d1c, 0x0d20, 542249423Sdim 0x0d24, 0x0d28, 0x0d2c, 0x0d30, 0x0d34, 0x0d38, 0x0d3c, 0x0d40, 0x0d44, 543249423Sdim 0x0d48, 0x0d4c, 0x0d50, 0x0d54, 0x0d58, 0x0d5c, 0x0d60, 0x0d64, 0x0d68, 544249423Sdim 0x0d6c, 0x0d70, 0x0d74, 0x0d78, 0x0d7c, 0x0d80, 0x0d84, 0x0d88, 0x0d8c, 545249423Sdim 0x0d90, 0x0d94, 0x0d98, 0x0d9c, 0x0da0, 0x0da4, 0x0da8, 0x0dac, 0x0db0, 546249423Sdim 0x0db4, 0x0db8, 0x0dbc, 0x0dc0, 0x0dc4, 0x0dc8, 0x0dcc, 0x0dd0, 0x0dd4, 547249423Sdim 0x0dd8, 0x0ddc, 0x0de0, 0x0de4, 0x0de8, 0x0dec, 0x0df0, 0x0df4, 0x0df8, 548249423Sdim 0x0dfc, 0x0dff, 0x0e02, 0x0e04, 0x0e06, 0x0e08, 0x0e0a, 0x0e0c, 0x0e0e, 549249423Sdim 0x0e10, 0x0e12, 0x0e14, 0x0e16, 0x0e18, 0x0e1a, 0x0e1c, 0x0e1e, 0x0e20, 550249423Sdim 0x0e22, 0x0e24, 0x0e26, 0x0e28, 0x0e2a, 0x0e2c, 0x0e2e, 0x0e30, 0x0e32, 551249423Sdim 0x0e34, 0x0e36, 0x0e38, 0x0e3a, 0x0e3c, 0x0e3e, 0x0e40, 0x0e42, 0x0e44, 552249423Sdim 0x0e46, 0x0e48, 0x0e4a, 0x0e4c, 0x0e4e, 0x0e50, 0x0e52, 0x0e54, 0x0e56, 553249423Sdim 0x0e58, 0x0e5a, 0x0e5c, 0x0e5e, 0x0e60, 0x0e62, 0x0e64, 0x0e66, 0x0e68, 554249423Sdim 0x0e6a, 0x0e6c, 0x0e6e, 0x0e70, 0x0e72, 0x0e74, 0x0e76, 0x0e78, 0x0e7a, 555249423Sdim 0x0e7c, 0x0e7e, 0x0e80, 0x0e82, 0x0e84, 0x0e86, 0x0e88, 0x0e8a, 0x0e8c, 556249423Sdim 0x0e8e, 0x0e90, 0x0e92, 0x0e94, 0x0e96, 0x0e98, 0x0e9a, 0x0e9c, 0x0e9e, 557249423Sdim 0x0ea0, 0x0ea2, 0x0ea4, 0x0ea6, 0x0ea8, 0x0eaa, 0x0eac, 0x0eae, 0x0eb0, 558249423Sdim 0x0eb2, 0x0eb4, 0x0eb6, 0x0eb8, 0x0eba, 0x0ebc, 0x0ebe, 0x0ec0, 0x0ec2, 559249423Sdim 0x0ec4, 0x0ec6, 0x0ec8, 0x0eca, 0x0ecc, 0x0ece, 0x0ed0, 0x0ed2, 0x0ed4, 560249423Sdim 0x0ed6, 0x0ed8, 0x0eda, 0x0edc, 0x0ede, 0x0ee0, 0x0ee2, 0x0ee4, 0x0ee6, 561249423Sdim 0x0ee8, 0x0eea, 0x0eec, 0x0eee, 0x0ef0, 0x0ef2, 0x0ef4, 0x0ef6, 0x0ef8, 562249423Sdim 0x0efa, 0x0efc, 0x0efe, 0x0eff, 0x0f01, 0x0f02, 0x0f03, 0x0f04, 0x0f05, 563249423Sdim 0x0f06, 0x0f07, 0x0f08, 0x0f09, 0x0f0a, 0x0f0b, 0x0f0c, 0x0f0d, 0x0f0e, 564249423Sdim 0x0f0f, 0x0f10, 0x0f11, 0x0f12, 0x0f13, 0x0f14, 0x0f15, 0x0f16, 0x0f17, 565249423Sdim 0x0f18, 0x0f19, 0x0f1a, 0x0f1b, 0x0f1c, 0x0f1d, 0x0f1e, 0x0f1f, 0x0f20, 566249423Sdim 0x0f21, 0x0f22, 0x0f23, 0x0f24, 0x0f25, 0x0f26, 0x0f27, 0x0f28, 0x0f29, 567249423Sdim 0x0f2a, 0x0f2b, 0x0f2c, 0x0f2d, 0x0f2e, 0x0f2f, 0x0f30, 0x0f31, 0x0f32, 568249423Sdim 0x0f33, 0x0f34, 0x0f35, 0x0f36, 0x0f37, 0x0f38, 0x0f39, 0x0f3a, 0x0f3b, 569249423Sdim 0x0f3c, 0x0f3d, 0x0f3e, 0x0f3f, 0x0f40, 0x0f41, 0x0f42, 0x0f43, 0x0f44, 570249423Sdim 0x0f45, 0x0f46, 0x0f47, 0x0f48, 0x0f49, 0x0f4a, 0x0f4b, 0x0f4c, 0x0f4d, 571249423Sdim 0x0f4e, 0x0f4f, 0x0f50, 0x0f51, 0x0f52, 0x0f53, 0x0f54, 0x0f55, 0x0f56, 572249423Sdim 0x0f57, 0x0f58, 0x0f59, 0x0f5a, 0x0f5b, 0x0f5c, 0x0f5d, 0x0f5e, 0x0f5f, 573249423Sdim 0x0f60, 0x0f61, 0x0f62, 0x0f63, 0x0f64, 0x0f65, 0x0f66, 0x0f67, 0x0f68, 574249423Sdim 0x0f69, 0x0f6a, 0x0f6b, 0x0f6c, 0x0f6d, 0x0f6e, 0x0f6f, 0x0f70, 0x0f71, 575249423Sdim 0x0f72, 0x0f73, 0x0f74, 0x0f75, 0x0f76, 0x0f77, 0x0f78, 0x0f79, 0x0f7a, 576249423Sdim 0x0f7b, 0x0f7c, 0x0f7d, 0x0f7e, 0x0f7f, 0x0f80, 0x0f81, 0x0f82, 0x0f83, 577249423Sdim 0x0f84, 0x0f85, 0x0f86, 0x0f87, 0x0f88, 0x0f89, 0x0f8a, 0x0f8b, 0x0f8c, 578249423Sdim 0x0f8d, 0x0f8e, 0x0f8f, 0x0f90, 0x0f91, 0x0f92, 0x0f93, 0x0f94, 0x0f95, 579249423Sdim 0x0f96, 0x0f97, 0x0f98, 0x0f99, 0x0f9a, 0x0f9b, 0x0f9c, 0x0f9d, 0x0f9e, 580249423Sdim 0x0f9f, 0x0fa0, 0x0fa1, 0x0fa2, 0x0fa3, 0x0fa4, 0x0fa5, 0x0fa6, 0x0fa7, 581249423Sdim 0x0fa8, 0x0fa9, 0x0faa, 0x0fab, 0x0fac, 0x0fad, 0x0fae, 0x0faf, 0x0fb0, 582249423Sdim 0x0fb1, 0x0fb2, 0x0fb3, 0x0fb4, 0x0fb5, 0x0fb6, 0x0fb7, 0x0fb8, 0x0fb9, 583249423Sdim 0x0fba, 0x0fbb, 0x0fbc, 0x0fbd, 0x0fbe, 0x0fbf, 0x0fc0, 0x0fc1, 0x0fc2, 584249423Sdim 0x0fc3, 0x0fc4, 0x0fc5, 0x0fc6, 0x0fc7, 0x0fc8, 0x0fc9, 0x0fca, 0x0fcb, 585249423Sdim 0x0fcc, 0x0fcd, 0x0fce, 0x0fcf, 0x0fd0, 0x0fd1, 0x0fd2, 0x0fd3, 0x0fd4, 586249423Sdim 0x0fd5, 0x0fd6, 0x0fd7, 0x0fd8, 0x0fd9, 0x0fda, 0x0fdb, 0x0fdc, 0x0fdd, 587249423Sdim 0x0fde, 0x0fdf, 0x0fe0, 0x0fe1, 0x0fe2, 0x0fe3, 0x0fe4, 0x0fe5, 0x0fe6, 588249423Sdim 0x0fe7, 0x0fe8, 0x0fe9, 0x0fea, 0x0feb, 0x0fec, 0x0fed, 0x0fee, 0x0fef, 589249423Sdim 0x0ff0, 0x0ff1, 0x0ff2, 0x0ff3, 0x0ff4, 0x0ff5, 0x0ff6, 0x0ff7, 0x0ff8, 590249423Sdim 0x0ff9, 0x0ffa, 0x0ffb, 0x0ffc, 0x0ffd, 0x0ffe, 0x0fff}; 591249423Sdim 592249423Sdim#define SELECT_GUS_REG(port,x) outb(port+GUS_REG_SELECT,x) 593249423Sdim#define WHICH_GUS_REG(port) inb(port+GUS_REG_SELECT) 594249423Sdim#define ADDR_HIGH(x) (unsigned int) ((x >> 7L) & 0x1fffL) 595249423Sdim#define ADDR_LOW(x) (unsigned int) ((x & 0x7fL) << 9L) 596249423Sdim 597249423Sdim#define GUS_MIN_VOICES 14 /* Minimum possible number of voices */ 598249423Sdim#define GUS_MAX_VOICES 32 /* Maximum possible number of voices */ 599249423Sdim#define GUS_VOICE_LEFT 0 /* Voice used for left (and mono) playback */ 600249423Sdim#define GUS_VOICE_RIGHT 1 /* Voice used for right playback */ 601249423Sdim#define GUS_MEM_OFFSET 32 /* Offset into GUS memory to begin of buffer */ 602249423Sdim#define GUS_BUFFER_MULTIPLE 1024 /* Audio buffers are multiples of this */ 603249423Sdim#define GUS_MEM_FOR_BUFFERS 131072 /* use this many bytes on-GUS */ 604249423Sdim#define GUS_LEFT_RIGHT_OFFSET (sc->sc_nbufs * sc->sc_chanblocksize + GUS_MEM_OFFSET) 605249423Sdim 606249423Sdim#define GUS_PREC_BYTES (sc->sc_precision >> 3) /* precision to bytes */ 607249423Sdim 608249423Sdim/* splgus() must be splaudio() */ 609249423Sdim 610249423Sdim#define splgus splaudio 611249423Sdim 612249423Sdim/* 613249423Sdim * Interface to higher level audio driver 614263508Sdim */ 615249423Sdim 616249423Sdimstruct audio_hw_if gus_hw_if = { 617249423Sdim gusopen, 618249423Sdim gusclose, 619249423Sdim NULL, /* drain */ 620249423Sdim gus_set_in_sr, 621249423Sdim gus_get_in_sr, 622249423Sdim gus_set_out_sr, 623249423Sdim gus_get_out_sr, 624249423Sdim 625249423Sdim gus_query_encoding, 626249423Sdim gus_set_encoding, 627249423Sdim gus_get_encoding, 628249423Sdim 629249423Sdim gus_set_precision, 630249423Sdim gus_get_precision, 631249423Sdim 632249423Sdim gus_set_channels, 633249423Sdim gus_get_channels, 634249423Sdim 635249423Sdim gus_round_blocksize, 636249423Sdim 637249423Sdim gus_set_out_port, 638249423Sdim gus_get_out_port, 639249423Sdim gus_set_in_port, 640249423Sdim gus_get_in_port, 641249423Sdim 642249423Sdim gus_commit_settings, 643249423Sdim 644249423Sdim gus_expand, 645249423Sdim mulaw_compress, 646249423Sdim 647249423Sdim gus_dma_output, 648249423Sdim gus_dma_input, 649249423Sdim gus_halt_out_dma, 650249423Sdim gus_halt_in_dma, 651249423Sdim gus_cont_out_dma, 652249423Sdim gus_cont_in_dma, 653249423Sdim 654249423Sdim gus_speaker_ctl, 655249423Sdim 656249423Sdim gus_getdev, 657249423Sdim gus_setfd, 658218885Sdim gus_mixer_set_port, 659221345Sdim gus_mixer_get_port, 660218885Sdim gus_mixer_query_devinfo, 661218885Sdim 1, /* full-duplex */ 662218885Sdim 0, 663218885Sdim}; 664218885Sdim 665221345Sdim 666218885Sdim/* 667249423Sdim * Some info about the current audio device 668249423Sdim */ 669218885Sdim 670263508Sdimstruct audio_device gus_device = { 671249423Sdim "UltraSound", 672249423Sdim "", 673218885Sdim "gus", 674218885Sdim}; 675221345Sdim 676263508Sdim#define FLIP_REV 5 /* This rev has flipped mixer chans */ 677249423Sdim 678249423Sdim 679218885Sdimint 680218885Sdimgusprobe(parent, match, aux) 681218885Sdim struct device *parent; 682218885Sdim void *match, *aux; 683249423Sdim{ 684249423Sdim register struct gus_softc *sc = match; 685221345Sdim register struct isa_attach_args *ia = aux; 686218885Sdim struct cfdata *cf = sc->sc_dev.dv_cfdata; 687218885Sdim register int iobase = ia->ia_iobase; 688249423Sdim int recdrq = cf->cf_flags; 689249423Sdim 690218885Sdim /* 691218885Sdim * Before we do anything else, make sure requested IRQ and DRQ are 692218885Sdim * valid for this card. 693221345Sdim */ 694218885Sdim 695218885Sdim if (gus_irq_map[ia->ia_irq] == IRQUNK) { 696218885Sdim printf("gus: invalid irq %d, card not probed\n", ia->ia_irq); 697218885Sdim return(0); 698218885Sdim } 699249423Sdim 700249423Sdim if (gus_drq_map[ia->ia_drq] == DRQUNK) { 701249423Sdim printf("gus: invalid drq %d, card not probed\n", ia->ia_drq); 702249423Sdim return(0); 703249423Sdim } 704249423Sdim 705249423Sdim if (recdrq != 0x00) { 706249423Sdim if (recdrq > 7 || gus_drq_map[recdrq] == DRQUNK) { 707249423Sdim printf("gus: invalid flag given for second DMA channel (0x%x), card not probed\n", recdrq); 708249423Sdim return(0); 709249423Sdim } 710249423Sdim } else 711249423Sdim recdrq = ia->ia_drq; 712249423Sdim 713249423Sdim if (iobase == IOBASEUNK) { 714249423Sdim int i; 715249423Sdim for(i = 0; i < gus_addrs; i++) 716249423Sdim if (gus_test_iobase(gus_base_addrs[i])) { 717249423Sdim iobase = gus_base_addrs[i]; 718249423Sdim goto done; 719249423Sdim } 720249423Sdim return 0; 721249423Sdim } else if (! gus_test_iobase(iobase)) 722249423Sdim return 0; 723249423Sdim 724249423Sdimdone: 725249423Sdim sc->sc_iobase = iobase; 726218885Sdim sc->sc_irq = ia->ia_irq; 727218885Sdim sc->sc_drq = ia->ia_drq; 728218885Sdim sc->sc_recdrq = recdrq; 729218885Sdim 730218885Sdim ia->ia_iobase = sc->sc_iobase; 731218885Sdim ia->ia_iosize = 16; /* XXX */ 732218885Sdim return(1); 733218885Sdim} 734218885Sdim 735218885Sdim/* 736218885Sdim * Test to see if a particular I/O base is valid for the GUS. Return true 737221345Sdim * if it is. 738218885Sdim */ 739218885Sdim 740218885SdimSTATIC int 741218885Sdimgus_test_iobase (int iobase) 742218885Sdim{ 743218885Sdim int i = splgus(); 744218885Sdim u_char s1, s2; 745218885Sdim 746221345Sdim /* 747218885Sdim * Reset GUS to an initial state before we do anything. 748218885Sdim */ 749218885Sdim 750218885Sdim delay(500); 751218885Sdim 752218885Sdim SELECT_GUS_REG(iobase, GUSREG_RESET); 753221345Sdim outb(iobase+GUS_DATA_HIGH, 0x00); 754218885Sdim 755218885Sdim delay(500); 756218885Sdim 757218885Sdim SELECT_GUS_REG(iobase, GUSREG_RESET); 758218885Sdim outb(iobase+GUS_DATA_HIGH, GUSMASK_MASTER_RESET); 759221345Sdim 760218885Sdim delay(500); 761218885Sdim 762218885Sdim splx(i); 763218885Sdim 764218885Sdim /* 765218885Sdim * See if we can write to the board's memory 766218885Sdim */ 767221345Sdim 768218885Sdim s1 = guspeek(iobase, 0L); 769218885Sdim s2 = guspeek(iobase, 1L); 770218885Sdim 771218885Sdim guspoke(iobase, 0L, 0xaa); 772218885Sdim guspoke(iobase, 1L, 0x55); 773218885Sdim 774226633Sdim if ((i=(int)guspeek(iobase, 0L)) != 0xaa) { 775218885Sdim return(0); 776218885Sdim } 777218885Sdim 778221345Sdim guspoke(iobase, 0L, s1); 779218885Sdim guspoke(iobase, 1L, s2); 780218885Sdim 781218885Sdim return 1; 782218885Sdim} 783221345Sdim 784218885Sdim/* 785218885Sdim * Setup the GUS for use; called shortly after probe 786218885Sdim */ 787218885Sdim 788218885Sdimvoid 789218885Sdimgusattach(parent, self, aux) 790218885Sdim struct device *parent, *self; 791218885Sdim void *aux; 792218885Sdim{ 793218885Sdim register struct gus_softc *sc = (void *) self; 794221345Sdim register struct isa_attach_args *ia = aux; 795218885Sdim register int port = ia->ia_iobase; 796221345Sdim int i; 797219077Sdim register unsigned char c,d,m; 798219077Sdim 799219077Sdim /* 800219077Sdim * Figure out our board rev, and see if we need to initialize the 801219077Sdim * mixer 802219077Sdim */ 803219077Sdim 804219077Sdim delay(500); 805221345Sdim 806218885Sdim c = inb(port+GUS_BOARD_REV); 807219077Sdim if (c != 0xff) 808218885Sdim sc->sc_revision = c; 809218885Sdim else 810218885Sdim sc->sc_revision = 0; 811218885Sdim 812218885Sdim 813218885Sdim SELECT_GUS_REG(port, GUSREG_RESET); 814218885Sdim outb(port+GUS_DATA_HIGH, 0x00); 815218885Sdim 816218885Sdim gusreset(sc, GUS_MAX_VOICES); /* initialize all voices */ 817218885Sdim gusreset(sc, GUS_MIN_VOICES); /* then set to just the ones we use */ 818218885Sdim 819218885Sdim /* 820218885Sdim * Setup the IRQ and DRQ lines in software, using values from 821226633Sdim * config file 822218885Sdim */ 823218885Sdim 824218885Sdim m = GUSMASK_LINE_IN|GUSMASK_LINE_OUT; /* disable all */ 825218885Sdim 826218885Sdim c = ((unsigned char) gus_irq_map[ia->ia_irq]) | GUSMASK_BOTH_RQ; 827218885Sdim 828218885Sdim if (sc->sc_recdrq == sc->sc_drq) 829218885Sdim d = (unsigned char) (gus_drq_map[sc->sc_drq] | 830218885Sdim GUSMASK_BOTH_RQ); 831218885Sdim else 832218885Sdim d = (unsigned char) (gus_drq_map[sc->sc_drq] | 833218885Sdim gus_drq_map[sc->sc_recdrq] << 3); 834218885Sdim 835218885Sdim /* 836218885Sdim * Program the IRQ and DMA channels on the GUS. Note that we hardwire 837218885Sdim * the GUS to only use one IRQ channel, but we give the user the 838218885Sdim * option of using two DMA channels (the other one given by the flags 839221345Sdim * option in the config file). Two DMA channels are needed for full- 840218885Sdim * duplex operation. 841221345Sdim * 842218885Sdim * The order of these operations is very magical. 843218885Sdim */ 844218885Sdim 845218885Sdim disable_intr(); 846218885Sdim 847218885Sdim outb(port+GUS_REG_CONTROL, GUS_REG_IRQCTL); 848218885Sdim outb(port+GUS_MIX_CONTROL, m); 849218885Sdim outb(port+GUS_IRQCTL_CONTROL, 0x00); 850218885Sdim outb(port+0x0f, 0x00); 851218885Sdim 852218885Sdim outb(port+GUS_MIX_CONTROL, m); 853221345Sdim outb(port+GUS_DMA_CONTROL, d | 0x80); /* magic reset? */ 854218885Sdim 855218885Sdim outb(port+GUS_MIX_CONTROL, m | GUSMASK_CONTROL_SEL); 856218885Sdim outb(port+GUS_IRQ_CONTROL, c); 857221345Sdim 858218885Sdim outb(port+GUS_MIX_CONTROL, m); 859218885Sdim outb(port+GUS_DMA_CONTROL, d); 860218885Sdim 861218885Sdim outb(port+GUS_MIX_CONTROL, m | GUSMASK_CONTROL_SEL); 862221345Sdim outb(port+GUS_IRQ_CONTROL, c); 863218885Sdim 864218885Sdim outb(port+GUS_VOICE_SELECT, 0x00); 865218885Sdim 866218885Sdim /* enable line in, line out. leave mic disabled. */ 867218885Sdim outb(port+GUS_MIX_CONTROL, 868218885Sdim (m | GUSMASK_LATCHES) & ~(GUSMASK_LINE_OUT|GUSMASK_LINE_IN)); 869218885Sdim outb(port+GUS_VOICE_SELECT, 0x00); 870218885Sdim 871218885Sdim enable_intr(); 872218885Sdim 873218885Sdim sc->sc_mixcontrol = 874218885Sdim (m | GUSMASK_LATCHES) & ~(GUSMASK_LINE_OUT|GUSMASK_LINE_IN); 875218885Sdim 876218885Sdim 877218885Sdim if (sc->sc_revision >= 5 && sc->sc_revision <= 9) { 878218885Sdim sc->sc_flags |= GUS_MIXER_INSTALLED; 879218885Sdim gus_init_ics2101(sc); 880218885Sdim } 881218885Sdim if (sc->sc_revision >= 0xa) { 882218885Sdim gus_init_cs4231(sc); 883218885Sdim } 884218885Sdim 885221345Sdim SELECT_GUS_REG(port, GUSREG_RESET); 886218885Sdim /* 887218885Sdim * Check to see how much memory we have on this card; see if any 888218885Sdim * "mirroring" occurs. We're assuming at least 256K already exists 889218885Sdim * on the card; otherwise the initial probe would have failed 890218885Sdim */ 891218885Sdim 892218885Sdim guspoke(port, 0L, 0x00); 893218885Sdim for(i = 1; i < 1024; i++) { 894218885Sdim u_long loc; 895218885Sdim 896218885Sdim /* 897218885Sdim * See if we've run into mirroring yet 898218885Sdim */ 899218885Sdim 900218885Sdim if (guspeek(port, 0L) != 0) 901218885Sdim break; 902218885Sdim 903218885Sdim loc = i << 10; 904218885Sdim 905218885Sdim guspoke(port, loc, 0xaa); 906218885Sdim if (guspeek(port, loc) != 0xaa) 907218885Sdim break; 908243830Sdim } 909218885Sdim 910218885Sdim sc->sc_dsize = i; 911218885Sdim sprintf(gus_device.version, "3.%d", sc->sc_revision); 912218885Sdim 913218885Sdim printf("\n <Gravis UltraSound version 3.%d, %dKB DRAM, ", 914221345Sdim sc->sc_revision, sc->sc_dsize); 915218885Sdim if (HAS_MIXER(sc)) 916218885Sdim printf("ICS2101 mixer, "); 917218885Sdim if (HAS_CODEC(sc)) 918218885Sdim printf("%s codec/mixer, ", sc->sc_codec.chip_name); 919221345Sdim if (sc->sc_recdrq == sc->sc_drq) { 920218885Sdim printf("half-duplex"); 921218885Sdim gus_hw_if.full_duplex = 0; 922218885Sdim } else { 923218885Sdim printf("full-duplex, record drq %d", sc->sc_recdrq); 924218885Sdim gus_hw_if.full_duplex = 1; 925218885Sdim } 926218885Sdim 927218885Sdim printf(">\n"); 928218885Sdim 929218885Sdim /* 930221345Sdim * Setup a default interrupt handler 931218885Sdim */ 932218885Sdim 933218885Sdim /* XXX we shouldn't have to use splgus == splclock, nor should 934218885Sdim * we use IPL_CLOCK. 935218885Sdim */ 936218885Sdim sc->sc_ih = isa_intr_establish(ia->ia_ic, ia->ia_irq, IST_EDGE, 937218885Sdim IPL_AUDIO, gusintr, sc /* sc->sc_gusdsp */); 938218885Sdim 939218885Sdim /* 940218885Sdim * Set some default values 941218885Sdim */ 942218885Sdim 943218885Sdim sc->sc_irate = sc->sc_orate = 44100; 944218885Sdim sc->sc_encoding = AUDIO_ENCODING_LINEAR; 945218885Sdim sc->sc_precision = 16; 946218885Sdim sc->sc_voc[GUS_VOICE_LEFT].voccntl |= GUSMASK_DATA_SIZE16; 947218885Sdim sc->sc_voc[GUS_VOICE_RIGHT].voccntl |= GUSMASK_DATA_SIZE16; 948221345Sdim sc->sc_channels = 1; 949218885Sdim sc->sc_ogain = 340; 950218885Sdim gus_commit_settings(sc); 951218885Sdim 952218885Sdim /* 953218885Sdim * We always put the left channel full left & right channel 954218885Sdim * full right. 955221345Sdim * For mono playback, we set up both voices playing the same buffer. 956263508Sdim */ 957263508Sdim outb(sc->sc_iobase+GUS_VOICE_SELECT, (unsigned char) GUS_VOICE_LEFT); 958218885Sdim SELECT_GUS_REG(sc->sc_iobase, GUSREG_PAN_POS); 959218885Sdim outb(sc->sc_iobase+GUS_DATA_HIGH, GUS_PAN_FULL_LEFT); 960218885Sdim 961218885Sdim outb(sc->sc_iobase+GUS_VOICE_SELECT, (unsigned char) GUS_VOICE_RIGHT); 962218885Sdim SELECT_GUS_REG(sc->sc_iobase, GUSREG_PAN_POS); 963218885Sdim outb(sc->sc_iobase+GUS_DATA_HIGH, GUS_PAN_FULL_RIGHT); 964218885Sdim 965218885Sdim /* 966263508Sdim * Attach to the generic audio layer 967263508Sdim */ 968218885Sdim 969263508Sdim if (audio_hardware_attach(&gus_hw_if, HAS_CODEC(sc) ? (void *)&sc->sc_codec : (void *)sc) != 0) 970218885Sdim printf("gus: could not attach to audio pseudo-device driver\n"); 971218885Sdim} 972218885Sdim 973218885Sdimint 974226633Sdimgusopen(dev, flags) 975218885Sdim dev_t dev; 976218885Sdim int flags; 977221345Sdim{ 978223017Sdim int unit = AUDIOUNIT(dev); 979223017Sdim struct gus_softc *sc; 980223017Sdim 981223017Sdim DPRINTF(("gusopen() called\n")); 982223017Sdim 983224145Sdim if (unit >= gus_cd.cd_ndevs) 984224145Sdim return ENXIO; 985263508Sdim sc = gus_cd.cd_devs[unit]; 986263508Sdim if (!sc) 987218885Sdim return ENXIO; 988218885Sdim 989218885Sdim if (sc->sc_flags & GUS_OPEN) 990223017Sdim return EBUSY; 991223017Sdim 992221345Sdim /* 993263508Sdim * Some initialization 994218885Sdim */ 995221345Sdim 996223017Sdim sc->sc_flags |= GUS_OPEN; 997223017Sdim sc->sc_dmabuf = 0; 998263508Sdim sc->sc_playbuf = -1; 999223017Sdim sc->sc_bufcnt = 0; 1000223017Sdim sc->sc_voc[GUS_VOICE_LEFT].start_addr = GUS_MEM_OFFSET - 1; 1001243830Sdim sc->sc_voc[GUS_VOICE_LEFT].current_addr = GUS_MEM_OFFSET; 1002223017Sdim 1003223017Sdim if (HAS_CODEC(sc)) { 1004224145Sdim ad1848_open(&sc->sc_codec, dev, flags); 1005223017Sdim sc->sc_codec.aux1_mute = 0; 1006223017Sdim ad1848_mute_aux1(&sc->sc_codec, 0); /* turn on DAC output */ 1007218885Sdim if (flags & FREAD) { 1008218885Sdim sc->sc_codec.mono_mute = 0; 1009263508Sdim cs4231_mute_mono(&sc->sc_codec, 0); 1010218885Sdim } 1011221345Sdim } else if (flags & FREAD) { 1012218885Sdim /* enable/unmute the microphone */ 1013221345Sdim if (HAS_MIXER(sc)) { 1014263508Sdim gusics_mic_mute(&sc->sc_mixer, 0); 1015218885Sdim } else 1016221345Sdim gus_mic_ctl(sc, SPKR_ON); 1017263508Sdim } 1018221345Sdim if (sc->sc_nbufs == 0) 1019221345Sdim gus_round_blocksize(sc, GUS_BUFFER_MULTIPLE); /* default blksiz */ 1020218885Sdim return 0; 1021221345Sdim} 1022221345Sdim 1023263508SdimSTATIC void 1024263508Sdimgusmax_expand(hdl, encoding, buf, count) 1025263508Sdim void *hdl; 1026263508Sdim int encoding; 1027263508Sdim u_char *buf; 1028263508Sdim int count; 1029263508Sdim{ 1030263508Sdim register struct ad1848_softc *ac = hdl; 1031263508Sdim 1032218885Sdim gus_expand(ac->parent, encoding, buf, count); 1033218885Sdim} 1034218885Sdim 1035263508SdimSTATIC void 1036263508Sdimgus_expand(hdl, encoding, buf, count) 1037263508Sdim void *hdl; 1038218885Sdim int encoding; 1039221345Sdim u_char *buf; 1040218885Sdim int count; 1041218885Sdim{ 1042218885Sdim struct gus_softc *sc = hdl; 1043218885Sdim 1044218885Sdim mulaw_expand(NULL, encoding, buf, count); 1045218885Sdim /* 1046218885Sdim * If we need stereo deinterleaving, do it now. 1047263508Sdim */ 1048218885Sdim if (sc->sc_channels == 2) 1049218885Sdim gus_deinterleave(sc, (void *)buf, count); 1050221345Sdim} 1051218885Sdim 1052218885SdimSTATIC void 1053221345Sdimgus_deinterleave(sc, buf, size) 1054221345Sdim register struct gus_softc *sc; 1055218885Sdim void *buf; 1056218885Sdim int size; 1057243830Sdim{ 1058218885Sdim /* deinterleave the stereo data. We can use sc->sc_deintr_buf 1059218885Sdim for scratch space. */ 1060218885Sdim register int i; 1061218885Sdim 1062218885Sdim /* 1063218885Sdim * size is in bytes. 1064218885Sdim */ 1065218885Sdim if (sc->sc_precision == 16) { 1066218885Sdim register u_short *dei = sc->sc_deintr_buf; 1067218885Sdim register u_short *sbuf = buf; 1068218885Sdim size >>= 1; /* bytecnt to shortcnt */ 1069218885Sdim /* copy 2nd of each pair of samples to the staging area, while 1070218885Sdim compacting the 1st of each pair into the original area. */ 1071218885Sdim for (i = 0; i < size/2-1; i++) { 1072221345Sdim dei[i] = sbuf[i*2+1]; 1073218885Sdim sbuf[i+1] = sbuf[i*2+2]; 1074221345Sdim } 1075223017Sdim /* 1076223017Sdim * this has copied one less sample than half of the 1077223017Sdim * buffer. The first sample of the 1st stream was 1078223017Sdim * already in place and didn't need copying. 1079223017Sdim * Therefore, we've moved all of the 1st stream's 1080224145Sdim * samples into place. We have one sample from 2nd 1081224145Sdim * stream in the last slot of original area, not 1082218885Sdim * copied to the staging area (But we don't need to!). 1083218885Sdim * Copy the remainder of the original stream into place. 1084218885Sdim */ 1085223017Sdim bcopy(dei, &sbuf[size/2], i * sizeof(short)); 1086223017Sdim } else { 1087223017Sdim register u_char *dei = sc->sc_deintr_buf; 1088223017Sdim register u_char *sbuf = buf; 1089223017Sdim for (i = 0; i < size/2-1; i++) { 1090223017Sdim dei[i] = sbuf[i*2+1]; 1091223017Sdim sbuf[i+1] = sbuf[i*2+2]; 1092224145Sdim } 1093223017Sdim bcopy(dei, &sbuf[size/2], i); 1094218885Sdim } 1095223017Sdim} 1096223017Sdim 1097223017Sdim/* 1098243830Sdim * Actually output a buffer to the DSP chip 1099218885Sdim */ 1100223017Sdim 1101218885Sdimint 1102218885Sdimgusmax_dma_output(addr, buf, size, intr, arg) 1103218885Sdim void * addr; 1104221345Sdim void *buf; 1105218885Sdim int size; 1106218885Sdim void (*intr) __P((void *)); 1107218885Sdim void *arg; 1108221345Sdim{ 1109223017Sdim register struct ad1848_softc *ac = addr; 1110223017Sdim return gus_dma_output(ac->parent, buf, size, intr, arg); 1111223017Sdim} 1112223017Sdim 1113243830Sdim/* 1114243830Sdim * called at splgus() from interrupt handler. 1115223017Sdim */ 1116223017Sdimvoid 1117224145Sdimstereo_dmaintr(arg) 1118223017Sdim void *arg; 1119223017Sdim{ 1120224145Sdim struct gus_softc *sc = arg; 1121218885Sdim struct stereo_dma_intr *sa = &sc->sc_stereo; 1122218885Sdim 1123263508Sdim DMAPRINTF(("stereo_dmaintr")); 1124263508Sdim 1125221345Sdim /* 1126263508Sdim * Put other half in its place, then call the real interrupt routine :) 1127221345Sdim */ 1128218885Sdim 1129263508Sdim sc->sc_dmaoutintr = sa->intr; 1130221345Sdim sc->sc_outarg = sa->arg; 1131221345Sdim 1132218885Sdim#ifdef GUSPLAYDEBUG 1133263508Sdim if (gusstats) { 1134221345Sdim microtime(&dmarecords[dmarecord_index].tv); 1135223017Sdim dmarecords[dmarecord_index].gusaddr = sa->dmabuf; 1136218885Sdim dmarecords[dmarecord_index].bsdaddr = sa->buffer; 1137218885Sdim dmarecords[dmarecord_index].count = sa->size; 1138223017Sdim dmarecords[dmarecord_index].channel = 1; 1139221345Sdim dmarecords[dmarecord_index].direction = 1; 1140218885Sdim dmarecord_index = ++dmarecord_index % NDMARECS; 1141218885Sdim } 1142218885Sdim#endif 1143221345Sdim 1144224145Sdim gusdmaout(sc, sa->flags, sa->dmabuf, (caddr_t) sa->buffer, sa->size); 1145218885Sdim 1146218885Sdim sa->flags = 0; 1147243830Sdim sa->dmabuf = 0; 1148218885Sdim sa->buffer = 0; 1149218885Sdim sa->size = 0; 1150218885Sdim sa->intr = 0; 1151 sa->arg = 0; 1152} 1153 1154/* 1155 * Start up DMA output to the card. 1156 * Called at splgus/splaudio already, either from intr handler or from 1157 * generic audio code. 1158 */ 1159int 1160gus_dma_output(addr, buf, size, intr, arg) 1161 void * addr; 1162 void *buf; 1163 int size; 1164 void (*intr) __P((void *)); 1165 void *arg; 1166{ 1167 struct gus_softc *sc = addr; 1168 u_char *buffer = buf; 1169 u_long boarddma; 1170 int flags; 1171 1172 DMAPRINTF(("gus_dma_output %d @ %x\n", size, buf)); 1173 1174 if (size != sc->sc_blocksize) { 1175 DPRINTF(("gus_dma_output reqsize %d not sc_blocksize %d\n", 1176 size, sc->sc_blocksize)); 1177 return EINVAL; 1178 } 1179 1180 flags = GUSMASK_DMA_WRITE; 1181 if (sc->sc_precision == 16) 1182 flags |= GUSMASK_DMA_DATA_SIZE; 1183 /* pcm16 is signed, mulaw & pcm8 are unsigned */ 1184 if (sc->sc_encoding == AUDIO_ENCODING_ULAW || 1185 sc->sc_encoding == AUDIO_ENCODING_PCM8) 1186 flags |= GUSMASK_DMA_INVBIT; 1187 1188 if (sc->sc_channels == 2) { 1189 if (sc->sc_precision == 16) { 1190 if (size & 3) { 1191 DPRINTF(("gus_dma_output: unpaired 16bit samples")); 1192 size &= 3; 1193 } 1194 } else if (size & 1) { 1195 DPRINTF(("gus_dma_output: unpaired samples")); 1196 size &= 1; 1197 } 1198 if (size == 0) 1199 return 0; 1200 size >>= 1; 1201 1202 boarddma = size * sc->sc_dmabuf + GUS_MEM_OFFSET; 1203 1204 sc->sc_stereo.intr = intr; 1205 sc->sc_stereo.arg = arg; 1206 sc->sc_stereo.size = size; 1207 sc->sc_stereo.dmabuf = boarddma + GUS_LEFT_RIGHT_OFFSET; 1208 sc->sc_stereo.buffer = buffer + size; 1209 sc->sc_stereo.flags = flags; 1210 if (gus_dostereo) { 1211 intr = stereo_dmaintr; 1212 arg = sc; 1213 } 1214 } else 1215 boarddma = size * sc->sc_dmabuf + GUS_MEM_OFFSET; 1216 1217 1218 sc->sc_flags |= GUS_LOCKED; 1219 sc->sc_dmaoutintr = intr; 1220 sc->sc_outarg = arg; 1221 1222#ifdef GUSPLAYDEBUG 1223 if (gusstats) { 1224 microtime(&dmarecords[dmarecord_index].tv); 1225 dmarecords[dmarecord_index].gusaddr = boarddma; 1226 dmarecords[dmarecord_index].bsdaddr = buffer; 1227 dmarecords[dmarecord_index].count = size; 1228 dmarecords[dmarecord_index].channel = 0; 1229 dmarecords[dmarecord_index].direction = 1; 1230 dmarecord_index = ++dmarecord_index % NDMARECS; 1231 } 1232#endif 1233 1234 gusdmaout(sc, flags, boarddma, (caddr_t) buffer, size); 1235 1236 return 0; 1237} 1238 1239void 1240gusmax_close(addr) 1241 void *addr; 1242{ 1243 register struct ad1848_softc *ac = addr; 1244 register struct gus_softc *sc = ac->parent; 1245#if 0 1246 ac->aux1_mute = 1; 1247 ad1848_mute_aux1(ac, 1); /* turn off DAC output */ 1248#endif 1249 ad1848_close(ac); 1250 gusclose(sc); 1251} 1252 1253/* 1254 * Close out device stuff. Called at splgus() from generic audio layer. 1255 */ 1256void 1257gusclose(addr) 1258 void *addr; 1259{ 1260 struct gus_softc *sc = addr; 1261 1262 DPRINTF(("gus_close: sc=0x%x\n", sc)); 1263 1264 1265/* if (sc->sc_flags & GUS_DMAOUT_ACTIVE) */ { 1266 gus_halt_out_dma(sc); 1267 } 1268/* if (sc->sc_flags & GUS_DMAIN_ACTIVE) */ { 1269 gus_halt_in_dma(sc); 1270 } 1271 sc->sc_flags &= ~(GUS_OPEN|GUS_LOCKED|GUS_DMAOUT_ACTIVE|GUS_DMAIN_ACTIVE); 1272 1273 if (sc->sc_deintr_buf) { 1274 FREE(sc->sc_deintr_buf, M_DEVBUF); 1275 sc->sc_deintr_buf = NULL; 1276 } 1277 /* turn off speaker, etc. */ 1278 1279 /* make sure the voices shut up: */ 1280 gus_stop_voice(sc, GUS_VOICE_LEFT, 1); 1281 gus_stop_voice(sc, GUS_VOICE_RIGHT, 0); 1282} 1283 1284/* 1285 * Service interrupts. Farm them off to helper routines if we are using the 1286 * GUS for simple playback/record 1287 */ 1288 1289#ifdef DIAGNOSTIC 1290int gusintrcnt; 1291int gusdmaintrcnt; 1292int gusvocintrcnt; 1293#endif 1294 1295int 1296gusintr(arg) 1297 void *arg; 1298{ 1299 register struct gus_softc *sc = arg; 1300 unsigned char intr; 1301 register int port = sc->sc_iobase; 1302 int retval = 0; 1303 1304 DPRINTF(("gusintr\n")); 1305#ifdef DIAGNOSTIC 1306 gusintrcnt++; 1307#endif 1308 if (HAS_CODEC(sc)) 1309 retval = ad1848_intr(&sc->sc_codec); 1310 if ((intr = inb(port+GUS_IRQ_STATUS)) & GUSMASK_IRQ_DMATC) { 1311 DMAPRINTF(("gusintr dma flags=%x\n", sc->sc_flags)); 1312#ifdef DIAGNOSTIC 1313 gusdmaintrcnt++; 1314#endif 1315 retval += gus_dmaout_intr(sc); 1316 if (sc->sc_flags & GUS_DMAIN_ACTIVE) { 1317 SELECT_GUS_REG(port, GUSREG_SAMPLE_CONTROL); 1318 intr = inb(port+GUS_DATA_HIGH); 1319 if (intr & GUSMASK_SAMPLE_DMATC) { 1320 retval += gus_dmain_intr(sc); 1321 } 1322 } 1323 } 1324 if (intr & (GUSMASK_IRQ_VOICE | GUSMASK_IRQ_VOLUME)) { 1325 DMAPRINTF(("gusintr voice flags=%x\n", sc->sc_flags)); 1326#ifdef DIAGNOSTIC 1327 gusvocintrcnt++; 1328#endif 1329 retval += gus_voice_intr(sc); 1330 } 1331 if (retval) 1332 return 1; 1333 return retval; 1334} 1335 1336int gus_bufcnt[GUS_MEM_FOR_BUFFERS / GUS_BUFFER_MULTIPLE]; 1337int gus_restart; /* how many restarts? */ 1338int gus_stops; /* how many times did voice stop? */ 1339int gus_falsestops; /* stopped but not done? */ 1340int gus_continues; 1341 1342struct playcont { 1343 struct timeval tv; 1344 u_int playbuf; 1345 u_int dmabuf; 1346 u_char bufcnt; 1347 u_char vaction; 1348 u_char voccntl; 1349 u_char volcntl; 1350 u_long curaddr; 1351 u_long endaddr; 1352} playstats[NDMARECS]; 1353 1354int playcntr; 1355 1356STATIC void 1357gus_dmaout_timeout(arg) 1358 void *arg; 1359{ 1360 register struct gus_softc *sc = arg; 1361 register int port = sc->sc_iobase; 1362 int s; 1363 1364 printf("%s: dmaout timeout\n", sc->sc_dev.dv_xname); 1365 /* 1366 * Stop any DMA. 1367 */ 1368 1369 s = splgus(); 1370 SELECT_GUS_REG(port, GUSREG_DMA_CONTROL); 1371 outb(sc->sc_iobase+GUS_DATA_HIGH, 0); 1372 1373#if 0 1374 isa_dmaabort(sc->sc_drq); /* XXX we will dmadone below? */ 1375#endif 1376 1377 gus_dmaout_dointr(sc); 1378 splx(s); 1379} 1380 1381 1382/* 1383 * Service DMA interrupts. This routine will only get called if we're doing 1384 * a DMA transfer for playback/record requests from the audio layer. 1385 */ 1386 1387STATIC int 1388gus_dmaout_intr(sc) 1389 struct gus_softc *sc; 1390{ 1391 register int port = sc->sc_iobase; 1392 1393 /* 1394 * If we got a DMA transfer complete from the GUS DRAM, then deal 1395 * with it. 1396 */ 1397 1398 SELECT_GUS_REG(port, GUSREG_DMA_CONTROL); 1399 if (inb(port+GUS_DATA_HIGH) & GUSMASK_DMA_IRQPEND) { 1400 untimeout(gus_dmaout_timeout, sc); 1401 gus_dmaout_dointr(sc); 1402 return 1; 1403 } 1404 return 0; 1405} 1406 1407STATIC void 1408gus_dmaout_dointr(sc) 1409 struct gus_softc *sc; 1410{ 1411 register int port = sc->sc_iobase; 1412 1413 /* sc->sc_dmaoutcnt - 1 because DMA controller counts from zero?. */ 1414 isa_dmadone(DMAMODE_WRITE, 1415 sc->sc_dmaoutaddr, 1416 sc->sc_dmaoutcnt - 1, 1417 sc->sc_drq); 1418 sc->sc_flags &= ~GUS_DMAOUT_ACTIVE; /* pending DMA is done */ 1419 DMAPRINTF(("gus_dmaout_dointr %d @ %x\n", sc->sc_dmaoutcnt, 1420 sc->sc_dmaoutaddr)); 1421 1422 /* 1423 * to prevent clicking, we need to copy last sample 1424 * from last buffer to scratch area just before beginning of 1425 * buffer. However, if we're doing formats that are converted by 1426 * the card during the DMA process, we need to pick up the converted 1427 * byte rather than the one we have in memory. 1428 */ 1429 if (sc->sc_dmabuf == sc->sc_nbufs - 1) { 1430 register int i; 1431 switch (sc->sc_encoding) { 1432 case AUDIO_ENCODING_PCM16: 1433 /* we have the native format */ 1434 for (i = 1; i <= 2; i++) 1435 guspoke(port, sc->sc_gusaddr - 1436 (sc->sc_nbufs - 1) * sc->sc_chanblocksize - i, 1437 sc->sc_dmaoutaddr[sc->sc_dmaoutcnt-i]); 1438 break; 1439 case AUDIO_ENCODING_PCM8: 1440 case AUDIO_ENCODING_ULAW: 1441 /* we need to fetch the translated byte, then stuff it. */ 1442 guspoke(port, sc->sc_gusaddr - 1443 (sc->sc_nbufs - 1) * sc->sc_chanblocksize - 1, 1444 guspeek(port, 1445 sc->sc_gusaddr + sc->sc_chanblocksize - 1)); 1446 break; 1447 } 1448 } 1449 /* 1450 * If this is the first half of stereo, "ignore" this one 1451 * and copy out the second half. 1452 */ 1453 if (sc->sc_dmaoutintr == stereo_dmaintr) { 1454 (*sc->sc_dmaoutintr)(sc->sc_outarg); 1455 return; 1456 } 1457 /* 1458 * If the voice is stopped, then start it. Reset the loop 1459 * and roll bits. Call the audio layer routine, since if 1460 * we're starting a stopped voice, that means that the next 1461 * buffer can be filled 1462 */ 1463 1464 sc->sc_flags &= ~GUS_LOCKED; 1465 if (sc->sc_voc[GUS_VOICE_LEFT].voccntl & 1466 GUSMASK_VOICE_STOPPED) { 1467 if (sc->sc_flags & GUS_PLAYING) { 1468 printf("%s: playing yet stopped?\n", sc->sc_dev.dv_xname); 1469 } 1470 sc->sc_bufcnt++; /* another yet to be played */ 1471 gus_start_playing(sc, sc->sc_dmabuf); 1472 gus_restart++; 1473 } else { 1474 /* 1475 * set the sound action based on which buffer we 1476 * just transferred. If we just transferred buffer 0 1477 * we want the sound to loop when it gets to the nth 1478 * buffer; if we just transferred 1479 * any other buffer, we want the sound to roll over 1480 * at least one more time. The voice interrupt 1481 * handlers will take care of accounting & 1482 * setting control bits if it's not caught up to us 1483 * yet. 1484 */ 1485 if (++sc->sc_bufcnt == 2) { 1486 /* 1487 * XXX 1488 * If we're too slow in reaction here, 1489 * the voice could be just approaching the 1490 * end of its run. It should be set to stop, 1491 * so these adjustments might not DTRT. 1492 */ 1493 if (sc->sc_dmabuf == 0 && 1494 sc->sc_playbuf == sc->sc_nbufs - 1) { 1495 /* player is just at the last buf, we're at the 1496 first. Turn on looping, turn off rolling. */ 1497 sc->sc_voc[GUS_VOICE_LEFT].voccntl |= GUSMASK_LOOP_ENABLE; 1498 sc->sc_voc[GUS_VOICE_LEFT].volcntl &= ~GUSMASK_VOICE_ROLL; 1499 playstats[playcntr].vaction = 3; 1500 } else { 1501 /* player is at previous buf: 1502 turn on rolling, turn off looping */ 1503 sc->sc_voc[GUS_VOICE_LEFT].voccntl &= ~GUSMASK_LOOP_ENABLE; 1504 sc->sc_voc[GUS_VOICE_LEFT].volcntl |= GUSMASK_VOICE_ROLL; 1505 playstats[playcntr].vaction = 4; 1506 } 1507#ifdef GUSPLAYDEBUG 1508 if (gusstats) { 1509 microtime(&playstats[playcntr].tv); 1510 playstats[playcntr].endaddr = sc->sc_voc[GUS_VOICE_LEFT].end_addr; 1511 playstats[playcntr].voccntl = sc->sc_voc[GUS_VOICE_LEFT].voccntl; 1512 playstats[playcntr].volcntl = sc->sc_voc[GUS_VOICE_LEFT].volcntl; 1513 playstats[playcntr].playbuf = sc->sc_playbuf; 1514 playstats[playcntr].dmabuf = sc->sc_dmabuf; 1515 playstats[playcntr].bufcnt = sc->sc_bufcnt; 1516 playstats[playcntr].curaddr = gus_get_curaddr(sc, GUS_VOICE_LEFT); 1517 playcntr = ++playcntr % NDMARECS; 1518 } 1519#endif 1520 outb(port+GUS_VOICE_SELECT, GUS_VOICE_LEFT); 1521 SELECT_GUS_REG(port, GUSREG_VOICE_CNTL); 1522 outb(port+GUS_DATA_HIGH, sc->sc_voc[GUS_VOICE_LEFT].voccntl); 1523 SELECT_GUS_REG(port, GUSREG_VOLUME_CONTROL); 1524 outb(port+GUS_DATA_HIGH, sc->sc_voc[GUS_VOICE_LEFT].volcntl); 1525 } 1526 } 1527 gus_bufcnt[sc->sc_bufcnt-1]++; 1528 /* 1529 * flip to the next DMA buffer 1530 */ 1531 1532 sc->sc_dmabuf = ++sc->sc_dmabuf % sc->sc_nbufs; 1533 /* 1534 * See comments below about DMA admission control strategy. 1535 * We can call the upper level here if we have an 1536 * idle buffer (not currently playing) to DMA into. 1537 */ 1538 if (sc->sc_dmaoutintr && sc->sc_bufcnt < sc->sc_nbufs) { 1539 /* clean out to prevent double calls */ 1540 void (*pfunc) __P((void *)) = sc->sc_dmaoutintr; 1541 void *arg = sc->sc_outarg; 1542 1543 sc->sc_outarg = 0; 1544 sc->sc_dmaoutintr = 0; 1545 (*pfunc)(arg); 1546 } 1547} 1548 1549/* 1550 * Service voice interrupts 1551 */ 1552 1553STATIC int 1554gus_voice_intr(sc) 1555 struct gus_softc *sc; 1556{ 1557 register int port = sc->sc_iobase; 1558 int ignore = 0, voice, rval = 0; 1559 unsigned char intr, status; 1560 1561 /* 1562 * The point of this may not be obvious at first. A voice can 1563 * interrupt more than once; according to the GUS SDK we are supposed 1564 * to ignore multiple interrupts for the same voice. 1565 */ 1566 1567 while(1) { 1568 SELECT_GUS_REG(port, GUSREG_IRQ_STATUS); 1569 intr = inb(port+GUS_DATA_HIGH); 1570 1571 if ((intr & (GUSMASK_WIRQ_VOLUME | GUSMASK_WIRQ_VOICE)) 1572 == (GUSMASK_WIRQ_VOLUME | GUSMASK_WIRQ_VOICE)) 1573 /* 1574 * No more interrupts, time to return 1575 */ 1576 return rval; 1577 1578 if ((intr & GUSMASK_WIRQ_VOICE) == 0) { 1579 1580 /* 1581 * We've got a voice interrupt. Ignore previous 1582 * interrupts by the same voice. 1583 */ 1584 1585 rval = 1; 1586 voice = intr & GUSMASK_WIRQ_VOICEMASK; 1587 1588 if ((1 << voice) & ignore) 1589 break; 1590 1591 ignore |= 1 << voice; 1592 1593 /* 1594 * If the voice is stopped, then force it to stop 1595 * (this stops it from continuously generating IRQs) 1596 */ 1597 1598 SELECT_GUS_REG(port, GUSREG_VOICE_CNTL+0x80); 1599 status = inb(port+GUS_DATA_HIGH); 1600 if (status & GUSMASK_VOICE_STOPPED) { 1601 if (voice != GUS_VOICE_LEFT) { 1602 DMAPRINTF(("%s: spurious voice %d stop?\n", 1603 sc->sc_dev.dv_xname, voice)); 1604 gus_stop_voice(sc, voice, 0); 1605 continue; 1606 } 1607 gus_stop_voice(sc, voice, 1); 1608 /* also kill right voice */ 1609 gus_stop_voice(sc, GUS_VOICE_RIGHT, 0); 1610 sc->sc_bufcnt--; /* it finished a buffer */ 1611 if (sc->sc_bufcnt > 0) { 1612 /* 1613 * probably a race to get here: the voice 1614 * stopped while the DMA code was just trying to 1615 * get the next buffer in place. 1616 * Start the voice again. 1617 */ 1618 printf("%s: stopped voice not drained? (%x)\n", 1619 sc->sc_dev.dv_xname, sc->sc_bufcnt); 1620 gus_falsestops++; 1621 1622 sc->sc_playbuf = ++sc->sc_playbuf % sc->sc_nbufs; 1623 gus_start_playing(sc, sc->sc_playbuf); 1624 } else if (sc->sc_bufcnt < 0) { 1625#ifdef DDB 1626 printf("%s: negative bufcnt in stopped voice\n", 1627 sc->sc_dev.dv_xname); 1628 Debugger(); 1629#else 1630 panic("%s: negative bufcnt in stopped voice", 1631 sc->sc_dev.dv_xname); 1632#endif 1633 } else { 1634 sc->sc_playbuf = -1; /* none are active */ 1635 gus_stops++; 1636 } 1637 /* fall through to callback and admit another 1638 buffer.... */ 1639 } else if (sc->sc_bufcnt != 0) { 1640 /* 1641 * This should always be taken if the voice 1642 * is not stopped. 1643 */ 1644 gus_continues++; 1645 if (gus_continue_playing(sc, voice)) { 1646 /* 1647 * we shouldn't have continued--active DMA 1648 * is in the way in the ring, for 1649 * some as-yet undebugged reason. 1650 */ 1651 gus_stop_voice(sc, GUS_VOICE_LEFT, 1); 1652 /* also kill right voice */ 1653 gus_stop_voice(sc, GUS_VOICE_RIGHT, 0); 1654 sc->sc_playbuf = -1; 1655 gus_stops++; 1656 } 1657 } 1658 /* 1659 * call the upper level to send on down another 1660 * block. We do admission rate control as follows: 1661 * 1662 * When starting up output (in the first N 1663 * blocks), call the upper layer after the DMA is 1664 * complete (see above in gus_dmaout_intr()). 1665 * 1666 * When output is already in progress and we have 1667 * no more GUS buffers to use for DMA, the DMA 1668 * output routines do not call the upper layer. 1669 * Instead, we call the DMA completion routine 1670 * here, after the voice interrupts indicating 1671 * that it's finished with a buffer. 1672 * 1673 * However, don't call anything here if the DMA 1674 * output flag is set, (which shouldn't happen) 1675 * because we'll squish somebody else's DMA if 1676 * that's the case. When DMA is done, it will 1677 * call back if there is a spare buffer. 1678 */ 1679 if (sc->sc_dmaoutintr && !(sc->sc_flags & GUS_LOCKED)) { 1680 if (sc->sc_dmaoutintr == stereo_dmaintr) 1681 printf("gusdmaout botch?\n"); 1682 else { 1683 /* clean out to avoid double calls */ 1684 void (*pfunc) __P((void *)) = sc->sc_dmaoutintr; 1685 void *arg = sc->sc_outarg; 1686 1687 sc->sc_outarg = 0; 1688 sc->sc_dmaoutintr = 0; 1689 (*pfunc)(arg); 1690 } 1691 } 1692 } 1693 1694 /* 1695 * Ignore other interrupts for now 1696 */ 1697 } 1698 return 0; 1699} 1700 1701STATIC void 1702gus_start_playing(sc, bufno) 1703struct gus_softc *sc; 1704int bufno; 1705{ 1706 register int port = sc->sc_iobase; 1707 /* 1708 * Start the voices playing, with buffer BUFNO. 1709 */ 1710 1711 /* 1712 * Loop or roll if we have buffers ready. 1713 */ 1714 1715 if (sc->sc_bufcnt == 1) { 1716 sc->sc_voc[GUS_VOICE_LEFT].voccntl &= ~(GUSMASK_LOOP_ENABLE); 1717 sc->sc_voc[GUS_VOICE_LEFT].volcntl &= ~(GUSMASK_VOICE_ROLL); 1718 } else { 1719 if (bufno == sc->sc_nbufs - 1) { 1720 sc->sc_voc[GUS_VOICE_LEFT].voccntl |= GUSMASK_LOOP_ENABLE; 1721 sc->sc_voc[GUS_VOICE_LEFT].volcntl &= ~(GUSMASK_VOICE_ROLL); 1722 } else { 1723 sc->sc_voc[GUS_VOICE_LEFT].voccntl &= ~GUSMASK_LOOP_ENABLE; 1724 sc->sc_voc[GUS_VOICE_LEFT].volcntl |= GUSMASK_VOICE_ROLL; 1725 } 1726 } 1727 1728 outb(port+GUS_VOICE_SELECT, GUS_VOICE_LEFT); 1729 1730 SELECT_GUS_REG(port, GUSREG_VOICE_CNTL); 1731 outb(port+GUS_DATA_HIGH, sc->sc_voc[GUS_VOICE_LEFT].voccntl); 1732 1733 SELECT_GUS_REG(port, GUSREG_VOLUME_CONTROL); 1734 outb(port+GUS_DATA_HIGH, sc->sc_voc[GUS_VOICE_LEFT].volcntl); 1735 1736 sc->sc_voc[GUS_VOICE_LEFT].current_addr = 1737 GUS_MEM_OFFSET + sc->sc_chanblocksize * bufno; 1738 sc->sc_voc[GUS_VOICE_LEFT].end_addr = 1739 sc->sc_voc[GUS_VOICE_LEFT].current_addr + sc->sc_chanblocksize - 1; 1740 sc->sc_voc[GUS_VOICE_RIGHT].current_addr = 1741 sc->sc_voc[GUS_VOICE_LEFT].current_addr + 1742 (gus_dostereo && sc->sc_channels == 2 ? GUS_LEFT_RIGHT_OFFSET : 0); 1743 /* 1744 * set up right channel to just loop forever, no interrupts, 1745 * starting at the buffer we just filled. We'll feed it data 1746 * at the same time as left channel. 1747 */ 1748 sc->sc_voc[GUS_VOICE_RIGHT].voccntl |= GUSMASK_LOOP_ENABLE; 1749 sc->sc_voc[GUS_VOICE_RIGHT].volcntl &= ~(GUSMASK_VOICE_ROLL); 1750 1751#ifdef GUSPLAYDEBUG 1752 if (gusstats) { 1753 microtime(&playstats[playcntr].tv); 1754 playstats[playcntr].curaddr = sc->sc_voc[GUS_VOICE_LEFT].current_addr; 1755 1756 playstats[playcntr].voccntl = sc->sc_voc[GUS_VOICE_LEFT].voccntl; 1757 playstats[playcntr].volcntl = sc->sc_voc[GUS_VOICE_LEFT].volcntl; 1758 playstats[playcntr].endaddr = sc->sc_voc[GUS_VOICE_LEFT].end_addr; 1759 playstats[playcntr].playbuf = bufno; 1760 playstats[playcntr].dmabuf = sc->sc_dmabuf; 1761 playstats[playcntr].bufcnt = sc->sc_bufcnt; 1762 playstats[playcntr].vaction = 5; 1763 playcntr = ++playcntr % NDMARECS; 1764 } 1765#endif 1766 1767 outb(port+GUS_VOICE_SELECT, GUS_VOICE_RIGHT); 1768 SELECT_GUS_REG(port, GUSREG_VOICE_CNTL); 1769 outb(port+GUS_DATA_HIGH, sc->sc_voc[GUS_VOICE_RIGHT].voccntl); 1770 SELECT_GUS_REG(port, GUSREG_VOLUME_CONTROL); 1771 outb(port+GUS_DATA_HIGH, sc->sc_voc[GUS_VOICE_RIGHT].volcntl); 1772 1773 gus_start_voice(sc, GUS_VOICE_RIGHT, 0); 1774 gus_start_voice(sc, GUS_VOICE_LEFT, 1); 1775 if (sc->sc_playbuf == -1) 1776 /* mark start of playing */ 1777 sc->sc_playbuf = bufno; 1778} 1779 1780STATIC int 1781gus_continue_playing(sc, voice) 1782register struct gus_softc *sc; 1783int voice; 1784{ 1785 register int port = sc->sc_iobase; 1786 1787 /* 1788 * stop this voice from interrupting while we work. 1789 */ 1790 1791 SELECT_GUS_REG(port, GUSREG_VOICE_CNTL); 1792 outb(port+GUS_DATA_HIGH, sc->sc_voc[voice].voccntl & ~(GUSMASK_VOICE_IRQ)); 1793 1794 /* 1795 * update playbuf to point to the buffer the hardware just started 1796 * playing 1797 */ 1798 sc->sc_playbuf = ++sc->sc_playbuf % sc->sc_nbufs; 1799 1800 /* 1801 * account for buffer just finished 1802 */ 1803 if (--sc->sc_bufcnt == 0) { 1804 DPRINTF(("gus: bufcnt 0 on continuing voice?\n")); 1805 } 1806 if (sc->sc_playbuf == sc->sc_dmabuf && (sc->sc_flags & GUS_LOCKED)) { 1807 printf("%s: continue into active dmabuf?\n", sc->sc_dev.dv_xname); 1808 return 1; 1809 } 1810 1811 /* 1812 * Select the end of the buffer based on the currently active 1813 * buffer, [plus extra contiguous buffers (if ready)]. 1814 */ 1815 1816 /* 1817 * set endpoint at end of buffer we just started playing. 1818 * 1819 * The total gets -1 because end addrs are one less than you might 1820 * think (the end_addr is the address of the last sample to play) 1821 */ 1822 gus_set_endaddr(sc, voice, GUS_MEM_OFFSET + 1823 sc->sc_chanblocksize * (sc->sc_playbuf + 1) - 1); 1824 1825 if (sc->sc_bufcnt < 2) { 1826 /* 1827 * Clear out the loop and roll flags, and rotate the currently 1828 * playing buffer. That way, if we don't manage to get more 1829 * data before this buffer finishes, we'll just stop. 1830 */ 1831 sc->sc_voc[voice].voccntl &= ~GUSMASK_LOOP_ENABLE; 1832 sc->sc_voc[voice].volcntl &= ~GUSMASK_VOICE_ROLL; 1833 playstats[playcntr].vaction = 0; 1834 } else { 1835 /* 1836 * We have some buffers to play. set LOOP if we're on the 1837 * last buffer in the ring, otherwise set ROLL. 1838 */ 1839 if (sc->sc_playbuf == sc->sc_nbufs - 1) { 1840 sc->sc_voc[voice].voccntl |= GUSMASK_LOOP_ENABLE; 1841 sc->sc_voc[voice].volcntl &= ~GUSMASK_VOICE_ROLL; 1842 playstats[playcntr].vaction = 1; 1843 } else { 1844 sc->sc_voc[voice].voccntl &= ~GUSMASK_LOOP_ENABLE; 1845 sc->sc_voc[voice].volcntl |= GUSMASK_VOICE_ROLL; 1846 playstats[playcntr].vaction = 2; 1847 } 1848 } 1849#ifdef GUSPLAYDEBUG 1850 if (gusstats) { 1851 microtime(&playstats[playcntr].tv); 1852 playstats[playcntr].curaddr = gus_get_curaddr(sc, voice); 1853 1854 playstats[playcntr].voccntl = sc->sc_voc[voice].voccntl; 1855 playstats[playcntr].volcntl = sc->sc_voc[voice].volcntl; 1856 playstats[playcntr].endaddr = sc->sc_voc[voice].end_addr; 1857 playstats[playcntr].playbuf = sc->sc_playbuf; 1858 playstats[playcntr].dmabuf = sc->sc_dmabuf; 1859 playstats[playcntr].bufcnt = sc->sc_bufcnt; 1860 playcntr = ++playcntr % NDMARECS; 1861 } 1862#endif 1863 1864 /* 1865 * (re-)set voice parameters. This will reenable interrupts from this 1866 * voice. 1867 */ 1868 1869 SELECT_GUS_REG(port, GUSREG_VOICE_CNTL); 1870 outb(port+GUS_DATA_HIGH, sc->sc_voc[voice].voccntl); 1871 SELECT_GUS_REG(port, GUSREG_VOLUME_CONTROL); 1872 outb(port+GUS_DATA_HIGH, sc->sc_voc[voice].volcntl); 1873 return 0; 1874} 1875 1876/* 1877 * Send/receive data into GUS's DRAM using DMA. Called at splgus() 1878 */ 1879 1880STATIC void 1881gusdmaout(sc, flags, gusaddr, buffaddr, length) 1882 struct gus_softc *sc; 1883 int flags, length; 1884 u_long gusaddr; 1885 caddr_t buffaddr; 1886{ 1887 register unsigned char c = (unsigned char) flags; 1888 register int port = sc->sc_iobase; 1889 1890 DMAPRINTF(("gusdmaout flags=%x scflags=%x\n", flags, sc->sc_flags)); 1891 1892 sc->sc_gusaddr = gusaddr; 1893 1894 /* 1895 * If we're using a 16 bit DMA channel, we have to jump through some 1896 * extra hoops; this includes translating the DRAM address a bit 1897 */ 1898 1899 if (sc->sc_drq >= 4) { 1900 c |= GUSMASK_DMA_WIDTH; 1901 gusaddr = convert_to_16bit(gusaddr); 1902 } 1903 1904 /* 1905 * Add flag bits that we always set - fast DMA, enable IRQ 1906 */ 1907 1908 c |= GUSMASK_DMA_ENABLE | GUSMASK_DMA_R0 | GUSMASK_DMA_IRQ; 1909 1910 /* 1911 * Make sure the GUS _isn't_ setup for DMA 1912 */ 1913 1914 SELECT_GUS_REG(port, GUSREG_DMA_CONTROL); 1915 outb(port+GUS_DATA_HIGH, 0); 1916 1917 /* 1918 * Tell the PC DMA controller to start doing DMA 1919 */ 1920 1921 sc->sc_dmaoutaddr = (u_char *) buffaddr; 1922 sc->sc_dmaoutcnt = length; 1923 isa_dmastart(DMAMODE_WRITE, buffaddr, length, sc->sc_drq); 1924 1925 /* 1926 * Set up DMA address - use the upper 16 bits ONLY 1927 */ 1928 1929 sc->sc_flags |= GUS_DMAOUT_ACTIVE; 1930 1931 SELECT_GUS_REG(port, GUSREG_DMA_START); 1932 outw(port+GUS_DATA_LOW, (int) (gusaddr >> 4)); 1933 1934 /* 1935 * Tell the GUS to start doing DMA 1936 */ 1937 1938 SELECT_GUS_REG(port, GUSREG_DMA_CONTROL); 1939 outb(port+GUS_DATA_HIGH, c); 1940 1941 /* 1942 * XXX If we don't finish in one second, give up... 1943 */ 1944 untimeout(gus_dmaout_timeout, sc); /* flush old one, if there is one */ 1945 timeout(gus_dmaout_timeout, sc, hz); 1946} 1947 1948/* 1949 * Start a voice playing on the GUS. Called from interrupt handler at 1950 * splgus(). 1951 */ 1952 1953STATIC void 1954gus_start_voice(sc, voice, intrs) 1955 struct gus_softc *sc; 1956 int voice; 1957 int intrs; 1958{ 1959 register int port = sc->sc_iobase; 1960 u_long start; 1961 u_long current; 1962 u_long end; 1963 1964 /* 1965 * Pick all the values for the voice out of the gus_voice struct 1966 * and use those to program the voice 1967 */ 1968 1969 start = sc->sc_voc[voice].start_addr; 1970 current = sc->sc_voc[voice].current_addr; 1971 end = sc->sc_voc[voice].end_addr; 1972 1973 /* 1974 * If we're using 16 bit data, mangle the addresses a bit 1975 */ 1976 1977 if (sc->sc_voc[voice].voccntl & GUSMASK_DATA_SIZE16) { 1978 /* -1 on start so that we get onto sample boundary--other 1979 code always sets it for 1-byte rollover protection */ 1980 start = convert_to_16bit(start-1); 1981 current = convert_to_16bit(current); 1982 end = convert_to_16bit(end); 1983 } 1984 1985 /* 1986 * Select the voice we want to use, and program the data addresses 1987 */ 1988 1989 outb(port+GUS_VOICE_SELECT, (unsigned char) voice); 1990 1991 SELECT_GUS_REG(port, GUSREG_START_ADDR_HIGH); 1992 outw(port+GUS_DATA_LOW, ADDR_HIGH(start)); 1993 SELECT_GUS_REG(port, GUSREG_START_ADDR_LOW); 1994 outw(port+GUS_DATA_LOW, ADDR_LOW(start)); 1995 1996 SELECT_GUS_REG(port, GUSREG_CUR_ADDR_HIGH); 1997 outw(port+GUS_DATA_LOW, ADDR_HIGH(current)); 1998 SELECT_GUS_REG(port, GUSREG_CUR_ADDR_LOW); 1999 outw(port+GUS_DATA_LOW, ADDR_LOW(current)); 2000 2001 SELECT_GUS_REG(port, GUSREG_END_ADDR_HIGH); 2002 outw(port+GUS_DATA_LOW, ADDR_HIGH(end)); 2003 SELECT_GUS_REG(port, GUSREG_END_ADDR_LOW); 2004 outw(port+GUS_DATA_LOW, ADDR_LOW(end)); 2005 2006 /* 2007 * (maybe) enable interrupts, disable voice stopping 2008 */ 2009 2010 if (intrs) { 2011 sc->sc_flags |= GUS_PLAYING; /* playing is about to start */ 2012 sc->sc_voc[voice].voccntl |= GUSMASK_VOICE_IRQ; 2013 DMAPRINTF(("gus voice playing=%x\n", sc->sc_flags)); 2014 } else 2015 sc->sc_voc[voice].voccntl &= ~GUSMASK_VOICE_IRQ; 2016 sc->sc_voc[voice].voccntl &= ~(GUSMASK_VOICE_STOPPED | 2017 GUSMASK_STOP_VOICE); 2018 2019 /* 2020 * Tell the GUS about it. Note that we're doing volume ramping here 2021 * from 0 up to the set volume to help reduce clicks. 2022 */ 2023 2024 SELECT_GUS_REG(port, GUSREG_START_VOLUME); 2025 outb(port+GUS_DATA_HIGH, 0x00); 2026 SELECT_GUS_REG(port, GUSREG_END_VOLUME); 2027 outb(port+GUS_DATA_HIGH, sc->sc_voc[voice].current_volume >> 4); 2028 SELECT_GUS_REG(port, GUSREG_CUR_VOLUME); 2029 outw(port+GUS_DATA_LOW, 0x00); 2030 SELECT_GUS_REG(port, GUSREG_VOLUME_RATE); 2031 outb(port+GUS_DATA_HIGH, 63); 2032 2033 SELECT_GUS_REG(port, GUSREG_VOICE_CNTL); 2034 outb(port+GUS_DATA_HIGH, sc->sc_voc[voice].voccntl); 2035 SELECT_GUS_REG(port, GUSREG_VOLUME_CONTROL); 2036 outb(port+GUS_DATA_HIGH, 0x00); 2037 delay(50); 2038 SELECT_GUS_REG(port, GUSREG_VOICE_CNTL); 2039 outb(port+GUS_DATA_HIGH, sc->sc_voc[voice].voccntl); 2040 SELECT_GUS_REG(port, GUSREG_VOLUME_CONTROL); 2041 outb(port+GUS_DATA_HIGH, 0x00); 2042 2043} 2044 2045/* 2046 * Stop a given voice. called at splgus() 2047 */ 2048 2049STATIC void 2050gus_stop_voice(sc, voice, intrs_too) 2051 struct gus_softc *sc; 2052 int voice; 2053 int intrs_too; 2054{ 2055 register int port = sc->sc_iobase; 2056 2057 sc->sc_voc[voice].voccntl |= GUSMASK_VOICE_STOPPED | 2058 GUSMASK_STOP_VOICE; 2059 if (intrs_too) { 2060 sc->sc_voc[voice].voccntl &= ~(GUSMASK_VOICE_IRQ); 2061 /* no more DMA to do */ 2062 sc->sc_flags &= ~GUS_PLAYING; 2063 } 2064 DMAPRINTF(("gusintr voice notplaying=%x\n", sc->sc_flags)); 2065 2066 guspoke(port, 0L, 0); 2067 2068 outb(port+GUS_VOICE_SELECT, (unsigned char) voice); 2069 2070 SELECT_GUS_REG(port, GUSREG_CUR_VOLUME); 2071 outw(port+GUS_DATA_LOW, 0x0000); 2072 SELECT_GUS_REG(port, GUSREG_VOICE_CNTL); 2073 outb(port+GUS_DATA_HIGH, sc->sc_voc[voice].voccntl); 2074 delay(100); 2075 SELECT_GUS_REG(port, GUSREG_CUR_VOLUME); 2076 outw(port+GUS_DATA_LOW, 0x0000); 2077 SELECT_GUS_REG(port, GUSREG_VOICE_CNTL); 2078 outb(port+GUS_DATA_HIGH, sc->sc_voc[voice].voccntl); 2079 2080 SELECT_GUS_REG(port, GUSREG_CUR_ADDR_HIGH); 2081 outw(port+GUS_DATA_LOW, 0x0000); 2082 SELECT_GUS_REG(port, GUSREG_CUR_ADDR_LOW); 2083 outw(port+GUS_DATA_LOW, 0x0000); 2084 2085} 2086 2087 2088/* 2089 * Set the volume of a given voice. Called at splgus(). 2090 */ 2091STATIC void 2092gus_set_volume(sc, voice, volume) 2093 struct gus_softc *sc; 2094 int voice, volume; 2095{ 2096 register int port = sc->sc_iobase; 2097 unsigned int gusvol; 2098 2099 gusvol = gus_log_volumes[volume < 512 ? volume : 511]; 2100 2101 sc->sc_voc[voice].current_volume = gusvol; 2102 2103 outb(port+GUS_VOICE_SELECT, (unsigned char) voice); 2104 2105 SELECT_GUS_REG(port, GUSREG_START_VOLUME); 2106 outb(port+GUS_DATA_HIGH, (unsigned char) (gusvol >> 4)); 2107 2108 SELECT_GUS_REG(port, GUSREG_END_VOLUME); 2109 outb(port+GUS_DATA_HIGH, (unsigned char) (gusvol >> 4)); 2110 2111 SELECT_GUS_REG(port, GUSREG_CUR_VOLUME); 2112 outw(port+GUS_DATA_LOW, gusvol << 4); 2113 delay(500); 2114 outw(port+GUS_DATA_LOW, gusvol << 4); 2115 2116} 2117 2118/* 2119 * Interface to the audio layer - set the data encoding type 2120 */ 2121 2122int 2123gusmax_set_encoding(addr, encoding) 2124 void * addr; 2125 u_int encoding; 2126{ 2127 register struct ad1848_softc *ac = addr; 2128 register struct gus_softc *sc = ac->parent; 2129 int error; 2130 2131 error = ad1848_set_encoding(ac, encoding); 2132 return (error ? error : gus_set_encoding(sc, encoding)); 2133} 2134 2135int 2136gus_set_encoding(addr, encoding) 2137 void * addr; 2138 u_int encoding; 2139{ 2140 register struct gus_softc *sc = addr; 2141 2142 DPRINTF(("gus_set_encoding called\n")); 2143 2144 /* XXX todo: add alaw for codec */ 2145 if (encoding != AUDIO_ENCODING_ULAW && 2146 encoding != AUDIO_ENCODING_PCM16 && 2147 encoding != AUDIO_ENCODING_PCM8) 2148 return EINVAL; 2149 2150 if (encoding != AUDIO_ENCODING_PCM16) 2151 sc->sc_precision = 8; /* XXX force it. */ 2152 2153 sc->sc_encoding = encoding; 2154 2155 if (sc->sc_precision == 8) { 2156 sc->sc_voc[GUS_VOICE_LEFT].voccntl &= ~GUSMASK_DATA_SIZE16; 2157 sc->sc_voc[GUS_VOICE_RIGHT].voccntl &= ~GUSMASK_DATA_SIZE16; 2158 } else { 2159 sc->sc_voc[GUS_VOICE_LEFT].voccntl |= GUSMASK_DATA_SIZE16; 2160 sc->sc_voc[GUS_VOICE_RIGHT].voccntl |= GUSMASK_DATA_SIZE16; 2161 } 2162 return 0; 2163} 2164 2165int 2166gusmax_set_channels(addr, channels) 2167 void * addr; 2168 int channels; 2169{ 2170 register struct ad1848_softc *ac = addr; 2171 register struct gus_softc *sc = ac->parent; 2172 int error; 2173 2174 error = ad1848_set_channels(ac, channels); 2175 return (error ? error : gus_set_channels(sc, channels)); 2176} 2177 2178int 2179gus_set_channels(addr, channels) 2180 void * addr; 2181 int channels; 2182{ 2183 register struct gus_softc *sc = addr; 2184 2185 DPRINTF(("gus_set_channels called\n")); 2186 2187 if (channels != 1 && channels != 2) 2188 return EINVAL; 2189 2190 sc->sc_channels = channels; 2191 2192 return 0; 2193} 2194 2195/* 2196 * Interface to the audio layer - set the data precision 2197 */ 2198 2199int 2200gusmax_set_precision(addr, bits) 2201 void * addr; 2202 u_int bits; 2203{ 2204 register struct ad1848_softc *ac = addr; 2205 register struct gus_softc *sc = ac->parent; 2206 int error; 2207 2208 error = ad1848_set_precision(ac, bits); 2209 return (error ? error : gus_set_precision(sc, bits)); 2210} 2211 2212 2213int 2214gus_set_precision(addr, bits) 2215 void * addr; 2216 u_int bits; 2217{ 2218 register struct gus_softc *sc = addr; 2219 2220 DPRINTF(("gus_set_precision called\n")); 2221 2222 if (bits != 8 && bits != 16) 2223 return EINVAL; 2224 2225 if (sc->sc_encoding != AUDIO_ENCODING_PCM16 && bits != 8) 2226 /* If we're doing PCM8 or MULAW, it must be 8 bits. */ 2227 return EINVAL; 2228 2229 sc->sc_precision = bits; 2230 2231 if (bits == 16) { 2232 sc->sc_voc[GUS_VOICE_LEFT].voccntl |= GUSMASK_DATA_SIZE16; 2233 sc->sc_voc[GUS_VOICE_RIGHT].voccntl |= GUSMASK_DATA_SIZE16; 2234 } else { 2235 sc->sc_voc[GUS_VOICE_LEFT].voccntl &= ~GUSMASK_DATA_SIZE16; 2236 sc->sc_voc[GUS_VOICE_RIGHT].voccntl &= ~GUSMASK_DATA_SIZE16; 2237 } 2238 return 0; 2239} 2240 2241/* 2242 * Interface to the audio layer - set the blocksize to the correct number 2243 * of units 2244 */ 2245 2246int 2247gusmax_round_blocksize(addr, blocksize) 2248 void * addr; 2249 int blocksize; 2250{ 2251 register struct ad1848_softc *ac = addr; 2252 register struct gus_softc *sc = ac->parent; 2253 2254/* blocksize = ad1848_round_blocksize(ac, blocksize);*/ 2255 return gus_round_blocksize(sc, blocksize); 2256} 2257 2258int 2259gus_round_blocksize(addr, blocksize) 2260 void * addr; 2261 int blocksize; 2262{ 2263 register struct gus_softc *sc = addr; 2264 2265 DPRINTF(("gus_round_blocksize called\n")); 2266 2267 if (sc->sc_encoding == AUDIO_ENCODING_ULAW && blocksize > 32768) 2268 blocksize = 32768; 2269 else if (blocksize > 65536) 2270 blocksize = 65536; 2271 2272 if ((blocksize % GUS_BUFFER_MULTIPLE) != 0) 2273 blocksize = (blocksize / GUS_BUFFER_MULTIPLE + 1) * 2274 GUS_BUFFER_MULTIPLE; 2275 2276 /* set up temporary buffer to hold the deinterleave, if necessary 2277 for stereo output */ 2278 if (sc->sc_deintr_buf) { 2279 FREE(sc->sc_deintr_buf, M_DEVBUF); 2280 sc->sc_deintr_buf = NULL; 2281 } 2282 MALLOC(sc->sc_deintr_buf, void *, blocksize>>1, M_DEVBUF, M_WAITOK); 2283 2284 sc->sc_blocksize = blocksize; 2285 /* multi-buffering not quite working yet. */ 2286 sc->sc_nbufs = /*GUS_MEM_FOR_BUFFERS / blocksize*/ 2; 2287 2288 gus_set_chan_addrs(sc); 2289 2290 return blocksize; 2291} 2292 2293/* 2294 * Interfaces to the audio layer - return values from the software config 2295 * struct 2296 */ 2297 2298int 2299gusmax_get_encoding(addr) 2300 void * addr; 2301{ 2302 register struct ad1848_softc *ac = addr; 2303 register struct gus_softc *sc = ac->parent; 2304 return gus_get_encoding(sc); 2305} 2306 2307int 2308gus_get_encoding(addr) 2309 void * addr; 2310{ 2311 register struct gus_softc *sc = addr; 2312 2313 DPRINTF(("gus_get_encoding called\n")); 2314 2315 /* XXX TODO: codec stuff */ 2316 return sc->sc_encoding; 2317} 2318 2319int 2320gusmax_get_channels(addr) 2321 void * addr; 2322{ 2323 register struct ad1848_softc *ac = addr; 2324 register struct gus_softc *sc = ac->parent; 2325 return gus_get_channels(sc); 2326} 2327 2328int 2329gus_get_channels(addr) 2330 void * addr; 2331{ 2332 register struct gus_softc *sc = addr; 2333 2334 DPRINTF(("gus_get_channels called\n")); 2335 2336 return sc->sc_channels; 2337} 2338 2339u_long 2340gus_get_in_sr(addr) 2341 void * addr; 2342{ 2343 register struct gus_softc *sc = addr; 2344 2345 DPRINTF(("gus_get_in_sr called\n")); 2346 return sc->sc_irate; 2347} 2348 2349u_long 2350gusmax_get_in_sr(addr) 2351 void * addr; 2352{ 2353 register struct ad1848_softc *ac = addr; 2354 register struct gus_softc *sc = ac->parent; 2355 return gus_get_in_sr(sc); 2356} 2357 2358u_long 2359gusmax_get_out_sr(addr) 2360 void * addr; 2361{ 2362 register struct ad1848_softc *ac = addr; 2363 register struct gus_softc *sc = ac->parent; 2364 return gus_get_out_sr(sc); 2365} 2366 2367u_long 2368gus_get_out_sr(addr) 2369 void * addr; 2370{ 2371 register struct gus_softc *sc = addr; 2372 2373 DPRINTF(("gus_get_out_sr called\n")); 2374 return sc->sc_orate; 2375} 2376 2377int 2378gusmax_get_precision(addr) 2379 void * addr; 2380{ 2381 register struct ad1848_softc *sc = addr; 2382 return gus_get_precision(sc->parent); 2383} 2384 2385int 2386gus_get_precision(addr) 2387 void * addr; 2388{ 2389 register struct gus_softc *sc = addr; 2390 2391 DPRINTF(("gus_get_precision called\n")); 2392 2393 return sc->sc_precision; 2394} 2395 2396int 2397gus_get_out_gain(addr) 2398 caddr_t addr; 2399{ 2400 register struct gus_softc *sc = (struct gus_softc *) addr; 2401 2402 DPRINTF(("gus_get_out_gain called\n")); 2403 return sc->sc_ogain / 2; 2404} 2405 2406/* 2407 * Interface to the audio layer - set the sample rate of the output voices 2408 */ 2409 2410int 2411gusmax_set_out_sr(addr, rate) 2412 void * addr; 2413 u_long rate; 2414{ 2415 register struct ad1848_softc *ac = addr; 2416 register struct gus_softc *sc = ac->parent; 2417 int error; 2418 2419 error = ad1848_set_out_sr(ac, rate); 2420 return (error ? error : gus_set_out_sr(sc, rate)); 2421} 2422 2423int 2424gus_set_out_sr(addr, rate) 2425 void * addr; 2426 u_long rate; 2427{ 2428 register struct gus_softc *sc = addr; 2429 2430 DPRINTF(("gus_set_out_sr called\n")); 2431 2432 if (rate > gus_max_frequency[sc->sc_voices - GUS_MIN_VOICES]) 2433 rate = gus_max_frequency[sc->sc_voices - GUS_MIN_VOICES]; 2434 2435 sc->sc_orate = rate; 2436 2437 return 0; 2438} 2439 2440STATIC inline void gus_set_voices(sc, voices) 2441struct gus_softc *sc; 2442int voices; 2443{ 2444 register int port = sc->sc_iobase; 2445 /* 2446 * Select the active number of voices 2447 */ 2448 2449 SELECT_GUS_REG(port, GUSREG_ACTIVE_VOICES); 2450 outb(port+GUS_DATA_HIGH, (voices-1) | 0xc0); 2451 2452 sc->sc_voices = voices; 2453} 2454 2455/* 2456 * Actually set the settings of various values on the card 2457 */ 2458 2459int 2460gusmax_commit_settings(addr) 2461 void * addr; 2462{ 2463 register struct ad1848_softc *ac = addr; 2464 register struct gus_softc *sc = ac->parent; 2465 2466 (void) ad1848_commit_settings(ac); 2467 return gus_commit_settings(sc); 2468} 2469 2470/* 2471 * Commit the settings. Called at normal IPL. 2472 */ 2473int 2474gus_commit_settings(addr) 2475 void * addr; 2476{ 2477 register struct gus_softc *sc = addr; 2478 int s; 2479 2480 DPRINTF(("gus_commit_settings called (gain = %d)\n",sc->sc_ogain)); 2481 2482 2483 s = splgus(); 2484 2485 gus_set_recrate(sc, sc->sc_irate); 2486 gus_set_volume(sc, GUS_VOICE_LEFT, sc->sc_ogain); 2487 gus_set_volume(sc, GUS_VOICE_RIGHT, sc->sc_ogain); 2488 gus_set_samprate(sc, GUS_VOICE_LEFT, sc->sc_orate); 2489 gus_set_samprate(sc, GUS_VOICE_RIGHT, sc->sc_orate); 2490 splx(s); 2491 gus_set_chan_addrs(sc); 2492 2493 return 0; 2494} 2495 2496STATIC void 2497gus_set_chan_addrs(sc) 2498struct gus_softc *sc; 2499{ 2500 /* 2501 * We use sc_nbufs * blocksize bytes of storage in the on-board GUS 2502 * ram. 2503 * For mono, each of the sc_nbufs buffers is DMA'd to in one chunk, 2504 * and both left & right channels play the same buffer. 2505 * 2506 * For stereo, each channel gets a contiguous half of the memory, 2507 * and each has sc_nbufs buffers of size blocksize/2. 2508 * Stereo data are deinterleaved in main memory before the DMA out 2509 * routines are called to queue the output. 2510 * 2511 * The blocksize per channel is kept in sc_chanblocksize. 2512 */ 2513 if (sc->sc_channels == 2) 2514 sc->sc_chanblocksize = sc->sc_blocksize/2; 2515 else 2516 sc->sc_chanblocksize = sc->sc_blocksize; 2517 2518 sc->sc_voc[GUS_VOICE_LEFT].start_addr = GUS_MEM_OFFSET - 1; 2519 sc->sc_voc[GUS_VOICE_RIGHT].start_addr = 2520 (gus_dostereo && sc->sc_channels == 2 ? GUS_LEFT_RIGHT_OFFSET : 0) 2521 + GUS_MEM_OFFSET - 1; 2522 sc->sc_voc[GUS_VOICE_RIGHT].current_addr = 2523 sc->sc_voc[GUS_VOICE_RIGHT].start_addr + 1; 2524 sc->sc_voc[GUS_VOICE_RIGHT].end_addr = 2525 sc->sc_voc[GUS_VOICE_RIGHT].start_addr + 2526 sc->sc_nbufs * sc->sc_chanblocksize; 2527 2528} 2529 2530/* 2531 * Set the sample rate of the given voice. Called at splgus(). 2532 */ 2533 2534STATIC void 2535gus_set_samprate(sc, voice, freq) 2536 struct gus_softc *sc; 2537 int voice, freq; 2538{ 2539 register int port = sc->sc_iobase; 2540 unsigned int fc; 2541 u_long temp, f = (u_long) freq; 2542 2543 /* 2544 * calculate fc based on the number of active voices; 2545 * we need to use longs to preserve enough bits 2546 */ 2547 2548 temp = (u_long) gus_max_frequency[sc->sc_voices-GUS_MIN_VOICES]; 2549 2550 fc = (unsigned int)(((f << 9L) + (temp >> 1L)) / temp); 2551 2552 fc <<= 1; 2553 2554 2555 /* 2556 * Program the voice frequency, and set it in the voice data record 2557 */ 2558 2559 outb(port+GUS_VOICE_SELECT, (unsigned char) voice); 2560 SELECT_GUS_REG(port, GUSREG_FREQ_CONTROL); 2561 outw(port+GUS_DATA_LOW, fc); 2562 2563 sc->sc_voc[voice].rate = freq; 2564 2565} 2566 2567/* 2568 * Interface to the audio layer - set the recording sampling rate 2569 */ 2570 2571int 2572gusmax_set_in_sr(addr, rate) 2573 void * addr; 2574 u_long rate; 2575{ 2576 register struct ad1848_softc *ac = addr; 2577 register struct gus_softc *sc = ac->parent; 2578 int error; 2579 2580 error = ad1848_set_in_sr(ac, rate); 2581 return (error ? error : gus_set_in_sr(sc, rate)); 2582} 2583 2584 2585int 2586gus_set_in_sr(addr, rate) 2587 void *addr; 2588 u_long rate; 2589{ 2590 register struct gus_softc *sc = addr; 2591 2592 DPRINTF(("gus_set_in_sr called\n")); 2593 2594 sc->sc_irate = rate; 2595 2596 return 0; 2597} 2598/* 2599 * Set the sample rate of the recording frequency. Formula is from the GUS 2600 * SDK. Called at splgus(). 2601 */ 2602 2603STATIC void 2604gus_set_recrate(sc, rate) 2605 struct gus_softc *sc; 2606 u_long rate; 2607{ 2608 register int port = sc->sc_iobase; 2609 u_char realrate; 2610 DPRINTF(("gus_set_recrate %lu\n", rate)); 2611 2612#if 0 2613 realrate = 9878400/(16*(rate+2)); /* formula from GUS docs */ 2614#endif 2615 realrate = (9878400 >> 4)/rate - 2; /* formula from code, sigh. */ 2616 2617 SELECT_GUS_REG(port, GUSREG_SAMPLE_FREQ); 2618 outb(port+GUS_DATA_HIGH, realrate); 2619} 2620 2621/* 2622 * Interface to the audio layer - turn the output on or off. Note that some 2623 * of these bits are flipped in the register 2624 */ 2625 2626int 2627gusmax_speaker_ctl(addr, newstate) 2628 void * addr; 2629 int newstate; 2630{ 2631 register struct ad1848_softc *sc = addr; 2632 return gus_speaker_ctl(sc->parent, newstate); 2633} 2634 2635int 2636gus_speaker_ctl(addr, newstate) 2637 void * addr; 2638 int newstate; 2639{ 2640 register struct gus_softc *sc = (struct gus_softc *) addr; 2641 2642 /* Line out bit is flipped: 0 enables, 1 disables */ 2643 if ((newstate == SPKR_ON) && 2644 (sc->sc_mixcontrol & GUSMASK_LINE_OUT)) { 2645 sc->sc_mixcontrol &= ~GUSMASK_LINE_OUT; 2646 outb(sc->sc_iobase+GUS_MIX_CONTROL, sc->sc_mixcontrol); 2647 } 2648 if ((newstate == SPKR_OFF) && 2649 (sc->sc_mixcontrol & GUSMASK_LINE_OUT) == 0) { 2650 sc->sc_mixcontrol |= GUSMASK_LINE_OUT; 2651 outb(sc->sc_iobase+GUS_MIX_CONTROL, sc->sc_mixcontrol); 2652 } 2653 2654 return 0; 2655} 2656 2657STATIC int 2658gus_linein_ctl(addr, newstate) 2659 void * addr; 2660 int newstate; 2661{ 2662 register struct gus_softc *sc = (struct gus_softc *) addr; 2663 2664 /* Line in bit is flipped: 0 enables, 1 disables */ 2665 if ((newstate == SPKR_ON) && 2666 (sc->sc_mixcontrol & GUSMASK_LINE_IN)) { 2667 sc->sc_mixcontrol &= ~GUSMASK_LINE_IN; 2668 outb(sc->sc_iobase+GUS_MIX_CONTROL, sc->sc_mixcontrol); 2669 } 2670 if ((newstate == SPKR_OFF) && 2671 (sc->sc_mixcontrol & GUSMASK_LINE_IN) == 0) { 2672 sc->sc_mixcontrol |= GUSMASK_LINE_IN; 2673 outb(sc->sc_iobase+GUS_MIX_CONTROL, sc->sc_mixcontrol); 2674 } 2675 2676 return 0; 2677} 2678 2679STATIC int 2680gus_mic_ctl(addr, newstate) 2681 void * addr; 2682 int newstate; 2683{ 2684 register struct gus_softc *sc = (struct gus_softc *) addr; 2685 2686 /* Mic bit is normal: 1 enables, 0 disables */ 2687 if ((newstate == SPKR_ON) && 2688 (sc->sc_mixcontrol & GUSMASK_MIC_IN) == 0) { 2689 sc->sc_mixcontrol |= GUSMASK_MIC_IN; 2690 outb(sc->sc_iobase+GUS_MIX_CONTROL, sc->sc_mixcontrol); 2691 } 2692 if ((newstate == SPKR_OFF) && 2693 (sc->sc_mixcontrol & GUSMASK_MIC_IN)) { 2694 sc->sc_mixcontrol &= ~GUSMASK_MIC_IN; 2695 outb(sc->sc_iobase+GUS_MIX_CONTROL, sc->sc_mixcontrol); 2696 } 2697 2698 return 0; 2699} 2700 2701/* 2702 * Set the end address of a give voice. Called at splgus() 2703 */ 2704 2705STATIC void 2706gus_set_endaddr(sc, voice, addr) 2707 struct gus_softc *sc; 2708 int voice; 2709 u_long addr; 2710{ 2711 register int port = sc->sc_iobase; 2712 2713 sc->sc_voc[voice].end_addr = addr; 2714 2715 if (sc->sc_voc[voice].voccntl & GUSMASK_DATA_SIZE16) 2716 addr = convert_to_16bit(addr); 2717 2718 SELECT_GUS_REG(port, GUSREG_END_ADDR_HIGH); 2719 outw(port+GUS_DATA_LOW, ADDR_HIGH(addr)); 2720 SELECT_GUS_REG(port, GUSREG_END_ADDR_LOW); 2721 outw(port+GUS_DATA_LOW, ADDR_LOW(addr)); 2722 2723} 2724 2725#ifdef GUSPLAYDEBUG 2726/* 2727 * Set current address. called at splgus() 2728 */ 2729STATIC void 2730gus_set_curaddr(sc, voice, addr) 2731 struct gus_softc *sc; 2732 int voice; 2733 u_long addr; 2734{ 2735 register int port = sc->sc_iobase; 2736 2737 sc->sc_voc[voice].current_addr = addr; 2738 2739 if (sc->sc_voc[voice].voccntl & GUSMASK_DATA_SIZE16) 2740 addr = convert_to_16bit(addr); 2741 2742 outb(port+GUS_VOICE_SELECT, (unsigned char) voice); 2743 2744 SELECT_GUS_REG(port, GUSREG_CUR_ADDR_HIGH); 2745 outw(port+GUS_DATA_LOW, ADDR_HIGH(addr)); 2746 SELECT_GUS_REG(port, GUSREG_CUR_ADDR_LOW); 2747 outw(port+GUS_DATA_LOW, ADDR_LOW(addr)); 2748 2749} 2750 2751/* 2752 * Get current GUS playback address. Called at splgus(). 2753 */ 2754STATIC u_long 2755gus_get_curaddr(sc, voice) 2756 struct gus_softc *sc; 2757 int voice; 2758{ 2759 register int port = sc->sc_iobase; 2760 u_long addr; 2761 2762 outb(port+GUS_VOICE_SELECT, (unsigned char) voice); 2763 SELECT_GUS_REG(port, GUSREG_CUR_ADDR_HIGH|GUSREG_READ); 2764 addr = (inw(port+GUS_DATA_LOW) & 0x1fff) << 7; 2765 SELECT_GUS_REG(port, GUSREG_CUR_ADDR_LOW|GUSREG_READ); 2766 addr |= (inw(port+GUS_DATA_LOW) >> 9L) & 0x7f; 2767 2768 if (sc->sc_voc[voice].voccntl & GUSMASK_DATA_SIZE16) 2769 addr = (addr & 0xc0000) | ((addr & 0x1ffff) << 1); /* undo 16-bit change */ 2770 DPRINTF(("gus voice %d curaddr %d end_addr %d\n", 2771 voice, addr, sc->sc_voc[voice].end_addr)); 2772 /* XXX sanity check the address? */ 2773 2774 return(addr); 2775} 2776#endif 2777 2778/* 2779 * Convert an address value to a "16 bit" value - why this is necessary I 2780 * have NO idea 2781 */ 2782 2783STATIC u_long 2784convert_to_16bit(address) 2785 u_long address; 2786{ 2787 u_long old_address; 2788 2789 old_address = address; 2790 address >>= 1; 2791 address &= 0x0001ffffL; 2792 address |= (old_address & 0x000c0000L); 2793 2794 return (address); 2795} 2796 2797/* 2798 * Write a value into the GUS's DRAM 2799 */ 2800 2801STATIC void 2802guspoke(port, address, value) 2803 int port; 2804 long address; 2805 unsigned char value; 2806{ 2807 2808 /* 2809 * Select the DRAM address 2810 */ 2811 2812 SELECT_GUS_REG(port, GUSREG_DRAM_ADDR_LOW); 2813 outw(port+GUS_DATA_LOW, (unsigned int) (address & 0xffff)); 2814 SELECT_GUS_REG(port, GUSREG_DRAM_ADDR_HIGH); 2815 outb(port+GUS_DATA_HIGH, (unsigned char) ((address >> 16) & 0xff)); 2816 2817 /* 2818 * Actually write the data 2819 */ 2820 2821 outb(port+GUS_DRAM_DATA, value); 2822} 2823 2824/* 2825 * Read a value from the GUS's DRAM 2826 */ 2827 2828STATIC unsigned char 2829guspeek(port, address) 2830 int port; 2831 u_long address; 2832{ 2833 2834 /* 2835 * Select the DRAM address 2836 */ 2837 2838 SELECT_GUS_REG(port, GUSREG_DRAM_ADDR_LOW); 2839 outw(port+GUS_DATA_LOW, (unsigned int) (address & 0xffff)); 2840 SELECT_GUS_REG(port, GUSREG_DRAM_ADDR_HIGH); 2841 outb(port+GUS_DATA_HIGH, (unsigned char) ((address >> 16) & 0xff)); 2842 2843 /* 2844 * Read in the data from the board 2845 */ 2846 2847 return (unsigned char) inb(port+GUS_DRAM_DATA); 2848} 2849 2850/* 2851 * Reset the Gravis UltraSound card, completely 2852 */ 2853 2854STATIC void 2855gusreset(sc, voices) 2856 struct gus_softc *sc; 2857 int voices; 2858{ 2859 register int port = sc->sc_iobase; 2860 int i,s; 2861 2862 s = splgus(); 2863 2864 /* 2865 * Reset the GF1 chip 2866 */ 2867 2868 SELECT_GUS_REG(port, GUSREG_RESET); 2869 outb(port+GUS_DATA_HIGH, 0x00); 2870 2871 delay(500); 2872 2873 /* 2874 * Release reset 2875 */ 2876 2877 SELECT_GUS_REG(port, GUSREG_RESET); 2878 outb(port+GUS_DATA_HIGH, GUSMASK_MASTER_RESET); 2879 2880 delay(500); 2881 2882 /* 2883 * Reset MIDI port as well 2884 */ 2885 2886 outb(GUS_MIDI_CONTROL,MIDI_RESET); 2887 2888 delay(500); 2889 2890 outb(GUS_MIDI_CONTROL,0x00); 2891 2892 /* 2893 * Clear interrupts 2894 */ 2895 2896 SELECT_GUS_REG(port, GUSREG_DMA_CONTROL); 2897 outb(port+GUS_DATA_HIGH, 0x00); 2898 SELECT_GUS_REG(port, GUSREG_TIMER_CONTROL); 2899 outb(port+GUS_DATA_HIGH, 0x00); 2900 SELECT_GUS_REG(port, GUSREG_SAMPLE_CONTROL); 2901 outb(port+GUS_DATA_HIGH, 0x00); 2902 2903 gus_set_voices(sc, voices); 2904 2905 inb(port+GUS_IRQ_STATUS); 2906 SELECT_GUS_REG(port, GUSREG_DMA_CONTROL); 2907 inb(port+GUS_DATA_HIGH); 2908 SELECT_GUS_REG(port, GUSREG_SAMPLE_CONTROL); 2909 inb(port+GUS_DATA_HIGH); 2910 SELECT_GUS_REG(port, GUSREG_IRQ_STATUS); 2911 inb(port+GUS_DATA_HIGH); 2912 2913 /* 2914 * Reset voice specific information 2915 */ 2916 2917 for(i = 0; i < voices; i++) { 2918 outb(port+GUS_VOICE_SELECT, (unsigned char) i); 2919 2920 SELECT_GUS_REG(port, GUSREG_VOICE_CNTL); 2921 2922 sc->sc_voc[i].voccntl = GUSMASK_VOICE_STOPPED | 2923 GUSMASK_STOP_VOICE; 2924 2925 outb(port+GUS_DATA_HIGH, sc->sc_voc[i].voccntl); 2926 2927 sc->sc_voc[i].volcntl = GUSMASK_VOLUME_STOPPED | 2928 GUSMASK_STOP_VOLUME; 2929 2930 SELECT_GUS_REG(port, GUSREG_VOLUME_CONTROL); 2931 outb(port+GUS_DATA_HIGH, sc->sc_voc[i].volcntl); 2932 2933 delay(100); 2934 2935 gus_set_samprate(sc, i, 8000); 2936 SELECT_GUS_REG(port, GUSREG_START_ADDR_HIGH); 2937 outw(port+GUS_DATA_LOW, 0x0000); 2938 SELECT_GUS_REG(port, GUSREG_START_ADDR_LOW); 2939 outw(port+GUS_DATA_LOW, 0x0000); 2940 SELECT_GUS_REG(port, GUSREG_END_ADDR_HIGH); 2941 outw(port+GUS_DATA_LOW, 0x0000); 2942 SELECT_GUS_REG(port, GUSREG_END_ADDR_LOW); 2943 outw(port+GUS_DATA_LOW, 0x0000); 2944 SELECT_GUS_REG(port, GUSREG_VOLUME_RATE); 2945 outb(port+GUS_DATA_HIGH, 0x01); 2946 SELECT_GUS_REG(port, GUSREG_START_VOLUME); 2947 outb(port+GUS_DATA_HIGH, 0x10); 2948 SELECT_GUS_REG(port, GUSREG_END_VOLUME); 2949 outb(port+GUS_DATA_HIGH, 0xe0); 2950 SELECT_GUS_REG(port, GUSREG_CUR_VOLUME); 2951 outw(port+GUS_DATA_LOW, 0x0000); 2952 2953 SELECT_GUS_REG(port, GUSREG_CUR_ADDR_HIGH); 2954 outw(port+GUS_DATA_LOW, 0x0000); 2955 SELECT_GUS_REG(port, GUSREG_CUR_ADDR_LOW); 2956 outw(port+GUS_DATA_LOW, 0x0000); 2957 SELECT_GUS_REG(port, GUSREG_PAN_POS); 2958 outb(port+GUS_DATA_HIGH, 0x07); 2959 } 2960 2961 /* 2962 * Clear out any pending IRQs 2963 */ 2964 2965 inb(port+GUS_IRQ_STATUS); 2966 SELECT_GUS_REG(port, GUSREG_DMA_CONTROL); 2967 inb(port+GUS_DATA_HIGH); 2968 SELECT_GUS_REG(port, GUSREG_SAMPLE_CONTROL); 2969 inb(port+GUS_DATA_HIGH); 2970 SELECT_GUS_REG(port, GUSREG_IRQ_STATUS); 2971 inb(port+GUS_DATA_HIGH); 2972 2973 SELECT_GUS_REG(port, GUSREG_RESET); 2974 outb(port+GUS_DATA_HIGH, GUSMASK_MASTER_RESET | GUSMASK_DAC_ENABLE | 2975 GUSMASK_IRQ_ENABLE); 2976 2977 splx(s); 2978} 2979 2980 2981STATIC void 2982gus_init_cs4231(sc) 2983 struct gus_softc *sc; 2984{ 2985 register int port = sc->sc_iobase; 2986 u_char ctrl; 2987 2988 ctrl = (port & 0xf0) >> 4; /* set port address middle nibble */ 2989 /* 2990 * The codec is a bit weird--swapped dma channels. 2991 */ 2992 ctrl |= GUS_MAX_CODEC_ENABLE; 2993 if (sc->sc_drq >= 4) 2994 ctrl |= GUS_MAX_RECCHAN16; 2995 if (sc->sc_recdrq >= 4) 2996 ctrl |= GUS_MAX_PLAYCHAN16; 2997 2998 outb(port+GUS_MAX_CTRL, ctrl); 2999 3000 sc->sc_codec.sc_iobase = port+GUS_MAX_CODEC_BASE; 3001 3002 if (ad1848_probe(&sc->sc_codec) == 0) { 3003 sc->sc_flags &= ~GUS_CODEC_INSTALLED; 3004 } else { 3005 struct ad1848_volume vol = {AUDIO_MAX_GAIN, AUDIO_MAX_GAIN}; 3006 struct audio_hw_if gusmax_hw_if = { 3007 gusopen, 3008 gusmax_close, 3009 NULL, /* drain */ 3010 gusmax_set_in_sr, 3011 gusmax_get_in_sr, 3012 gusmax_set_out_sr, 3013 gusmax_get_out_sr, 3014 3015 ad1848_query_encoding, /* query encoding */ 3016 gusmax_set_encoding, 3017 gusmax_get_encoding, 3018 3019 gusmax_set_precision, 3020 gusmax_get_precision, 3021 3022 gusmax_set_channels, 3023 gusmax_get_channels, 3024 3025 gusmax_round_blocksize, 3026 3027 gusmax_set_out_port, 3028 gusmax_get_out_port, 3029 gusmax_set_in_port, 3030 gusmax_get_in_port, 3031 3032 gusmax_commit_settings, 3033 3034 gusmax_expand, /* XXX use codec */ 3035 mulaw_compress, 3036 3037 gusmax_dma_output, 3038 gusmax_dma_input, 3039 gusmax_halt_out_dma, 3040 gusmax_halt_in_dma, 3041 gusmax_cont_out_dma, 3042 gusmax_cont_in_dma, 3043 3044 gusmax_speaker_ctl, 3045 3046 gus_getdev, 3047 gus_setfd, 3048 gusmax_mixer_set_port, 3049 gusmax_mixer_get_port, 3050 gusmax_mixer_query_devinfo, 3051 1, /* full-duplex */ 3052 0, 3053 }; 3054 sc->sc_flags |= GUS_CODEC_INSTALLED; 3055 sc->sc_codec.parent = sc; 3056 sc->sc_codec.sc_drq = sc->sc_recdrq; 3057 sc->sc_codec.sc_recdrq = sc->sc_drq; 3058 gus_hw_if = gusmax_hw_if; 3059 /* enable line in and mic in the GUS mixer; the codec chip 3060 will do the real mixing for them. */ 3061 sc->sc_mixcontrol &= ~GUSMASK_LINE_IN; /* 0 enables. */ 3062 sc->sc_mixcontrol |= GUSMASK_MIC_IN; /* 1 enables. */ 3063 outb(sc->sc_iobase+GUS_MIX_CONTROL, sc->sc_mixcontrol); 3064 3065 ad1848_attach(&sc->sc_codec); 3066 /* turn on pre-MUX microphone gain. */ 3067 ad1848_set_mic_gain(&sc->sc_codec, &vol); 3068 } 3069} 3070 3071 3072/* 3073 * Return info about the audio device, for the AUDIO_GETINFO ioctl 3074 */ 3075 3076int 3077gus_getdev(addr, dev) 3078 void * addr; 3079 struct audio_device *dev; 3080{ 3081 *dev = gus_device; 3082 return 0; 3083} 3084 3085/* 3086 * stubs (XXX) 3087 */ 3088 3089int 3090gus_set_in_gain(addr, gain, balance) 3091 caddr_t addr; 3092 u_int gain; 3093 u_char balance; 3094{ 3095 DPRINTF(("gus_set_in_gain called\n")); 3096 return 0; 3097} 3098 3099int 3100gus_get_in_gain(addr) 3101 caddr_t addr; 3102{ 3103 DPRINTF(("gus_get_in_gain called\n")); 3104 return 0; 3105} 3106 3107int 3108gusmax_set_out_port(addr, port) 3109 void * addr; 3110 int port; 3111{ 3112 register struct ad1848_softc *sc = addr; 3113 return gus_set_out_port(sc->parent, port); 3114} 3115 3116int 3117gus_set_out_port(addr, port) 3118 void * addr; 3119 int port; 3120{ 3121 register struct gus_softc *sc = addr; 3122 DPRINTF(("gus_set_out_port called\n")); 3123 sc->sc_out_port = port; 3124 3125 return 0; 3126} 3127 3128int 3129gusmax_get_out_port(addr) 3130 void * addr; 3131{ 3132 register struct ad1848_softc *sc = addr; 3133 return gus_get_out_port(sc->parent); 3134} 3135 3136int 3137gus_get_out_port(addr) 3138 void * addr; 3139{ 3140 register struct gus_softc *sc = addr; 3141 DPRINTF(("gus_get_out_port() called\n")); 3142 return sc->sc_out_port; 3143} 3144 3145int 3146gusmax_set_in_port(addr, port) 3147 void * addr; 3148 int port; 3149{ 3150 register struct ad1848_softc *sc = addr; 3151 DPRINTF(("gusmax_set_in_port: %d\n", port)); 3152 3153 switch(port) { 3154 case GUSMAX_MONO_LVL: 3155 port = MIC_IN_PORT; 3156 break; 3157 case GUSMAX_LINE_IN_LVL: 3158 port = LINE_IN_PORT; 3159 break; 3160 case GUSMAX_DAC_LVL: 3161 port = AUX1_IN_PORT; 3162 break; 3163 case GUSMAX_MIX_IN: 3164 port = DAC_IN_PORT; 3165 break; 3166 default: 3167 return(EINVAL); 3168 /*NOTREACHED*/ 3169 } 3170 return(ad1848_set_rec_port(sc, port)); 3171} 3172 3173int 3174gusmax_get_in_port(addr) 3175 void * addr; 3176{ 3177 register struct ad1848_softc *sc = addr; 3178 int port = GUSMAX_MONO_LVL; 3179 3180 switch(ad1848_get_rec_port(sc)) { 3181 case MIC_IN_PORT: 3182 port = GUSMAX_MONO_LVL; 3183 break; 3184 case LINE_IN_PORT: 3185 port = GUSMAX_LINE_IN_LVL; 3186 break; 3187 case DAC_IN_PORT: 3188 port = GUSMAX_MIX_IN; 3189 break; 3190 case AUX1_IN_PORT: 3191 port = GUSMAX_DAC_LVL; 3192 break; 3193 } 3194 3195 DPRINTF(("gusmax_get_in_port: %d\n", port)); 3196 3197 return(port); 3198} 3199 3200int 3201gus_set_in_port(addr, port) 3202 void * addr; 3203 int port; 3204{ 3205 register struct gus_softc *sc = addr; 3206 DPRINTF(("gus_set_in_port called\n")); 3207 /* 3208 * On the GUS with ICS mixer, the ADC input is after the mixer stage, 3209 * so we can't set the input port. 3210 * 3211 * On the GUS with CS4231 codec/mixer, see gusmax_set_in_port(). 3212 */ 3213 sc->sc_in_port = port; 3214 3215 return 0; 3216} 3217 3218 3219int 3220gus_get_in_port(addr) 3221 void * addr; 3222{ 3223 register struct gus_softc *sc = addr; 3224 DPRINTF(("gus_get_in_port called\n")); 3225 return sc->sc_in_port; 3226} 3227 3228 3229int 3230gusmax_dma_input(addr, buf, size, callback, arg) 3231 void * addr; 3232 void *buf; 3233 int size; 3234 void (*callback) __P((void *)); 3235 void *arg; 3236{ 3237 register struct ad1848_softc *sc = addr; 3238 return gus_dma_input(sc->parent, buf, size, callback, arg); 3239} 3240 3241/* 3242 * Start sampling the input source into the requested DMA buffer. 3243 * Called at splgus(), either from top-half or from interrupt handler. 3244 */ 3245int 3246gus_dma_input(addr, buf, size, callback, arg) 3247 void * addr; 3248 void *buf; 3249 int size; 3250 void (*callback) __P((void *)); 3251 void *arg; 3252{ 3253 register struct gus_softc *sc = addr; 3254 register int port = sc->sc_iobase; 3255 register u_char dmac; 3256 DMAPRINTF(("gus_dma_input called\n")); 3257 3258 /* 3259 * Sample SIZE bytes of data from the card, into buffer at BUF. 3260 */ 3261 3262 if (sc->sc_precision == 16) 3263 return EINVAL; /* XXX */ 3264 3265 /* set DMA modes */ 3266 dmac = GUSMASK_SAMPLE_IRQ|GUSMASK_SAMPLE_START; 3267 if (sc->sc_recdrq >= 4) 3268 dmac |= GUSMASK_SAMPLE_DATA16; 3269 if (sc->sc_encoding == AUDIO_ENCODING_ULAW || 3270 sc->sc_encoding == AUDIO_ENCODING_PCM8) 3271 dmac |= GUSMASK_SAMPLE_INVBIT; 3272 if (sc->sc_channels == 2) 3273 dmac |= GUSMASK_SAMPLE_STEREO; 3274 isa_dmastart(DMAMODE_READ, (caddr_t) buf, size, sc->sc_recdrq); 3275 3276 DMAPRINTF(("gus_dma_input isa_dmastarted\n")); 3277 sc->sc_flags |= GUS_DMAIN_ACTIVE; 3278 sc->sc_dmainintr = callback; 3279 sc->sc_inarg = arg; 3280 sc->sc_dmaincnt = size; 3281 sc->sc_dmainaddr = buf; 3282 3283 SELECT_GUS_REG(port, GUSREG_SAMPLE_CONTROL); 3284 outb(port+GUS_DATA_HIGH, dmac); /* Go! */ 3285 3286 3287 DMAPRINTF(("gus_dma_input returning\n")); 3288 3289 return 0; 3290} 3291 3292STATIC int 3293gus_dmain_intr(sc) 3294 struct gus_softc *sc; 3295{ 3296 void (*callback) __P((void *)); 3297 void *arg; 3298 3299 DMAPRINTF(("gus_dmain_intr called\n")); 3300 if (sc->sc_dmainintr) { 3301 isa_dmadone(DMAMODE_READ, sc->sc_dmainaddr, sc->sc_dmaincnt - 1, 3302 sc->sc_recdrq); 3303 callback = sc->sc_dmainintr; 3304 arg = sc->sc_inarg; 3305 3306 sc->sc_dmainaddr = 0; 3307 sc->sc_dmaincnt = 0; 3308 sc->sc_dmainintr = 0; 3309 sc->sc_inarg = 0; 3310 3311 sc->sc_flags &= ~GUS_DMAIN_ACTIVE; 3312 DMAPRINTF(("calling dmain_intr callback %x(%x)\n", callback, arg)); 3313 (*callback)(arg); 3314 return 1; 3315 } else { 3316 DMAPRINTF(("gus_dmain_intr false?\n")); 3317 return 0; /* XXX ??? */ 3318 } 3319} 3320 3321int 3322gusmax_halt_out_dma(addr) 3323 void * addr; 3324{ 3325 register struct ad1848_softc *sc = addr; 3326 return gus_halt_out_dma(sc->parent); 3327} 3328 3329 3330int 3331gusmax_halt_in_dma(addr) 3332 void * addr; 3333{ 3334 register struct ad1848_softc *sc = addr; 3335 return gus_halt_in_dma(sc->parent); 3336} 3337 3338int 3339gusmax_cont_out_dma(addr) 3340 void * addr; 3341{ 3342 register struct ad1848_softc *sc = addr; 3343 return gus_cont_out_dma(sc->parent); 3344} 3345 3346int 3347gusmax_cont_in_dma(addr) 3348 void * addr; 3349{ 3350 register struct ad1848_softc *sc = addr; 3351 return gus_cont_in_dma(sc->parent); 3352} 3353 3354/* 3355 * Stop any DMA output. Called at splgus(). 3356 */ 3357int 3358gus_halt_out_dma(addr) 3359 void * addr; 3360{ 3361 register struct gus_softc *sc = addr; 3362 register int port = sc->sc_iobase; 3363 3364 DMAPRINTF(("gus_halt_out_dma called\n")); 3365 /* 3366 * Make sure the GUS _isn't_ setup for DMA 3367 */ 3368 3369 SELECT_GUS_REG(port, GUSREG_DMA_CONTROL); 3370 outb(sc->sc_iobase+GUS_DATA_HIGH, 0); 3371 3372 untimeout(gus_dmaout_timeout, sc); 3373 isa_dmaabort(sc->sc_drq); 3374 sc->sc_flags &= ~(GUS_DMAOUT_ACTIVE|GUS_LOCKED); 3375 sc->sc_dmaoutintr = 0; 3376 sc->sc_outarg = 0; 3377 sc->sc_dmaoutaddr = 0; 3378 sc->sc_dmaoutcnt = 0; 3379 sc->sc_dmabuf = 0; 3380 sc->sc_bufcnt = 0; 3381 sc->sc_playbuf = -1; 3382 /* also stop playing */ 3383 gus_stop_voice(sc, GUS_VOICE_LEFT, 1); 3384 gus_stop_voice(sc, GUS_VOICE_RIGHT, 0); 3385 3386 return 0; 3387} 3388 3389/* 3390 * Stop any DMA output. Called at splgus(). 3391 */ 3392int 3393gus_halt_in_dma(addr) 3394 void * addr; 3395{ 3396 register struct gus_softc *sc = addr; 3397 register int port = sc->sc_iobase; 3398 DMAPRINTF(("gus_halt_in_dma called\n")); 3399 3400 /* 3401 * Make sure the GUS _isn't_ setup for DMA 3402 */ 3403 3404 SELECT_GUS_REG(port, GUSREG_SAMPLE_CONTROL); 3405 outb(port+GUS_DATA_HIGH, 3406 inb(port+GUS_DATA_HIGH) & ~(GUSMASK_SAMPLE_START|GUSMASK_SAMPLE_IRQ)); 3407 3408 isa_dmaabort(sc->sc_recdrq); 3409 sc->sc_flags &= ~GUS_DMAIN_ACTIVE; 3410 sc->sc_dmainintr = 0; 3411 sc->sc_inarg = 0; 3412 sc->sc_dmainaddr = 0; 3413 sc->sc_dmaincnt = 0; 3414 3415 return 0; 3416} 3417 3418int 3419gus_cont_out_dma(addr) 3420 void * addr; 3421{ 3422 DPRINTF(("gus_cont_out_dma called\n")); 3423 return EOPNOTSUPP; 3424} 3425 3426int 3427gus_cont_in_dma(addr) 3428 void * addr; 3429{ 3430 DPRINTF(("gus_cont_in_dma called\n")); 3431 return EOPNOTSUPP; 3432} 3433 3434 3435STATIC int 3436gus_setfd(addr, flag) 3437 void *addr; 3438 int flag; 3439{ 3440 if (gus_hw_if.full_duplex == 0) 3441 return ENOTTY; 3442 3443 return(0); /* nothing fancy to do. */ 3444} 3445 3446STATIC __inline int 3447gus_to_vol(cp, vol) 3448 mixer_ctrl_t *cp; 3449 struct ad1848_volume *vol; 3450{ 3451 if (cp->un.value.num_channels == 1) { 3452 vol->left = vol->right = cp->un.value.level[AUDIO_MIXER_LEVEL_MONO]; 3453 return(1); 3454 } 3455 else if (cp->un.value.num_channels == 2) { 3456 vol->left = cp->un.value.level[AUDIO_MIXER_LEVEL_LEFT]; 3457 vol->right = cp->un.value.level[AUDIO_MIXER_LEVEL_RIGHT]; 3458 return(1); 3459 } 3460 return(0); 3461} 3462 3463STATIC __inline int 3464gus_from_vol(cp, vol) 3465 mixer_ctrl_t *cp; 3466 struct ad1848_volume *vol; 3467{ 3468 if (cp->un.value.num_channels == 1) { 3469 cp->un.value.level[AUDIO_MIXER_LEVEL_MONO] = vol->left; 3470 return(1); 3471 } 3472 else if (cp->un.value.num_channels == 2) { 3473 cp->un.value.level[AUDIO_MIXER_LEVEL_LEFT] = vol->left; 3474 cp->un.value.level[AUDIO_MIXER_LEVEL_RIGHT] = vol->right; 3475 return(1); 3476 } 3477 return(0); 3478} 3479 3480STATIC int 3481gusmax_mixer_get_port(addr, cp) 3482 void *addr; 3483 mixer_ctrl_t *cp; 3484{ 3485 register struct ad1848_softc *ac = addr; 3486 register struct gus_softc *sc = ac->parent; 3487 struct ad1848_volume vol; 3488 int error = EINVAL; 3489 3490 DPRINTF(("gusmax_mixer_get_port: port=%d\n", cp->dev)); 3491 3492 switch (cp->dev) { 3493#if 0 /* use mono level instead */ 3494 case GUSMAX_MIC_IN_LVL: /* Microphone */ 3495 if (cp->type == AUDIO_MIXER_VALUE) { 3496 error = ad1848_get_mic_gain(ac, &vol); 3497 if (!error) 3498 gus_from_vol(cp, &vol); 3499 } 3500 break; 3501#endif 3502 3503 case GUSMAX_DAC_LVL: /* dac out */ 3504 if (cp->type == AUDIO_MIXER_VALUE) { 3505 error = ad1848_get_aux1_gain(ac, &vol); 3506 if (!error) 3507 gus_from_vol(cp, &vol); 3508 } 3509 break; 3510 3511 case GUSMAX_LINE_IN_LVL: /* line in */ 3512 if (cp->type == AUDIO_MIXER_VALUE) { 3513 error = cs4231_get_linein_gain(ac, &vol); 3514 if (!error) 3515 gus_from_vol(cp, &vol); 3516 } 3517 break; 3518 3519 case GUSMAX_MONO_LVL: /* mono */ 3520 if (cp->type == AUDIO_MIXER_VALUE && 3521 cp->un.value.num_channels == 1) { 3522 error = cs4231_get_mono_gain(ac, &vol); 3523 if (!error) 3524 gus_from_vol(cp, &vol); 3525 } 3526 break; 3527 3528 case GUSMAX_CD_LVL: /* CD */ 3529 if (cp->type == AUDIO_MIXER_VALUE) { 3530 error = ad1848_get_aux2_gain(ac, &vol); 3531 if (!error) 3532 gus_from_vol(cp, &vol); 3533 } 3534 break; 3535 3536 case GUSMAX_MONITOR_LVL: /* monitor level */ 3537 if (cp->type == AUDIO_MIXER_VALUE && 3538 cp->un.value.num_channels == 1) { 3539 error = ad1848_get_mon_gain(ac, &vol); 3540 if (!error) 3541 cp->un.value.level[AUDIO_MIXER_LEVEL_MONO] = 3542 vol.left; 3543 } 3544 break; 3545 3546 case GUSMAX_OUT_LVL: /* output level */ 3547 if (cp->type == AUDIO_MIXER_VALUE) { 3548 error = ad1848_get_out_gain(ac, &vol); 3549 if (!error) 3550 gus_from_vol(cp, &vol); 3551 } 3552 break; 3553 3554 case GUSMAX_SPEAKER_LVL: /* fake speaker for mute naming */ 3555 if (cp->type == AUDIO_MIXER_VALUE) { 3556 if (sc->sc_mixcontrol & GUSMASK_LINE_OUT) 3557 vol.left = vol.right = AUDIO_MAX_GAIN; 3558 else 3559 vol.left = vol.right = AUDIO_MIN_GAIN; 3560 error = 0; 3561 gus_from_vol(cp, &vol); 3562 } 3563 break; 3564 3565 case GUSMAX_LINE_IN_MUTE: 3566 if (cp->type == AUDIO_MIXER_ENUM) { 3567 cp->un.ord = ac->line_mute; 3568 error = 0; 3569 } 3570 break; 3571 3572 3573 case GUSMAX_DAC_MUTE: 3574 if (cp->type == AUDIO_MIXER_ENUM) { 3575 cp->un.ord = ac->aux1_mute; 3576 error = 0; 3577 } 3578 break; 3579 3580 case GUSMAX_CD_MUTE: 3581 if (cp->type == AUDIO_MIXER_ENUM) { 3582 cp->un.ord = ac->aux2_mute; 3583 error = 0; 3584 } 3585 break; 3586 3587 case GUSMAX_MONO_MUTE: 3588 if (cp->type == AUDIO_MIXER_ENUM) { 3589 cp->un.ord = ac->mono_mute; 3590 error = 0; 3591 } 3592 break; 3593 3594 case GUSMAX_MONITOR_MUTE: 3595 if (cp->type == AUDIO_MIXER_ENUM) { 3596 cp->un.ord = ac->mon_mute; 3597 error = 0; 3598 } 3599 break; 3600 3601 case GUSMAX_SPEAKER_MUTE: 3602 if (cp->type == AUDIO_MIXER_ENUM) { 3603 cp->un.ord = sc->sc_mixcontrol & GUSMASK_LINE_OUT ? 1 : 0; 3604 error = 0; 3605 } 3606 break; 3607 3608 case GUSMAX_REC_LVL: /* record level */ 3609 if (cp->type == AUDIO_MIXER_VALUE) { 3610 error = ad1848_get_rec_gain(ac, &vol); 3611 if (!error) 3612 gus_from_vol(cp, &vol); 3613 } 3614 break; 3615 3616 case GUSMAX_RECORD_SOURCE: 3617 if (cp->type == AUDIO_MIXER_ENUM) { 3618 cp->un.ord = ad1848_get_rec_port(ac); 3619 error = 0; 3620 } 3621 break; 3622 3623 default: 3624 error = ENXIO; 3625 break; 3626 } 3627 3628 return(error); 3629} 3630 3631STATIC int 3632gus_mixer_get_port(addr, cp) 3633 void *addr; 3634 mixer_ctrl_t *cp; 3635{ 3636 register struct gus_softc *sc = addr; 3637 register struct ics2101_softc *ic = &sc->sc_mixer; 3638 struct ad1848_volume vol; 3639 int error = EINVAL; 3640 3641 DPRINTF(("gus_mixer_get_port: dev=%d type=%d\n", cp->dev, cp->type)); 3642 3643 if (!HAS_MIXER(sc) && cp->dev > GUSICS_MASTER_MUTE) 3644 return ENXIO; 3645 3646 switch (cp->dev) { 3647 3648 case GUSICS_MIC_IN_MUTE: /* Microphone */ 3649 if (cp->type == AUDIO_MIXER_ENUM) { 3650 if (HAS_MIXER(sc)) 3651 cp->un.ord = ic->sc_mute[GUSMIX_CHAN_MIC][ICSMIX_LEFT]; 3652 else 3653 cp->un.ord = 3654 sc->sc_mixcontrol & GUSMASK_MIC_IN ? 0 : 1; 3655 error = 0; 3656 } 3657 break; 3658 3659 case GUSICS_LINE_IN_MUTE: 3660 if (cp->type == AUDIO_MIXER_ENUM) { 3661 if (HAS_MIXER(sc)) 3662 cp->un.ord = ic->sc_mute[GUSMIX_CHAN_LINE][ICSMIX_LEFT]; 3663 else 3664 cp->un.ord = 3665 sc->sc_mixcontrol & GUSMASK_LINE_IN ? 1 : 0; 3666 error = 0; 3667 } 3668 break; 3669 3670 case GUSICS_MASTER_MUTE: 3671 if (cp->type == AUDIO_MIXER_ENUM) { 3672 if (HAS_MIXER(sc)) 3673 cp->un.ord = ic->sc_mute[GUSMIX_CHAN_MASTER][ICSMIX_LEFT]; 3674 else 3675 cp->un.ord = 3676 sc->sc_mixcontrol & GUSMASK_LINE_OUT ? 1 : 0; 3677 error = 0; 3678 } 3679 break; 3680 3681 case GUSICS_DAC_MUTE: 3682 if (cp->type == AUDIO_MIXER_ENUM) { 3683 cp->un.ord = ic->sc_mute[GUSMIX_CHAN_DAC][ICSMIX_LEFT]; 3684 error = 0; 3685 } 3686 break; 3687 3688 case GUSICS_CD_MUTE: 3689 if (cp->type == AUDIO_MIXER_ENUM) { 3690 cp->un.ord = ic->sc_mute[GUSMIX_CHAN_CD][ICSMIX_LEFT]; 3691 error = 0; 3692 } 3693 break; 3694 3695 case GUSICS_MASTER_LVL: 3696 if (cp->type == AUDIO_MIXER_VALUE) { 3697 vol.left = ic->sc_setting[GUSMIX_CHAN_MASTER][ICSMIX_LEFT]; 3698 vol.right = ic->sc_setting[GUSMIX_CHAN_MASTER][ICSMIX_RIGHT]; 3699 if (gus_from_vol(cp, &vol)) 3700 error = 0; 3701 } 3702 break; 3703 3704 case GUSICS_MIC_IN_LVL: /* Microphone */ 3705 if (cp->type == AUDIO_MIXER_VALUE) { 3706 vol.left = ic->sc_setting[GUSMIX_CHAN_MIC][ICSMIX_LEFT]; 3707 vol.right = ic->sc_setting[GUSMIX_CHAN_MIC][ICSMIX_RIGHT]; 3708 if (gus_from_vol(cp, &vol)) 3709 error = 0; 3710 } 3711 break; 3712 3713 case GUSICS_LINE_IN_LVL: /* line in */ 3714 if (cp->type == AUDIO_MIXER_VALUE) { 3715 vol.left = ic->sc_setting[GUSMIX_CHAN_LINE][ICSMIX_LEFT]; 3716 vol.right = ic->sc_setting[GUSMIX_CHAN_LINE][ICSMIX_RIGHT]; 3717 if (gus_from_vol(cp, &vol)) 3718 error = 0; 3719 } 3720 break; 3721 3722 3723 case GUSICS_CD_LVL: 3724 if (cp->type == AUDIO_MIXER_VALUE) { 3725 vol.left = ic->sc_setting[GUSMIX_CHAN_CD][ICSMIX_LEFT]; 3726 vol.right = ic->sc_setting[GUSMIX_CHAN_CD][ICSMIX_RIGHT]; 3727 if (gus_from_vol(cp, &vol)) 3728 error = 0; 3729 } 3730 break; 3731 3732 case GUSICS_DAC_LVL: /* dac out */ 3733 if (cp->type == AUDIO_MIXER_VALUE) { 3734 vol.left = ic->sc_setting[GUSMIX_CHAN_DAC][ICSMIX_LEFT]; 3735 vol.right = ic->sc_setting[GUSMIX_CHAN_DAC][ICSMIX_RIGHT]; 3736 if (gus_from_vol(cp, &vol)) 3737 error = 0; 3738 } 3739 break; 3740 3741 3742 case GUSICS_RECORD_SOURCE: 3743 if (cp->type == AUDIO_MIXER_ENUM) { 3744 /* Can't set anything else useful, sigh. */ 3745 cp->un.ord = 0; 3746 } 3747 break; 3748 3749 default: 3750 return ENXIO; 3751 /*NOTREACHED*/ 3752 } 3753 return error; 3754} 3755 3756STATIC void 3757gusics_master_mute(ic, mute) 3758 struct ics2101_softc *ic; 3759 int mute; 3760{ 3761 ics2101_mix_mute(ic, GUSMIX_CHAN_MASTER, ICSMIX_LEFT, mute); 3762 ics2101_mix_mute(ic, GUSMIX_CHAN_MASTER, ICSMIX_RIGHT, mute); 3763} 3764 3765STATIC void 3766gusics_mic_mute(ic, mute) 3767 struct ics2101_softc *ic; 3768 int mute; 3769{ 3770 ics2101_mix_mute(ic, GUSMIX_CHAN_MIC, ICSMIX_LEFT, mute); 3771 ics2101_mix_mute(ic, GUSMIX_CHAN_MIC, ICSMIX_RIGHT, mute); 3772} 3773 3774STATIC void 3775gusics_linein_mute(ic, mute) 3776 struct ics2101_softc *ic; 3777 int mute; 3778{ 3779 ics2101_mix_mute(ic, GUSMIX_CHAN_LINE, ICSMIX_LEFT, mute); 3780 ics2101_mix_mute(ic, GUSMIX_CHAN_LINE, ICSMIX_RIGHT, mute); 3781} 3782 3783STATIC void 3784gusics_cd_mute(ic, mute) 3785 struct ics2101_softc *ic; 3786 int mute; 3787{ 3788 ics2101_mix_mute(ic, GUSMIX_CHAN_CD, ICSMIX_LEFT, mute); 3789 ics2101_mix_mute(ic, GUSMIX_CHAN_CD, ICSMIX_RIGHT, mute); 3790} 3791 3792STATIC void 3793gusics_dac_mute(ic, mute) 3794 struct ics2101_softc *ic; 3795 int mute; 3796{ 3797 ics2101_mix_mute(ic, GUSMIX_CHAN_DAC, ICSMIX_LEFT, mute); 3798 ics2101_mix_mute(ic, GUSMIX_CHAN_DAC, ICSMIX_RIGHT, mute); 3799} 3800 3801STATIC int 3802gusmax_mixer_set_port(addr, cp) 3803 void *addr; 3804 mixer_ctrl_t *cp; 3805{ 3806 register struct ad1848_softc *ac = addr; 3807 register struct gus_softc *sc = ac->parent; 3808 struct ad1848_volume vol; 3809 int error = EINVAL; 3810 3811 DPRINTF(("gusmax_mixer_set_port: dev=%d type=%d\n", cp->dev, cp->type)); 3812 3813 switch (cp->dev) { 3814#if 0 3815 case GUSMAX_MIC_IN_LVL: /* Microphone */ 3816 if (cp->type == AUDIO_MIXER_VALUE && 3817 cp->un.value.num_channels == 1) { 3818 /* XXX enable/disable pre-MUX fixed gain */ 3819 if (gus_to_vol(cp, &vol)) 3820 error = ad1848_set_mic_gain(ac, &vol); 3821 } 3822 break; 3823#endif 3824 3825 case GUSMAX_DAC_LVL: /* dac out */ 3826 if (cp->type == AUDIO_MIXER_VALUE) { 3827 if (gus_to_vol(cp, &vol)) 3828 error = ad1848_set_aux1_gain(ac, &vol); 3829 } 3830 break; 3831 3832 case GUSMAX_LINE_IN_LVL: /* line in */ 3833 if (cp->type == AUDIO_MIXER_VALUE) { 3834 if (gus_to_vol(cp, &vol)) 3835 error = cs4231_set_linein_gain(ac, &vol); 3836 } 3837 break; 3838 3839 case GUSMAX_MONO_LVL: /* mic/mono in */ 3840 if (cp->type == AUDIO_MIXER_VALUE && 3841 cp->un.value.num_channels == 1) { 3842 if (gus_to_vol(cp, &vol)) 3843 error = cs4231_set_mono_gain(ac, &vol); 3844 } 3845 break; 3846 3847 case GUSMAX_CD_LVL: /* CD: AUX2 */ 3848 if (cp->type == AUDIO_MIXER_VALUE) { 3849 if (gus_to_vol(cp, &vol)) 3850 error = ad1848_set_aux2_gain(ac, &vol); 3851 } 3852 break; 3853 3854 case GUSMAX_MONITOR_LVL: 3855 if (cp->type == AUDIO_MIXER_VALUE && 3856 cp->un.value.num_channels == 1) { 3857 vol.left = cp->un.value.level[AUDIO_MIXER_LEVEL_MONO]; 3858 error = ad1848_set_mon_gain(ac, &vol); 3859 } 3860 break; 3861 3862 case GUSMAX_OUT_LVL: /* output volume */ 3863 if (cp->type == AUDIO_MIXER_VALUE) { 3864 if (gus_to_vol(cp, &vol)) 3865 error = ad1848_set_out_gain(ac, &vol); 3866 } 3867 break; 3868 3869 case GUSMAX_SPEAKER_LVL: 3870 if (cp->type == AUDIO_MIXER_VALUE && 3871 cp->un.value.num_channels == 1) { 3872 if (gus_to_vol(cp, &vol)) { 3873 gus_speaker_ctl(sc, vol.left > AUDIO_MIN_GAIN ? 3874 SPKR_ON : SPKR_OFF); 3875 error = 0; 3876 } 3877 } 3878 break; 3879 3880 case GUSMAX_LINE_IN_MUTE: 3881 if (cp->type == AUDIO_MIXER_ENUM) { 3882 ac->line_mute = cp->un.ord ? 1 : 0; 3883 DPRINTF(("line mute %d\n", cp->un.ord)); 3884 cs4231_mute_line(ac, ac->line_mute); 3885 gus_linein_ctl(sc, ac->line_mute ? SPKR_OFF : SPKR_ON); 3886 error = 0; 3887 } 3888 break; 3889 3890 case GUSMAX_DAC_MUTE: 3891 if (cp->type == AUDIO_MIXER_ENUM) { 3892 ac->aux1_mute = cp->un.ord ? 1 : 0; 3893 DPRINTF(("dac mute %d\n", cp->un.ord)); 3894 ad1848_mute_aux1(ac, ac->aux1_mute); 3895 error = 0; 3896 } 3897 break; 3898 3899 case GUSMAX_CD_MUTE: 3900 if (cp->type == AUDIO_MIXER_ENUM) { 3901 ac->aux2_mute = cp->un.ord ? 1 : 0; 3902 DPRINTF(("cd mute %d\n", cp->un.ord)); 3903 ad1848_mute_aux2(ac, ac->aux2_mute); 3904 error = 0; 3905 } 3906 break; 3907 3908 case GUSMAX_MONO_MUTE: /* Microphone */ 3909 if (cp->type == AUDIO_MIXER_ENUM) { 3910 ac->mono_mute = cp->un.ord ? 1 : 0; 3911 DPRINTF(("mono mute %d\n", cp->un.ord)); 3912 cs4231_mute_mono(ac, ac->mono_mute); 3913 gus_mic_ctl(sc, ac->mono_mute ? SPKR_OFF : SPKR_ON); 3914 error = 0; 3915 } 3916 break; 3917 3918 case GUSMAX_MONITOR_MUTE: 3919 if (cp->type == AUDIO_MIXER_ENUM) { 3920 ac->mon_mute = cp->un.ord ? 1 : 0; 3921 DPRINTF(("mono mute %d\n", cp->un.ord)); 3922 cs4231_mute_monitor(ac, ac->mon_mute); 3923 error = 0; 3924 } 3925 break; 3926 3927 case GUSMAX_SPEAKER_MUTE: 3928 if (cp->type == AUDIO_MIXER_ENUM) { 3929 gus_speaker_ctl(sc, cp->un.ord ? SPKR_OFF : SPKR_ON); 3930 error = 0; 3931 } 3932 break; 3933 3934 case GUSMAX_REC_LVL: /* record level */ 3935 if (cp->type == AUDIO_MIXER_VALUE) { 3936 if (gus_to_vol(cp, &vol)) 3937 error = ad1848_set_rec_gain(ac, &vol); 3938 } 3939 break; 3940 3941 case GUSMAX_RECORD_SOURCE: 3942 if (cp->type == AUDIO_MIXER_ENUM) { 3943 error = ad1848_set_rec_port(ac, cp->un.ord); 3944 } 3945 break; 3946 3947 default: 3948 return ENXIO; 3949 /*NOTREACHED*/ 3950 } 3951 return error; 3952} 3953 3954STATIC int 3955gus_mixer_set_port(addr, cp) 3956 void *addr; 3957 mixer_ctrl_t *cp; 3958{ 3959 register struct gus_softc *sc = addr; 3960 register struct ics2101_softc *ic = &sc->sc_mixer; 3961 struct ad1848_volume vol; 3962 int error = EINVAL; 3963 3964 DPRINTF(("gus_mixer_set_port: dev=%d type=%d\n", cp->dev, cp->type)); 3965 3966 if (!HAS_MIXER(sc) && cp->dev > GUSICS_MASTER_MUTE) 3967 return ENXIO; 3968 3969 switch (cp->dev) { 3970 3971 case GUSICS_MIC_IN_MUTE: /* Microphone */ 3972 if (cp->type == AUDIO_MIXER_ENUM) { 3973 DPRINTF(("mic mute %d\n", cp->un.ord)); 3974 if (HAS_MIXER(sc)) { 3975 gusics_mic_mute(ic, cp->un.ord); 3976 } 3977 gus_mic_ctl(sc, cp->un.ord ? SPKR_OFF : SPKR_ON); 3978 error = 0; 3979 } 3980 break; 3981 3982 case GUSICS_LINE_IN_MUTE: 3983 if (cp->type == AUDIO_MIXER_ENUM) { 3984 DPRINTF(("linein mute %d\n", cp->un.ord)); 3985 if (HAS_MIXER(sc)) { 3986 gusics_linein_mute(ic, cp->un.ord); 3987 } 3988 gus_linein_ctl(sc, cp->un.ord ? SPKR_OFF : SPKR_ON); 3989 error = 0; 3990 } 3991 break; 3992 3993 case GUSICS_MASTER_MUTE: 3994 if (cp->type == AUDIO_MIXER_ENUM) { 3995 DPRINTF(("master mute %d\n", cp->un.ord)); 3996 if (HAS_MIXER(sc)) { 3997 gusics_master_mute(ic, cp->un.ord); 3998 } 3999 gus_speaker_ctl(sc, cp->un.ord ? SPKR_OFF : SPKR_ON); 4000 error = 0; 4001 } 4002 break; 4003 4004 case GUSICS_DAC_MUTE: 4005 if (cp->type == AUDIO_MIXER_ENUM) { 4006 gusics_dac_mute(ic, cp->un.ord); 4007 error = 0; 4008 } 4009 break; 4010 4011 case GUSICS_CD_MUTE: 4012 if (cp->type == AUDIO_MIXER_ENUM) { 4013 gusics_cd_mute(ic, cp->un.ord); 4014 error = 0; 4015 } 4016 break; 4017 4018 case GUSICS_MASTER_LVL: 4019 if (cp->type == AUDIO_MIXER_VALUE) { 4020 if (gus_to_vol(cp, &vol)) { 4021 ics2101_mix_attenuate(ic, 4022 GUSMIX_CHAN_MASTER, 4023 ICSMIX_LEFT, 4024 vol.left); 4025 ics2101_mix_attenuate(ic, 4026 GUSMIX_CHAN_MASTER, 4027 ICSMIX_RIGHT, 4028 vol.right); 4029 error = 0; 4030 } 4031 } 4032 break; 4033 4034 case GUSICS_MIC_IN_LVL: /* Microphone */ 4035 if (cp->type == AUDIO_MIXER_VALUE) { 4036 if (gus_to_vol(cp, &vol)) { 4037 ics2101_mix_attenuate(ic, 4038 GUSMIX_CHAN_MIC, 4039 ICSMIX_LEFT, 4040 vol.left); 4041 ics2101_mix_attenuate(ic, 4042 GUSMIX_CHAN_MIC, 4043 ICSMIX_RIGHT, 4044 vol.right); 4045 error = 0; 4046 } 4047 } 4048 break; 4049 4050 case GUSICS_LINE_IN_LVL: /* line in */ 4051 if (cp->type == AUDIO_MIXER_VALUE) { 4052 if (gus_to_vol(cp, &vol)) { 4053 ics2101_mix_attenuate(ic, 4054 GUSMIX_CHAN_LINE, 4055 ICSMIX_LEFT, 4056 vol.left); 4057 ics2101_mix_attenuate(ic, 4058 GUSMIX_CHAN_LINE, 4059 ICSMIX_RIGHT, 4060 vol.right); 4061 error = 0; 4062 } 4063 } 4064 break; 4065 4066 4067 case GUSICS_CD_LVL: 4068 if (cp->type == AUDIO_MIXER_VALUE) { 4069 if (gus_to_vol(cp, &vol)) { 4070 ics2101_mix_attenuate(ic, 4071 GUSMIX_CHAN_CD, 4072 ICSMIX_LEFT, 4073 vol.left); 4074 ics2101_mix_attenuate(ic, 4075 GUSMIX_CHAN_CD, 4076 ICSMIX_RIGHT, 4077 vol.right); 4078 error = 0; 4079 } 4080 } 4081 break; 4082 4083 case GUSICS_DAC_LVL: /* dac out */ 4084 if (cp->type == AUDIO_MIXER_VALUE) { 4085 if (gus_to_vol(cp, &vol)) { 4086 ics2101_mix_attenuate(ic, 4087 GUSMIX_CHAN_DAC, 4088 ICSMIX_LEFT, 4089 vol.left); 4090 ics2101_mix_attenuate(ic, 4091 GUSMIX_CHAN_DAC, 4092 ICSMIX_RIGHT, 4093 vol.right); 4094 error = 0; 4095 } 4096 } 4097 break; 4098 4099 4100 case GUSICS_RECORD_SOURCE: 4101 if (cp->type == AUDIO_MIXER_ENUM && cp->un.ord == 0) { 4102 /* Can't set anything else useful, sigh. */ 4103 error = 0; 4104 } 4105 break; 4106 4107 default: 4108 return ENXIO; 4109 /*NOTREACHED*/ 4110 } 4111 return error; 4112} 4113 4114STATIC int 4115gusmax_mixer_query_devinfo(addr, dip) 4116 void *addr; 4117 register mixer_devinfo_t *dip; 4118{ 4119 DPRINTF(("gusmax_query_devinfo: index=%d\n", dip->index)); 4120 4121 switch(dip->index) { 4122 case GUSMAX_MIX_IN: /* mixed MUX input */ 4123 dip->type = AUDIO_MIXER_ENUM; 4124 dip->mixer_class = GUSMAX_INPUT_CLASS; 4125 dip->prev = dip->next = AUDIO_MIXER_LAST; 4126 strcpy(dip->label.name, AudioNmixerout); 4127 dip->un.e.num_mem = 0; /* XXX */ 4128 break; 4129 4130#if 0 4131 case GUSMAX_MIC_IN_LVL: /* Microphone */ 4132 dip->type = AUDIO_MIXER_VALUE; 4133 dip->mixer_class = GUSMAX_INPUT_CLASS; 4134 dip->prev = AUDIO_MIXER_LAST; 4135 dip->next = GUSMAX_MIC_IN_MUTE; 4136 strcpy(dip->label.name, AudioNmicrophone); 4137 dip->un.v.num_channels = 2; 4138 strcpy(dip->un.v.units.name, AudioNvolume); 4139 break; 4140#endif 4141 4142 case GUSMAX_MONO_LVL: /* mono/microphone mixer */ 4143 dip->type = AUDIO_MIXER_VALUE; 4144 dip->mixer_class = GUSMAX_INPUT_CLASS; 4145 dip->prev = AUDIO_MIXER_LAST; 4146 dip->next = GUSMAX_MONO_MUTE; 4147 strcpy(dip->label.name, AudioNmicrophone); 4148 dip->un.v.num_channels = 1; 4149 strcpy(dip->un.v.units.name, AudioNvolume); 4150 break; 4151 4152 case GUSMAX_DAC_LVL: /* dacout */ 4153 dip->type = AUDIO_MIXER_VALUE; 4154 dip->mixer_class = GUSMAX_INPUT_CLASS; 4155 dip->prev = AUDIO_MIXER_LAST; 4156 dip->next = GUSMAX_DAC_MUTE; 4157 strcpy(dip->label.name, AudioNdac); 4158 dip->un.v.num_channels = 2; 4159 strcpy(dip->un.v.units.name, AudioNvolume); 4160 break; 4161 4162 case GUSMAX_LINE_IN_LVL: /* line */ 4163 dip->type = AUDIO_MIXER_VALUE; 4164 dip->mixer_class = GUSMAX_INPUT_CLASS; 4165 dip->prev = AUDIO_MIXER_LAST; 4166 dip->next = GUSMAX_LINE_IN_MUTE; 4167 strcpy(dip->label.name, AudioNline); 4168 dip->un.v.num_channels = 2; 4169 strcpy(dip->un.v.units.name, AudioNvolume); 4170 break; 4171 4172 case GUSMAX_CD_LVL: /* cd */ 4173 dip->type = AUDIO_MIXER_VALUE; 4174 dip->mixer_class = GUSMAX_INPUT_CLASS; 4175 dip->prev = AUDIO_MIXER_LAST; 4176 dip->next = GUSMAX_CD_MUTE; 4177 strcpy(dip->label.name, AudioNcd); 4178 dip->un.v.num_channels = 2; 4179 strcpy(dip->un.v.units.name, AudioNvolume); 4180 break; 4181 4182 4183 case GUSMAX_MONITOR_LVL: /* monitor level */ 4184 dip->type = AUDIO_MIXER_VALUE; 4185 dip->mixer_class = GUSMAX_MONITOR_CLASS; 4186 dip->next = GUSMAX_MONITOR_MUTE; 4187 dip->prev = AUDIO_MIXER_LAST; 4188 strcpy(dip->label.name, AudioNmonitor); 4189 dip->un.v.num_channels = 1; 4190 strcpy(dip->un.v.units.name, AudioNvolume); 4191 break; 4192 4193 case GUSMAX_OUT_LVL: /* cs4231 output volume: not useful? */ 4194 dip->type = AUDIO_MIXER_VALUE; 4195 dip->mixer_class = GUSMAX_MONITOR_CLASS; 4196 dip->prev = dip->next = AUDIO_MIXER_LAST; 4197 strcpy(dip->label.name, AudioNoutput); 4198 dip->un.v.num_channels = 2; 4199 strcpy(dip->un.v.units.name, AudioNvolume); 4200 break; 4201 4202 case GUSMAX_SPEAKER_LVL: /* fake speaker volume */ 4203 dip->type = AUDIO_MIXER_VALUE; 4204 dip->mixer_class = GUSMAX_MONITOR_CLASS; 4205 dip->prev = AUDIO_MIXER_LAST; 4206 dip->next = GUSMAX_SPEAKER_MUTE; 4207 strcpy(dip->label.name, AudioNspeaker); 4208 dip->un.v.num_channels = 2; 4209 strcpy(dip->un.v.units.name, AudioNvolume); 4210 break; 4211 4212 case GUSMAX_LINE_IN_MUTE: 4213 dip->mixer_class = GUSMAX_INPUT_CLASS; 4214 dip->type = AUDIO_MIXER_ENUM; 4215 dip->prev = GUSMAX_LINE_IN_LVL; 4216 dip->next = AUDIO_MIXER_LAST; 4217 goto mute; 4218 4219 case GUSMAX_DAC_MUTE: 4220 dip->mixer_class = GUSMAX_INPUT_CLASS; 4221 dip->type = AUDIO_MIXER_ENUM; 4222 dip->prev = GUSMAX_DAC_LVL; 4223 dip->next = AUDIO_MIXER_LAST; 4224 goto mute; 4225 4226 case GUSMAX_CD_MUTE: 4227 dip->mixer_class = GUSMAX_INPUT_CLASS; 4228 dip->type = AUDIO_MIXER_ENUM; 4229 dip->prev = GUSMAX_CD_LVL; 4230 dip->next = AUDIO_MIXER_LAST; 4231 goto mute; 4232 4233 case GUSMAX_MONO_MUTE: 4234 dip->mixer_class = GUSMAX_INPUT_CLASS; 4235 dip->type = AUDIO_MIXER_ENUM; 4236 dip->prev = GUSMAX_MONO_LVL; 4237 dip->next = AUDIO_MIXER_LAST; 4238 goto mute; 4239 4240 case GUSMAX_MONITOR_MUTE: 4241 dip->mixer_class = GUSMAX_OUTPUT_CLASS; 4242 dip->type = AUDIO_MIXER_ENUM; 4243 dip->prev = GUSMAX_MONITOR_LVL; 4244 dip->next = AUDIO_MIXER_LAST; 4245 goto mute; 4246 4247 case GUSMAX_SPEAKER_MUTE: 4248 dip->mixer_class = GUSMAX_OUTPUT_CLASS; 4249 dip->type = AUDIO_MIXER_ENUM; 4250 dip->prev = GUSMAX_SPEAKER_LVL; 4251 dip->next = AUDIO_MIXER_LAST; 4252 mute: 4253 strcpy(dip->label.name, AudioNmute); 4254 dip->un.e.num_mem = 2; 4255 strcpy(dip->un.e.member[0].label.name, AudioNoff); 4256 dip->un.e.member[0].ord = 0; 4257 strcpy(dip->un.e.member[1].label.name, AudioNon); 4258 dip->un.e.member[1].ord = 1; 4259 break; 4260 4261 case GUSMAX_REC_LVL: /* record level */ 4262 dip->type = AUDIO_MIXER_VALUE; 4263 dip->mixer_class = GUSMAX_RECORD_CLASS; 4264 dip->prev = AUDIO_MIXER_LAST; 4265 dip->next = GUSMAX_RECORD_SOURCE; 4266 strcpy(dip->label.name, AudioNrecord); 4267 dip->un.v.num_channels = 2; 4268 strcpy(dip->un.v.units.name, AudioNvolume); 4269 break; 4270 4271 case GUSMAX_RECORD_SOURCE: 4272 dip->mixer_class = GUSMAX_RECORD_CLASS; 4273 dip->type = AUDIO_MIXER_ENUM; 4274 dip->prev = GUSMAX_REC_LVL; 4275 dip->next = AUDIO_MIXER_LAST; 4276 strcpy(dip->label.name, AudioNsource); 4277 dip->un.e.num_mem = 4; 4278 strcpy(dip->un.e.member[0].label.name, AudioNoutput); 4279 dip->un.e.member[0].ord = GUSMAX_MIX_IN; 4280 strcpy(dip->un.e.member[1].label.name, AudioNmicrophone); 4281 dip->un.e.member[1].ord = GUSMAX_MONO_LVL; 4282 strcpy(dip->un.e.member[2].label.name, AudioNdac); 4283 dip->un.e.member[2].ord = GUSMAX_DAC_LVL; 4284 strcpy(dip->un.e.member[3].label.name, AudioNline); 4285 dip->un.e.member[3].ord = GUSMAX_LINE_IN_LVL; 4286 break; 4287 4288 case GUSMAX_INPUT_CLASS: /* input class descriptor */ 4289 dip->type = AUDIO_MIXER_CLASS; 4290 dip->mixer_class = GUSMAX_INPUT_CLASS; 4291 dip->next = dip->prev = AUDIO_MIXER_LAST; 4292 strcpy(dip->label.name, AudioCInputs); 4293 break; 4294 4295 case GUSMAX_OUTPUT_CLASS: /* output class descriptor */ 4296 dip->type = AUDIO_MIXER_CLASS; 4297 dip->mixer_class = GUSMAX_OUTPUT_CLASS; 4298 dip->next = dip->prev = AUDIO_MIXER_LAST; 4299 strcpy(dip->label.name, AudioCOutputs); 4300 break; 4301 4302 case GUSMAX_MONITOR_CLASS: /* monitor class descriptor */ 4303 dip->type = AUDIO_MIXER_CLASS; 4304 dip->mixer_class = GUSMAX_MONITOR_CLASS; 4305 dip->next = dip->prev = AUDIO_MIXER_LAST; 4306 strcpy(dip->label.name, AudioCMonitor); 4307 break; 4308 4309 case GUSMAX_RECORD_CLASS: /* record source class */ 4310 dip->type = AUDIO_MIXER_CLASS; 4311 dip->mixer_class = GUSMAX_RECORD_CLASS; 4312 dip->next = dip->prev = AUDIO_MIXER_LAST; 4313 strcpy(dip->label.name, AudioCRecord); 4314 break; 4315 4316 default: 4317 return ENXIO; 4318 /*NOTREACHED*/ 4319 } 4320 DPRINTF(("AUDIO_MIXER_DEVINFO: name=%s\n", dip->label.name)); 4321 return 0; 4322} 4323 4324STATIC int 4325gus_mixer_query_devinfo(addr, dip) 4326 void *addr; 4327 register mixer_devinfo_t *dip; 4328{ 4329 register struct gus_softc *sc = addr; 4330 4331 DPRINTF(("gusmax_query_devinfo: index=%d\n", dip->index)); 4332 4333 if (!HAS_MIXER(sc) && dip->index > GUSICS_MASTER_MUTE) 4334 return ENXIO; 4335 4336 switch(dip->index) { 4337 4338 case GUSICS_MIC_IN_LVL: /* Microphone */ 4339 dip->type = AUDIO_MIXER_VALUE; 4340 dip->mixer_class = GUSICS_INPUT_CLASS; 4341 dip->prev = AUDIO_MIXER_LAST; 4342 dip->next = GUSICS_MIC_IN_MUTE; 4343 strcpy(dip->label.name, AudioNmicrophone); 4344 dip->un.v.num_channels = 2; 4345 strcpy(dip->un.v.units.name, AudioNvolume); 4346 break; 4347 4348 case GUSICS_LINE_IN_LVL: /* line */ 4349 dip->type = AUDIO_MIXER_VALUE; 4350 dip->mixer_class = GUSICS_INPUT_CLASS; 4351 dip->prev = AUDIO_MIXER_LAST; 4352 dip->next = GUSICS_LINE_IN_MUTE; 4353 strcpy(dip->label.name, AudioNline); 4354 dip->un.v.num_channels = 2; 4355 strcpy(dip->un.v.units.name, AudioNvolume); 4356 break; 4357 4358 case GUSICS_CD_LVL: /* cd */ 4359 dip->type = AUDIO_MIXER_VALUE; 4360 dip->mixer_class = GUSICS_INPUT_CLASS; 4361 dip->prev = AUDIO_MIXER_LAST; 4362 dip->next = GUSICS_CD_MUTE; 4363 strcpy(dip->label.name, AudioNcd); 4364 dip->un.v.num_channels = 2; 4365 strcpy(dip->un.v.units.name, AudioNvolume); 4366 break; 4367 4368 case GUSICS_DAC_LVL: /* dacout */ 4369 dip->type = AUDIO_MIXER_VALUE; 4370 dip->mixer_class = GUSICS_INPUT_CLASS; 4371 dip->prev = AUDIO_MIXER_LAST; 4372 dip->next = GUSICS_DAC_MUTE; 4373 strcpy(dip->label.name, AudioNdac); 4374 dip->un.v.num_channels = 2; 4375 strcpy(dip->un.v.units.name, AudioNvolume); 4376 break; 4377 4378 case GUSICS_MASTER_LVL: /* master output */ 4379 dip->type = AUDIO_MIXER_VALUE; 4380 dip->mixer_class = GUSICS_OUTPUT_CLASS; 4381 dip->prev = AUDIO_MIXER_LAST; 4382 dip->next = GUSICS_MASTER_MUTE; 4383 strcpy(dip->label.name, AudioNvolume); 4384 dip->un.v.num_channels = 2; 4385 strcpy(dip->un.v.units.name, AudioNvolume); 4386 break; 4387 4388 4389 case GUSICS_LINE_IN_MUTE: 4390 dip->mixer_class = GUSICS_INPUT_CLASS; 4391 dip->type = AUDIO_MIXER_ENUM; 4392 dip->prev = GUSICS_LINE_IN_LVL; 4393 dip->next = AUDIO_MIXER_LAST; 4394 goto mute; 4395 4396 case GUSICS_DAC_MUTE: 4397 dip->mixer_class = GUSICS_INPUT_CLASS; 4398 dip->type = AUDIO_MIXER_ENUM; 4399 dip->prev = GUSICS_DAC_LVL; 4400 dip->next = AUDIO_MIXER_LAST; 4401 goto mute; 4402 4403 case GUSICS_CD_MUTE: 4404 dip->mixer_class = GUSICS_INPUT_CLASS; 4405 dip->type = AUDIO_MIXER_ENUM; 4406 dip->prev = GUSICS_CD_LVL; 4407 dip->next = AUDIO_MIXER_LAST; 4408 goto mute; 4409 4410 case GUSICS_MIC_IN_MUTE: 4411 dip->mixer_class = GUSICS_INPUT_CLASS; 4412 dip->type = AUDIO_MIXER_ENUM; 4413 dip->prev = GUSICS_MIC_IN_LVL; 4414 dip->next = AUDIO_MIXER_LAST; 4415 goto mute; 4416 4417 case GUSICS_MASTER_MUTE: 4418 dip->mixer_class = GUSICS_OUTPUT_CLASS; 4419 dip->type = AUDIO_MIXER_ENUM; 4420 dip->prev = GUSICS_MASTER_LVL; 4421 dip->next = AUDIO_MIXER_LAST; 4422mute: 4423 strcpy(dip->label.name, AudioNmute); 4424 dip->un.e.num_mem = 2; 4425 strcpy(dip->un.e.member[0].label.name, AudioNoff); 4426 dip->un.e.member[0].ord = 0; 4427 strcpy(dip->un.e.member[1].label.name, AudioNon); 4428 dip->un.e.member[1].ord = 1; 4429 break; 4430 4431 case GUSICS_RECORD_SOURCE: 4432 dip->mixer_class = GUSICS_RECORD_CLASS; 4433 dip->type = AUDIO_MIXER_ENUM; 4434 dip->prev = dip->next = AUDIO_MIXER_LAST; 4435 strcpy(dip->label.name, AudioNsource); 4436 dip->un.e.num_mem = 1; 4437 strcpy(dip->un.e.member[0].label.name, AudioNoutput); 4438 dip->un.e.member[0].ord = GUSICS_MASTER_LVL; 4439 break; 4440 4441 case GUSICS_INPUT_CLASS: 4442 dip->type = AUDIO_MIXER_CLASS; 4443 dip->mixer_class = GUSICS_INPUT_CLASS; 4444 dip->next = dip->prev = AUDIO_MIXER_LAST; 4445 strcpy(dip->label.name, AudioCInputs); 4446 break; 4447 4448 case GUSICS_OUTPUT_CLASS: 4449 dip->type = AUDIO_MIXER_CLASS; 4450 dip->mixer_class = GUSICS_OUTPUT_CLASS; 4451 dip->next = dip->prev = AUDIO_MIXER_LAST; 4452 strcpy(dip->label.name, AudioCOutputs); 4453 break; 4454 4455 case GUSICS_RECORD_CLASS: 4456 dip->type = AUDIO_MIXER_CLASS; 4457 dip->mixer_class = GUSICS_RECORD_CLASS; 4458 dip->next = dip->prev = AUDIO_MIXER_LAST; 4459 strcpy(dip->label.name, AudioCRecord); 4460 break; 4461 4462 default: 4463 return ENXIO; 4464 /*NOTREACHED*/ 4465 } 4466 DPRINTF(("AUDIO_MIXER_DEVINFO: name=%s\n", dip->label.name)); 4467 return 0; 4468} 4469 4470STATIC int 4471gus_query_encoding(addr, fp) 4472 void *addr; 4473 struct audio_encoding *fp; 4474{ 4475 switch (fp->index) { 4476 case 0: 4477 strcpy(fp->name, AudioEmulaw); 4478 fp->format_id = AUDIO_ENCODING_ULAW; 4479 break; 4480 case 1: 4481 strcpy(fp->name, AudioEpcm16); 4482 fp->format_id = AUDIO_ENCODING_PCM16; 4483 break; 4484 case 2: 4485 strcpy(fp->name, AudioEpcm8); 4486 fp->format_id = AUDIO_ENCODING_PCM8; 4487 break; 4488 default: 4489 return(EINVAL); 4490 /*NOTREACHED*/ 4491 } 4492 return (0); 4493} 4494 4495/* 4496 * Setup the ICS mixer in "transparent" mode: reset everything to a sensible 4497 * level. Levels as suggested by GUS SDK code. 4498 */ 4499 4500STATIC void 4501gus_init_ics2101(sc) 4502 struct gus_softc *sc; 4503{ 4504 register int port = sc->sc_iobase; 4505 register struct ics2101_softc *ic = &sc->sc_mixer; 4506 sc->sc_mixer.sc_selio = port+GUS_MIXER_SELECT; 4507 sc->sc_mixer.sc_dataio = port+GUS_MIXER_DATA; 4508 sc->sc_mixer.sc_flags = (sc->sc_revision == 5) ? ICS_FLIP : 0; 4509 4510 ics2101_mix_attenuate(ic, 4511 GUSMIX_CHAN_MIC, 4512 ICSMIX_LEFT, 4513 ICSMIX_MIN_ATTN); 4514 ics2101_mix_attenuate(ic, 4515 GUSMIX_CHAN_MIC, 4516 ICSMIX_RIGHT, 4517 ICSMIX_MIN_ATTN); 4518 /* 4519 * Start with microphone muted by the mixer... 4520 */ 4521 gusics_mic_mute(ic, 1); 4522 4523 /* ... and enabled by the GUS master mix control */ 4524 gus_mic_ctl(sc, SPKR_ON); 4525 4526 ics2101_mix_attenuate(ic, 4527 GUSMIX_CHAN_LINE, 4528 ICSMIX_LEFT, 4529 ICSMIX_MIN_ATTN); 4530 ics2101_mix_attenuate(ic, 4531 GUSMIX_CHAN_LINE, 4532 ICSMIX_RIGHT, 4533 ICSMIX_MIN_ATTN); 4534 4535 ics2101_mix_attenuate(ic, 4536 GUSMIX_CHAN_CD, 4537 ICSMIX_LEFT, 4538 ICSMIX_MIN_ATTN); 4539 ics2101_mix_attenuate(ic, 4540 GUSMIX_CHAN_CD, 4541 ICSMIX_RIGHT, 4542 ICSMIX_MIN_ATTN); 4543 4544 ics2101_mix_attenuate(ic, 4545 GUSMIX_CHAN_DAC, 4546 ICSMIX_LEFT, 4547 ICSMIX_MIN_ATTN); 4548 ics2101_mix_attenuate(ic, 4549 GUSMIX_CHAN_DAC, 4550 ICSMIX_RIGHT, 4551 ICSMIX_MIN_ATTN); 4552 4553 ics2101_mix_attenuate(ic, 4554 ICSMIX_CHAN_4, 4555 ICSMIX_LEFT, 4556 ICSMIX_MAX_ATTN); 4557 ics2101_mix_attenuate(ic, 4558 ICSMIX_CHAN_4, 4559 ICSMIX_RIGHT, 4560 ICSMIX_MAX_ATTN); 4561 4562 ics2101_mix_attenuate(ic, 4563 GUSMIX_CHAN_MASTER, 4564 ICSMIX_LEFT, 4565 ICSMIX_MIN_ATTN); 4566 ics2101_mix_attenuate(ic, 4567 GUSMIX_CHAN_MASTER, 4568 ICSMIX_RIGHT, 4569 ICSMIX_MIN_ATTN); 4570 /* unmute other stuff: */ 4571 gusics_cd_mute(ic, 0); 4572 gusics_dac_mute(ic, 0); 4573 gusics_linein_mute(ic, 0); 4574 return; 4575} 4576 4577 4578#endif /* NGUS */ 4579