gus.c revision 1.34
1193323Sed/* $NetBSD: gus.c,v 1.34 1997/07/27 23:51:55 augustss Exp $ */ 2193323Sed 3193323Sed/*- 4193323Sed * Copyright (c) 1996 The NetBSD Foundation, Inc. 5193323Sed * All rights reserved. 6193323Sed * 7193323Sed * This code is derived from software contributed to The NetBSD Foundation 8193323Sed * by Ken Hornstein and John Kohl. 9193323Sed * 10193323Sed * Redistribution and use in source and binary forms, with or without 11193323Sed * modification, are permitted provided that the following conditions 12193323Sed * are met: 13193323Sed * 1. Redistributions of source code must retain the above copyright 14193323Sed * notice, this list of conditions and the following disclaimer. 15193323Sed * 2. Redistributions in binary form must reproduce the above copyright 16193323Sed * notice, this list of conditions and the following disclaimer in the 17193323Sed * documentation and/or other materials provided with the distribution. 18193323Sed * 3. All advertising materials mentioning features or use of this software 19193323Sed * must display the following acknowledgement: 20193323Sed * This product includes software developed by the NetBSD 21193323Sed * Foundation, Inc. and its contributors. 22193323Sed * 4. Neither the name of The NetBSD Foundation nor the names of its 23193323Sed * contributors may be used to endorse or promote products derived 24193323Sed * from this software without specific prior written permission. 25193323Sed * 26193323Sed * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 27193323Sed * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 28193323Sed * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 29193323Sed * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE 30193323Sed * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 31193323Sed * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 32193323Sed * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 33193323Sed * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 34193323Sed * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 35193323Sed * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 36193323Sed * POSSIBILITY OF SUCH DAMAGE. 37193323Sed */ 38193323Sed 39193323Sed/* 40193323Sed * 41193323Sed * TODO: 42193323Sed * . figure out why mixer activity while sound is playing causes problems 43193323Sed * (phantom interrupts?) 44193323Sed * . figure out a better deinterleave strategy that avoids sucking up 45193323Sed * CPU, memory and cache bandwidth. (Maybe a special encoding? 46193323Sed * Maybe use the double-speed sampling/hardware deinterleave trick 47193323Sed * from the GUS SDK?) A 486/33 isn't quite fast enough to keep 48193323Sed * up with 44.1kHz 16-bit stereo output without some drop-outs. 49193323Sed * . use CS4231 for 16-bit sampling, for a-law and mu-law playback. 50193323Sed * . actually test full-duplex sampling(recording) and playback. 51193323Sed */ 52193323Sed 53193323Sed/* 54193323Sed * Gravis UltraSound driver 55193323Sed * 56193323Sed * For more detailed information, see the GUS developers' kit 57193323Sed * available on the net at: 58193323Sed * 59193323Sed * ftp://freedom.nmsu.edu/pub/ultrasound/gravis/util/ 60193323Sed * gusdkXXX.zip (developers' kit--get rev 2.22 or later) 61193323Sed * See ultrawrd.doc inside--it's MS Word (ick), but it's the bible 62193323Sed * 63193323Sed */ 64193323Sed 65193323Sed/* 66193323Sed * The GUS Max has a slightly strange set of connections between the CS4231 67193323Sed * and the GF1 and the DMA interconnects. It's set up so that the CS4231 can 68193323Sed * be playing while the GF1 is loading patches from the system. 69193323Sed * 70193323Sed * Here's a recreation of the DMA interconnect diagram: 71193323Sed * 72193323Sed * GF1 73193323Sed * +---------+ digital 74193323Sed * | | record ASIC 75193323Sed * | |--------------+ 76193323Sed * | | | +--------+ 77193323Sed * | | play (dram) | +----+ | | 78193323Sed * | |--------------(------|-\ | | +-+ | 79193323Sed * +---------+ | | >-|----|---|C|--|------ dma chan 1 80193323Sed * | +---|-/ | | +-+ | 81193323Sed * | | +----+ | | | 82193323Sed * | | +----+ | | | 83193323Sed * +---------+ +-+ +--(---|-\ | | | | 84193323Sed * | | play |8| | | >-|----|----+---|------ dma chan 2 85193323Sed * | ---C----|--------|/|------(---|-/ | | | 86193323Sed * | ^ |record |1| | +----+ | | 87193323Sed * | | | /----|6|------+ +--------+ 88193323Sed * | ---+----|--/ +-+ 89193323Sed * +---------+ 90193323Sed * CS4231 8-to-16 bit bus conversion, if needed 91193323Sed * 92193323Sed * 93193323Sed * "C" is an optional combiner. 94193323Sed * 95193323Sed */ 96193323Sed 97193323Sed#include "gus.h" 98193323Sed#if NGUS > 0 99193323Sed 100193323Sed#include <sys/param.h> 101193323Sed#include <sys/systm.h> 102193323Sed#include <sys/errno.h> 103193323Sed#include <sys/ioctl.h> 104193323Sed#include <sys/syslog.h> 105193323Sed#include <sys/device.h> 106193323Sed#include <sys/proc.h> 107193323Sed#include <sys/buf.h> 108193323Sed#include <sys/fcntl.h> 109193323Sed#include <sys/malloc.h> 110193323Sed#include <sys/kernel.h> 111193323Sed 112193323Sed#include <machine/cpu.h> 113193323Sed#include <machine/intr.h> 114193323Sed#include <machine/bus.h> 115193323Sed#include <machine/pio.h> 116193323Sed#include <machine/cpufunc.h> 117193323Sed#include <sys/audioio.h> 118193323Sed#include <dev/audio_if.h> 119193323Sed#include <dev/mulaw.h> 120193323Sed 121193323Sed#include <dev/isa/isavar.h> 122193323Sed#include <dev/isa/isadmavar.h> 123193323Sed#include <i386/isa/icu.h> 124193323Sed 125193323Sed#include <dev/ic/ics2101reg.h> 126193323Sed#include <dev/ic/cs4231reg.h> 127193323Sed#include <dev/ic/ad1848reg.h> 128193323Sed#include <dev/isa/ics2101var.h> 129193323Sed#include <dev/isa/ad1848var.h> 130193323Sed#include <dev/isa/cs4231var.h> 131193323Sed#include "gusreg.h" 132193323Sed 133193323Sed#ifdef AUDIO_DEBUG 134193323Sed#define STATIC /* empty; for debugging symbols */ 135193323Sed#else 136193323Sed#define STATIC static 137193323Sed#endif 138193323Sed 139193323Sed/* 140193323Sed * Software state of a single "voice" on the GUS 141193323Sed */ 142193323Sed 143193323Sedstruct gus_voice { 144193323Sed 145193323Sed /* 146193323Sed * Various control bits 147193323Sed */ 148193323Sed 149193323Sed unsigned char voccntl; /* State of voice control register */ 150193323Sed unsigned char volcntl; /* State of volume control register */ 151193323Sed unsigned char pan_pos; /* Position of volume panning (4 bits) */ 152193323Sed int rate; /* Sample rate of voice being played back */ 153193323Sed 154193323Sed /* 155193323Sed * Address of the voice data into the GUS's DRAM. 20 bits each 156193323Sed */ 157193323Sed 158193323Sed u_long start_addr; /* Starting address of voice data loop area */ 159193323Sed u_long end_addr; /* Ending address of voice data loop */ 160193323Sed u_long current_addr; /* Beginning address of voice data 161193323Sed (start playing here) */ 162193323Sed 163193323Sed /* 164193323Sed * linear volume values for the GUS's volume ramp. 0-511 (9 bits). 165193323Sed * These values must be translated into the logarithmic values using 166193323Sed * gus_log_volumes[] 167193323Sed */ 168193323Sed 169193323Sed int start_volume; /* Starting position of volume ramp */ 170193323Sed int current_volume; /* Current position of volume on volume ramp */ 171193323Sed int end_volume; /* Ending position of volume on volume ramp */ 172193323Sed}; 173193323Sed 174193323Sed/* 175193323Sed * Software state of GUS 176193323Sed */ 177193323Sed 178193323Sedstruct gus_softc { 179193323Sed struct device sc_dev; /* base device */ 180193323Sed struct isadev sc_id; /* ISA device */ 181193323Sed void *sc_ih; /* interrupt vector */ 182193323Sed bus_space_tag_t sc_iot; /* tag */ 183193323Sed bus_space_handle_t sc_ioh; /* handle */ 184193323Sed 185193323Sed int sc_iobase; /* I/O base address */ 186193323Sed int sc_irq; /* IRQ used */ 187193323Sed int sc_drq; /* DMA channel for play */ 188193323Sed int sc_recdrq; /* DMA channel for recording */ 189193323Sed 190193323Sed int sc_flags; /* Various flags about the GUS */ 191193323Sed#define GUS_MIXER_INSTALLED 0x01 /* An ICS mixer is installed */ 192193323Sed#define GUS_LOCKED 0x02 /* GUS is busy doing multi-phase DMA */ 193193323Sed#define GUS_CODEC_INSTALLED 0x04 /* CS4231 installed/MAX */ 194193323Sed#define GUS_PLAYING 0x08 /* GUS is playing a voice */ 195193323Sed#define GUS_DMAOUT_ACTIVE 0x10 /* GUS is busy doing audio DMA */ 196193323Sed#define GUS_DMAIN_ACTIVE 0x20 /* GUS is busy sampling */ 197193323Sed#define GUS_OPEN 0x100 /* GUS is open */ 198193323Sed int sc_dsize; /* Size of GUS DRAM */ 199193323Sed int sc_voices; /* Number of active voices */ 200193323Sed u_char sc_revision; /* Board revision of GUS */ 201193323Sed u_char sc_mixcontrol; /* Value of GUS_MIX_CONTROL register */ 202193323Sed 203193323Sed u_long sc_orate; /* Output sampling rate */ 204193323Sed u_long sc_irate; /* Input sampling rate */ 205193323Sed 206193323Sed int sc_encoding; /* Current data encoding type */ 207193323Sed int sc_precision; /* # of bits of precision */ 208193323Sed int sc_channels; /* Number of active channels */ 209193323Sed int sc_blocksize; /* Current blocksize */ 210193323Sed int sc_chanblocksize; /* Current blocksize for each in-use 211193323Sed channel */ 212193323Sed short sc_nbufs; /* how many on-GUS bufs per-channel */ 213193323Sed short sc_bufcnt; /* how many need to be played */ 214193323Sed void *sc_deintr_buf; /* deinterleave buffer for stereo */ 215193323Sed 216193323Sed int sc_ogain; /* Output gain control */ 217193323Sed u_char sc_out_port; /* Current out port (generic only) */ 218193323Sed u_char sc_in_port; /* keep track of it when no codec */ 219193323Sed 220193323Sed void (*sc_dmaoutintr) __P((void*)); /* DMA completion intr handler */ 221193323Sed void *sc_outarg; /* argument for sc_dmaoutintr() */ 222193323Sed u_char *sc_dmaoutaddr; /* for isa_dmadone */ 223193323Sed u_long sc_gusaddr; /* where did we just put it? */ 224193323Sed int sc_dmaoutcnt; /* for isa_dmadone */ 225193323Sed 226193323Sed void (*sc_dmainintr) __P((void*)); /* DMA completion intr handler */ 227193323Sed void *sc_inarg; /* argument for sc_dmaoutintr() */ 228193323Sed u_char *sc_dmainaddr; /* for isa_dmadone */ 229193323Sed int sc_dmaincnt; /* for isa_dmadone */ 230193323Sed 231193323Sed struct stereo_dma_intr { 232193323Sed void (*intr)__P((void *)); 233193323Sed void *arg; 234193323Sed u_char *buffer; 235193323Sed u_long dmabuf; 236193323Sed int size; 237193323Sed int flags; 238193323Sed } sc_stereo; 239193323Sed 240193323Sed /* 241193323Sed * State information for linear audio layer 242193323Sed */ 243193323Sed 244193323Sed int sc_dmabuf; /* Which ring buffer we're DMA'ing to */ 245193323Sed int sc_playbuf; /* Which ring buffer we're playing */ 246193323Sed 247193323Sed /* 248193323Sed * Voice information array. All voice-specific information is stored 249193323Sed * here 250193323Sed */ 251193323Sed 252193323Sed struct gus_voice sc_voc[32]; /* Voice data for each voice */ 253193323Sed union { 254193323Sed struct ics2101_softc sc_mixer_u; 255193323Sed struct ad1848_softc sc_codec_u; 256193323Sed } u; 257193323Sed#define sc_mixer u.sc_mixer_u 258193323Sed#define sc_codec u.sc_codec_u 259193323Sed}; 260193323Sed 261193323Sedstruct ics2101_volume { 262193323Sed u_char left; 263193323Sed u_char right; 264193323Sed}; 265193323Sed 266193323Sed#define HAS_CODEC(sc) ((sc)->sc_flags & GUS_CODEC_INSTALLED) 267193323Sed#define HAS_MIXER(sc) ((sc)->sc_flags & GUS_MIXER_INSTALLED) 268193323Sed 269193323Sed/* 270193323Sed * Mixer devices for ICS2101 271193323Sed */ 272193323Sed/* MIC IN mute, line in mute, line out mute are first since they can be done 273193323Sed even if no ICS mixer. */ 274193323Sed#define GUSICS_MIC_IN_MUTE 0 275193323Sed#define GUSICS_LINE_IN_MUTE 1 276193323Sed#define GUSICS_MASTER_MUTE 2 277193323Sed#define GUSICS_CD_MUTE 3 278193323Sed#define GUSICS_DAC_MUTE 4 279193323Sed#define GUSICS_MIC_IN_LVL 5 280193323Sed#define GUSICS_LINE_IN_LVL 6 281193323Sed#define GUSICS_CD_LVL 7 282193323Sed#define GUSICS_DAC_LVL 8 283193323Sed#define GUSICS_MASTER_LVL 9 284193323Sed 285193323Sed#define GUSICS_RECORD_SOURCE 10 286193323Sed 287193323Sed/* Classes */ 288193323Sed#define GUSICS_INPUT_CLASS 11 289193323Sed#define GUSICS_OUTPUT_CLASS 12 290193323Sed#define GUSICS_RECORD_CLASS 13 291193323Sed 292193323Sed/* 293193323Sed * Mixer & MUX devices for CS4231 294193323Sed */ 295193323Sed#define GUSMAX_MONO_LVL 0 /* mic input to MUX; 296193323Sed also mono mixer input */ 297193323Sed#define GUSMAX_DAC_LVL 1 /* input to MUX; also mixer input */ 298193323Sed#define GUSMAX_LINE_IN_LVL 2 /* input to MUX; also mixer input */ 299193323Sed#define GUSMAX_CD_LVL 3 /* mixer input only */ 300193323Sed#define GUSMAX_MONITOR_LVL 4 /* digital mix (?) */ 301193323Sed#define GUSMAX_OUT_LVL 5 /* output level. (?) */ 302193323Sed#define GUSMAX_SPEAKER_LVL 6 /* pseudo-device for mute */ 303193323Sed#define GUSMAX_LINE_IN_MUTE 7 /* pre-mixer */ 304193323Sed#define GUSMAX_DAC_MUTE 8 /* pre-mixer */ 305193323Sed#define GUSMAX_CD_MUTE 9 /* pre-mixer */ 306193323Sed#define GUSMAX_MONO_MUTE 10 /* pre-mixer--microphone/mono */ 307193323Sed#define GUSMAX_MONITOR_MUTE 11 /* post-mixer level/mute */ 308193323Sed#define GUSMAX_SPEAKER_MUTE 12 /* speaker mute */ 309193323Sed 310193323Sed#define GUSMAX_REC_LVL 13 /* post-MUX gain */ 311193323Sed 312193323Sed#define GUSMAX_RECORD_SOURCE 14 313193323Sed 314193323Sed/* Classes */ 315193323Sed#define GUSMAX_INPUT_CLASS 15 316193323Sed#define GUSMAX_RECORD_CLASS 16 317193323Sed#define GUSMAX_MONITOR_CLASS 17 318193323Sed#define GUSMAX_OUTPUT_CLASS 18 319193323Sed 320193323Sed#ifdef AUDIO_DEBUG 321193323Sed#define GUSPLAYDEBUG /*XXX*/ 322193323Sed#define DPRINTF(x) if (gusdebug) printf x 323193323Sed#define DMAPRINTF(x) if (gusdmadebug) printf x 324193323Sedint gusdebug = 0; 325193323Sedint gusdmadebug = 0; 326193323Sed#else 327193323Sed#define DPRINTF(x) 328193323Sed#define DMAPRINTF(x) 329193323Sed#endif 330193323Sedint gus_dostereo = 1; 331193323Sed 332193323Sed#define NDMARECS 2048 333193323Sed#ifdef GUSPLAYDEBUG 334193323Sedint gusstats = 0; 335193323Sedstruct dma_record { 336193323Sed struct timeval tv; 337193323Sed u_long gusaddr; 338193323Sed caddr_t bsdaddr; 339193323Sed u_short count; 340193323Sed u_char channel; 341193323Sed u_char direction; 342193323Sed} dmarecords[NDMARECS]; 343193323Sed 344193323Sedint dmarecord_index = 0; 345193323Sed#endif 346193323Sed 347193323Sed/* 348193323Sed * local routines 349193323Sed */ 350193323Sed 351193323Sedint gusopen __P((dev_t, int)); 352193323Sedvoid gusclose __P((void *)); 353193323Sedvoid gusmax_close __P((void *)); 354193323Sedint gusintr __P((void *)); 355193323Sedint gus_set_in_gain __P((caddr_t, u_int, u_char)); 356193323Sedint gus_get_in_gain __P((caddr_t)); 357193323Sedint gus_set_out_gain __P((caddr_t, u_int, u_char)); 358193323Sedint gus_get_out_gain __P((caddr_t)); 359193323Sedint gus_set_params __P((void *, int, struct audio_params *, struct audio_params *)); 360193323Sedint gusmax_set_params __P((void *, int, struct audio_params *, struct audio_params *)); 361193323Sedint gus_round_blocksize __P((void *, int)); 362193323Sedint gus_set_out_port __P((void *, int)); 363193323Sedint gus_get_out_port __P((void *)); 364193323Sedint gus_set_in_port __P((void *, int)); 365193323Sedint gus_get_in_port __P((void *)); 366193323Sedint gus_commit_settings __P((void *)); 367193323Sedint gus_dma_output __P((void *, void *, int, void (*)(void *), void *)); 368193323Sedint gus_dma_input __P((void *, void *, int, void (*)(void *), void *)); 369193323Sedint gus_halt_out_dma __P((void *)); 370193323Sedint gus_halt_in_dma __P((void *)); 371193323Sedint gus_cont_out_dma __P((void *)); 372193323Sedint gus_cont_in_dma __P((void *)); 373193323Sedint gus_speaker_ctl __P((void *, int)); 374193323Sedint gusmax_round_blocksize __P((void *, int)); 375193323Sedint gusmax_commit_settings __P((void *)); 376193323Sedint gusmax_dma_output __P((void *, void *, int, void (*)(void *), void *)); 377193323Sedint gusmax_dma_input __P((void *, void *, int, void (*)(void *), void *)); 378193323Sedint gusmax_halt_out_dma __P((void *)); 379193323Sedint gusmax_halt_in_dma __P((void *)); 380193323Sedint gusmax_cont_out_dma __P((void *)); 381193323Sedint gusmax_cont_in_dma __P((void *)); 382193323Sedint gusmax_speaker_ctl __P((void *, int)); 383193323Sedint gusmax_set_out_port __P((void *, int)); 384193323Sedint gusmax_get_out_port __P((void *)); 385193323Sedint gusmax_set_in_port __P((void *, int)); 386193323Sedint gusmax_get_in_port __P((void *)); 387193323Sedint gus_getdev __P((void *, struct audio_device *)); 388193323Sed 389193323SedSTATIC void gus_deinterleave __P((struct gus_softc *, void *, int)); 390193323Sed 391193323SedSTATIC int gus_mic_ctl __P((void *, int)); 392193323SedSTATIC int gus_linein_ctl __P((void *, int)); 393193323SedSTATIC int gus_test_iobase __P((int)); 394193323SedSTATIC void guspoke __P((int, long, u_char)); 395193323SedSTATIC void gusdmaout __P((struct gus_softc *, int, u_long, caddr_t, int)); 396193323SedSTATIC void gus_init_cs4231 __P((struct gus_softc *)); 397193323SedSTATIC void gus_init_ics2101 __P((struct gus_softc *)); 398193323Sed 399193323SedSTATIC void gus_set_chan_addrs __P((struct gus_softc *)); 400193323SedSTATIC void gusreset __P((struct gus_softc *, int)); 401193323SedSTATIC void gus_set_voices __P((struct gus_softc *, int)); 402193323SedSTATIC void gus_set_volume __P((struct gus_softc *, int, int)); 403193323SedSTATIC void gus_set_samprate __P((struct gus_softc *, int, int)); 404193323SedSTATIC void gus_set_recrate __P((struct gus_softc *, u_long)); 405193323SedSTATIC void gus_start_voice __P((struct gus_softc *, int, int)); 406193323SedSTATIC void gus_stop_voice __P((struct gus_softc *, int, int)); 407193323SedSTATIC void gus_set_endaddr __P((struct gus_softc *, int, u_long)); 408193323Sed#ifdef GUSPLAYDEBUG 409193323SedSTATIC void gus_set_curaddr __P((struct gus_softc *, int, u_long)); 410193323SedSTATIC u_long gus_get_curaddr __P((struct gus_softc *, int)); 411193323Sed#endif 412193323SedSTATIC int gus_dmaout_intr __P((struct gus_softc *)); 413193323SedSTATIC void gus_dmaout_dointr __P((struct gus_softc *)); 414193323SedSTATIC void gus_dmaout_timeout __P((void *)); 415193323SedSTATIC int gus_dmain_intr __P((struct gus_softc *)); 416193323SedSTATIC int gus_voice_intr __P((struct gus_softc *)); 417193323SedSTATIC void gus_start_playing __P((struct gus_softc *, int)); 418193323SedSTATIC int gus_continue_playing __P((struct gus_softc *, int)); 419193323SedSTATIC u_char guspeek __P((int, u_long)); 420193323SedSTATIC u_long convert_to_16bit __P((u_long)); 421193323SedSTATIC int gus_mixer_set_port __P((void *, mixer_ctrl_t *)); 422193323SedSTATIC int gus_mixer_get_port __P((void *, mixer_ctrl_t *)); 423193323SedSTATIC int gusmax_mixer_set_port __P((void *, mixer_ctrl_t *)); 424193323SedSTATIC int gusmax_mixer_get_port __P((void *, mixer_ctrl_t *)); 425193323SedSTATIC int gus_mixer_query_devinfo __P((void *, mixer_devinfo_t *)); 426193323SedSTATIC int gusmax_mixer_query_devinfo __P((void *, mixer_devinfo_t *)); 427193323SedSTATIC int gus_query_encoding __P((void *, struct audio_encoding *)); 428193323Sed 429193323SedSTATIC void gusics_master_mute __P((struct ics2101_softc *, int)); 430193323SedSTATIC void gusics_dac_mute __P((struct ics2101_softc *, int)); 431193323SedSTATIC void gusics_mic_mute __P((struct ics2101_softc *, int)); 432193323SedSTATIC void gusics_linein_mute __P((struct ics2101_softc *, int)); 433193323SedSTATIC void gusics_cd_mute __P((struct ics2101_softc *, int)); 434193323Sed 435193323SedSTATIC __inline int gus_to_vol __P((mixer_ctrl_t *, struct ad1848_volume *)); 436193323SedSTATIC __inline int gus_from_vol __P((mixer_ctrl_t *, struct ad1848_volume *)); 437193323Sed 438193323Sedvoid stereo_dmaintr __P((void *)); 439193323Sed 440193323Sed/* 441193323Sed * ISA bus driver routines 442193323Sed */ 443193323Sed 444193323Sedint gusprobe __P((struct device *, void *, void *)); 445193323Sedvoid gusattach __P((struct device *, struct device *, void *)); 446193323Sed 447193323Sedstruct cfattach gus_ca = { 448193323Sed sizeof(struct gus_softc), gusprobe, gusattach, 449193323Sed}; 450193323Sed 451193323Sedstruct cfdriver gus_cd = { 452193323Sed NULL, "gus", DV_DULL 453193323Sed}; 454193323Sed 455193323Sed 456193323Sed/* 457193323Sed * A mapping from IRQ/DRQ values to the values used in the GUS's internal 458193323Sed * registers. A zero means that the referenced IRQ/DRQ is invalid 459193323Sed */ 460193323Sed 461193323Sedstatic int gus_irq_map[] = { 462193323Sed IRQUNK, IRQUNK, 1, 3, IRQUNK, 2, IRQUNK, 4, IRQUNK, 1, IRQUNK, 5, 6, 463193323Sed IRQUNK, IRQUNK, 7 464193323Sed}; 465193323Sedstatic int gus_drq_map[] = { 466193323Sed DRQUNK, 1, DRQUNK, 2, DRQUNK, 3, 4, 5 467193323Sed}; 468193323Sed 469193323Sed/* 470193323Sed * A list of valid base addresses for the GUS 471193323Sed */ 472193323Sed 473193323Sedstatic int gus_base_addrs[] = { 474193323Sed 0x210, 0x220, 0x230, 0x240, 0x250, 0x260 475193323Sed}; 476193323Sedstatic int gus_addrs = sizeof(gus_base_addrs) / sizeof(gus_base_addrs[0]); 477193323Sed 478193323Sed/* 479193323Sed * Maximum frequency values of the GUS based on the number of currently active 480193323Sed * voices. Since the GUS samples a voice every 1.6 us, the maximum frequency 481193323Sed * is dependent on the number of active voices. Yes, it is pretty weird. 482193323Sed */ 483193323Sed 484193323Sedstatic int gus_max_frequency[] = { 485193323Sed 44100, /* 14 voices */ 486193323Sed 41160, /* 15 voices */ 487193323Sed 38587, /* 16 voices */ 488193323Sed 36317, /* 17 voices */ 489193323Sed 34300, /* 18 voices */ 490193323Sed 32494, /* 19 voices */ 491193323Sed 30870, /* 20 voices */ 492193323Sed 29400, /* 21 voices */ 493193323Sed 28063, /* 22 voices */ 494193323Sed 26843, /* 23 voices */ 495193323Sed 25725, /* 24 voices */ 496193323Sed 24696, /* 25 voices */ 497193323Sed 23746, /* 26 voices */ 498193323Sed 22866, /* 27 voices */ 499193323Sed 22050, /* 28 voices */ 500193323Sed 21289, /* 29 voices */ 501193323Sed 20580, /* 30 voices */ 502193323Sed 19916, /* 31 voices */ 503193323Sed 19293 /* 32 voices */ 504193323Sed}; 505193323Sed/* 506193323Sed * A mapping of linear volume levels to the logarithmic volume values used 507193323Sed * by the GF1 chip on the GUS. From GUS SDK vol1.c. 508193323Sed */ 509193323Sed 510193323Sedstatic unsigned short gus_log_volumes[512] = { 511193323Sed 0x0000, 512193323Sed 0x0700, 0x07ff, 0x0880, 0x08ff, 0x0940, 0x0980, 0x09c0, 0x09ff, 0x0a20, 513193323Sed 0x0a40, 0x0a60, 0x0a80, 0x0aa0, 0x0ac0, 0x0ae0, 0x0aff, 0x0b10, 0x0b20, 514193323Sed 0x0b30, 0x0b40, 0x0b50, 0x0b60, 0x0b70, 0x0b80, 0x0b90, 0x0ba0, 0x0bb0, 515193323Sed 0x0bc0, 0x0bd0, 0x0be0, 0x0bf0, 0x0bff, 0x0c08, 0x0c10, 0x0c18, 0x0c20, 516193323Sed 0x0c28, 0x0c30, 0x0c38, 0x0c40, 0x0c48, 0x0c50, 0x0c58, 0x0c60, 0x0c68, 517193323Sed 0x0c70, 0x0c78, 0x0c80, 0x0c88, 0x0c90, 0x0c98, 0x0ca0, 0x0ca8, 0x0cb0, 518193323Sed 0x0cb8, 0x0cc0, 0x0cc8, 0x0cd0, 0x0cd8, 0x0ce0, 0x0ce8, 0x0cf0, 0x0cf8, 519193323Sed 0x0cff, 0x0d04, 0x0d08, 0x0d0c, 0x0d10, 0x0d14, 0x0d18, 0x0d1c, 0x0d20, 520193323Sed 0x0d24, 0x0d28, 0x0d2c, 0x0d30, 0x0d34, 0x0d38, 0x0d3c, 0x0d40, 0x0d44, 521193323Sed 0x0d48, 0x0d4c, 0x0d50, 0x0d54, 0x0d58, 0x0d5c, 0x0d60, 0x0d64, 0x0d68, 522193323Sed 0x0d6c, 0x0d70, 0x0d74, 0x0d78, 0x0d7c, 0x0d80, 0x0d84, 0x0d88, 0x0d8c, 523193323Sed 0x0d90, 0x0d94, 0x0d98, 0x0d9c, 0x0da0, 0x0da4, 0x0da8, 0x0dac, 0x0db0, 524193323Sed 0x0db4, 0x0db8, 0x0dbc, 0x0dc0, 0x0dc4, 0x0dc8, 0x0dcc, 0x0dd0, 0x0dd4, 525193323Sed 0x0dd8, 0x0ddc, 0x0de0, 0x0de4, 0x0de8, 0x0dec, 0x0df0, 0x0df4, 0x0df8, 526193323Sed 0x0dfc, 0x0dff, 0x0e02, 0x0e04, 0x0e06, 0x0e08, 0x0e0a, 0x0e0c, 0x0e0e, 527193323Sed 0x0e10, 0x0e12, 0x0e14, 0x0e16, 0x0e18, 0x0e1a, 0x0e1c, 0x0e1e, 0x0e20, 528193323Sed 0x0e22, 0x0e24, 0x0e26, 0x0e28, 0x0e2a, 0x0e2c, 0x0e2e, 0x0e30, 0x0e32, 529193323Sed 0x0e34, 0x0e36, 0x0e38, 0x0e3a, 0x0e3c, 0x0e3e, 0x0e40, 0x0e42, 0x0e44, 530193323Sed 0x0e46, 0x0e48, 0x0e4a, 0x0e4c, 0x0e4e, 0x0e50, 0x0e52, 0x0e54, 0x0e56, 531193323Sed 0x0e58, 0x0e5a, 0x0e5c, 0x0e5e, 0x0e60, 0x0e62, 0x0e64, 0x0e66, 0x0e68, 532193323Sed 0x0e6a, 0x0e6c, 0x0e6e, 0x0e70, 0x0e72, 0x0e74, 0x0e76, 0x0e78, 0x0e7a, 533193323Sed 0x0e7c, 0x0e7e, 0x0e80, 0x0e82, 0x0e84, 0x0e86, 0x0e88, 0x0e8a, 0x0e8c, 534193323Sed 0x0e8e, 0x0e90, 0x0e92, 0x0e94, 0x0e96, 0x0e98, 0x0e9a, 0x0e9c, 0x0e9e, 535193323Sed 0x0ea0, 0x0ea2, 0x0ea4, 0x0ea6, 0x0ea8, 0x0eaa, 0x0eac, 0x0eae, 0x0eb0, 536193323Sed 0x0eb2, 0x0eb4, 0x0eb6, 0x0eb8, 0x0eba, 0x0ebc, 0x0ebe, 0x0ec0, 0x0ec2, 537193323Sed 0x0ec4, 0x0ec6, 0x0ec8, 0x0eca, 0x0ecc, 0x0ece, 0x0ed0, 0x0ed2, 0x0ed4, 538193323Sed 0x0ed6, 0x0ed8, 0x0eda, 0x0edc, 0x0ede, 0x0ee0, 0x0ee2, 0x0ee4, 0x0ee6, 539193323Sed 0x0ee8, 0x0eea, 0x0eec, 0x0eee, 0x0ef0, 0x0ef2, 0x0ef4, 0x0ef6, 0x0ef8, 540193323Sed 0x0efa, 0x0efc, 0x0efe, 0x0eff, 0x0f01, 0x0f02, 0x0f03, 0x0f04, 0x0f05, 541193323Sed 0x0f06, 0x0f07, 0x0f08, 0x0f09, 0x0f0a, 0x0f0b, 0x0f0c, 0x0f0d, 0x0f0e, 542193323Sed 0x0f0f, 0x0f10, 0x0f11, 0x0f12, 0x0f13, 0x0f14, 0x0f15, 0x0f16, 0x0f17, 543193323Sed 0x0f18, 0x0f19, 0x0f1a, 0x0f1b, 0x0f1c, 0x0f1d, 0x0f1e, 0x0f1f, 0x0f20, 544193323Sed 0x0f21, 0x0f22, 0x0f23, 0x0f24, 0x0f25, 0x0f26, 0x0f27, 0x0f28, 0x0f29, 545193323Sed 0x0f2a, 0x0f2b, 0x0f2c, 0x0f2d, 0x0f2e, 0x0f2f, 0x0f30, 0x0f31, 0x0f32, 546193323Sed 0x0f33, 0x0f34, 0x0f35, 0x0f36, 0x0f37, 0x0f38, 0x0f39, 0x0f3a, 0x0f3b, 547193323Sed 0x0f3c, 0x0f3d, 0x0f3e, 0x0f3f, 0x0f40, 0x0f41, 0x0f42, 0x0f43, 0x0f44, 548193323Sed 0x0f45, 0x0f46, 0x0f47, 0x0f48, 0x0f49, 0x0f4a, 0x0f4b, 0x0f4c, 0x0f4d, 549193323Sed 0x0f4e, 0x0f4f, 0x0f50, 0x0f51, 0x0f52, 0x0f53, 0x0f54, 0x0f55, 0x0f56, 550193323Sed 0x0f57, 0x0f58, 0x0f59, 0x0f5a, 0x0f5b, 0x0f5c, 0x0f5d, 0x0f5e, 0x0f5f, 551193323Sed 0x0f60, 0x0f61, 0x0f62, 0x0f63, 0x0f64, 0x0f65, 0x0f66, 0x0f67, 0x0f68, 552193323Sed 0x0f69, 0x0f6a, 0x0f6b, 0x0f6c, 0x0f6d, 0x0f6e, 0x0f6f, 0x0f70, 0x0f71, 553193323Sed 0x0f72, 0x0f73, 0x0f74, 0x0f75, 0x0f76, 0x0f77, 0x0f78, 0x0f79, 0x0f7a, 554193323Sed 0x0f7b, 0x0f7c, 0x0f7d, 0x0f7e, 0x0f7f, 0x0f80, 0x0f81, 0x0f82, 0x0f83, 555193323Sed 0x0f84, 0x0f85, 0x0f86, 0x0f87, 0x0f88, 0x0f89, 0x0f8a, 0x0f8b, 0x0f8c, 556193323Sed 0x0f8d, 0x0f8e, 0x0f8f, 0x0f90, 0x0f91, 0x0f92, 0x0f93, 0x0f94, 0x0f95, 557193323Sed 0x0f96, 0x0f97, 0x0f98, 0x0f99, 0x0f9a, 0x0f9b, 0x0f9c, 0x0f9d, 0x0f9e, 558193323Sed 0x0f9f, 0x0fa0, 0x0fa1, 0x0fa2, 0x0fa3, 0x0fa4, 0x0fa5, 0x0fa6, 0x0fa7, 559193323Sed 0x0fa8, 0x0fa9, 0x0faa, 0x0fab, 0x0fac, 0x0fad, 0x0fae, 0x0faf, 0x0fb0, 560193323Sed 0x0fb1, 0x0fb2, 0x0fb3, 0x0fb4, 0x0fb5, 0x0fb6, 0x0fb7, 0x0fb8, 0x0fb9, 561193323Sed 0x0fba, 0x0fbb, 0x0fbc, 0x0fbd, 0x0fbe, 0x0fbf, 0x0fc0, 0x0fc1, 0x0fc2, 562193323Sed 0x0fc3, 0x0fc4, 0x0fc5, 0x0fc6, 0x0fc7, 0x0fc8, 0x0fc9, 0x0fca, 0x0fcb, 563193323Sed 0x0fcc, 0x0fcd, 0x0fce, 0x0fcf, 0x0fd0, 0x0fd1, 0x0fd2, 0x0fd3, 0x0fd4, 564193323Sed 0x0fd5, 0x0fd6, 0x0fd7, 0x0fd8, 0x0fd9, 0x0fda, 0x0fdb, 0x0fdc, 0x0fdd, 565193323Sed 0x0fde, 0x0fdf, 0x0fe0, 0x0fe1, 0x0fe2, 0x0fe3, 0x0fe4, 0x0fe5, 0x0fe6, 566193323Sed 0x0fe7, 0x0fe8, 0x0fe9, 0x0fea, 0x0feb, 0x0fec, 0x0fed, 0x0fee, 0x0fef, 567193323Sed 0x0ff0, 0x0ff1, 0x0ff2, 0x0ff3, 0x0ff4, 0x0ff5, 0x0ff6, 0x0ff7, 0x0ff8, 568193323Sed 0x0ff9, 0x0ffa, 0x0ffb, 0x0ffc, 0x0ffd, 0x0ffe, 0x0fff}; 569193323Sed 570193323Sed#define SELECT_GUS_REG(port,x) outb(port+GUS_REG_SELECT,x) 571193323Sed#define WHICH_GUS_REG(port) inb(port+GUS_REG_SELECT) 572193323Sed#define ADDR_HIGH(x) (unsigned int) ((x >> 7L) & 0x1fffL) 573193323Sed#define ADDR_LOW(x) (unsigned int) ((x & 0x7fL) << 9L) 574193323Sed 575193323Sed#define GUS_MIN_VOICES 14 /* Minimum possible number of voices */ 576193323Sed#define GUS_MAX_VOICES 32 /* Maximum possible number of voices */ 577193323Sed#define GUS_VOICE_LEFT 0 /* Voice used for left (and mono) playback */ 578193323Sed#define GUS_VOICE_RIGHT 1 /* Voice used for right playback */ 579193323Sed#define GUS_MEM_OFFSET 32 /* Offset into GUS memory to begin of buffer */ 580193323Sed#define GUS_BUFFER_MULTIPLE 1024 /* Audio buffers are multiples of this */ 581193323Sed#define GUS_MEM_FOR_BUFFERS 131072 /* use this many bytes on-GUS */ 582193323Sed#define GUS_LEFT_RIGHT_OFFSET (sc->sc_nbufs * sc->sc_chanblocksize + GUS_MEM_OFFSET) 583193323Sed 584193323Sed#define GUS_PREC_BYTES (sc->sc_precision >> 3) /* precision to bytes */ 585193323Sed 586193323Sed/* splgus() must be splaudio() */ 587193323Sed 588193323Sed#define splgus splaudio 589193323Sed 590193323Sed/* 591193323Sed * Interface to higher level audio driver 592193323Sed */ 593193323Sed 594193323Sedstruct audio_hw_if gus_hw_if = { 595193323Sed gusopen, 596193323Sed gusclose, 597193323Sed NULL, /* drain */ 598193323Sed 599193323Sed gus_query_encoding, 600193323Sed 601193323Sed gus_set_params, 602193323Sed 603193323Sed gus_round_blocksize, 604193323Sed 605193323Sed gus_set_out_port, 606193323Sed gus_get_out_port, 607193323Sed gus_set_in_port, 608193323Sed gus_get_in_port, 609193323Sed 610193323Sed gus_commit_settings, 611193323Sed 612193323Sed NULL, 613193323Sed NULL, 614193323Sed 615193323Sed gus_dma_output, 616193323Sed gus_dma_input, 617193323Sed gus_halt_out_dma, 618193323Sed gus_halt_in_dma, 619193323Sed gus_cont_out_dma, 620193323Sed gus_cont_in_dma, 621193323Sed 622193323Sed gus_speaker_ctl, 623193323Sed 624193323Sed gus_getdev, 625193323Sed NULL, 626193323Sed gus_mixer_set_port, 627193323Sed gus_mixer_get_port, 628193323Sed gus_mixer_query_devinfo, 629193323Sed NULL, 630193323Sed NULL, 631193323Sed NULL, 632193323Sed AUDIO_PROP_FULLDUPLEX, 633193323Sed 0, 634193323Sed}; 635193323Sed 636193323Sed 637193323Sed/* 638193323Sed * Some info about the current audio device 639193323Sed */ 640193323Sed 641193323Sedstruct audio_device gus_device = { 642193323Sed "UltraSound", 643193323Sed "", 644193323Sed "gus", 645193323Sed}; 646193323Sed 647193323Sed#define FLIP_REV 5 /* This rev has flipped mixer chans */ 648193323Sed 649193323Sed 650193323Sedint 651193323Sedgusprobe(parent, match, aux) 652193323Sed struct device *parent; 653193323Sed void *match, *aux; 654193323Sed{ 655193323Sed register struct gus_softc *sc = match; 656193323Sed register struct isa_attach_args *ia = aux; 657193323Sed struct cfdata *cf = sc->sc_dev.dv_cfdata; 658193323Sed register int iobase = ia->ia_iobase; 659193323Sed int recdrq = cf->cf_flags; 660193323Sed 661193323Sed sc->sc_iot = ia->ia_iot; 662193323Sed /* 663193323Sed * Before we do anything else, make sure requested IRQ and DRQ are 664193323Sed * valid for this card. 665193323Sed */ 666193323Sed 667193323Sed if (gus_irq_map[ia->ia_irq] == IRQUNK) { 668193323Sed printf("gus: invalid irq %d, card not probed\n", ia->ia_irq); 669193323Sed return(0); 670193323Sed } 671193323Sed 672193323Sed if (gus_drq_map[ia->ia_drq] == DRQUNK) { 673193323Sed printf("gus: invalid drq %d, card not probed\n", ia->ia_drq); 674193323Sed return(0); 675193323Sed } 676193323Sed 677193323Sed if (recdrq != 0x00) { 678193323Sed if (recdrq > 7 || gus_drq_map[recdrq] == DRQUNK) { 679193323Sed printf("gus: invalid flag given for second DMA channel (0x%x), card not probed\n", recdrq); 680193323Sed return(0); 681193323Sed } 682193323Sed } else 683193323Sed recdrq = ia->ia_drq; 684193323Sed 685193323Sed if (iobase == IOBASEUNK) { 686193323Sed int i; 687193323Sed for(i = 0; i < gus_addrs; i++) 688193323Sed if (gus_test_iobase(gus_base_addrs[i])) { 689193323Sed iobase = gus_base_addrs[i]; 690193323Sed goto done; 691193323Sed } 692193323Sed return 0; 693193323Sed } else if (! gus_test_iobase(iobase)) 694193323Sed return 0; 695193323Sed 696193323Seddone: 697193323Sed sc->sc_iobase = iobase; 698193323Sed sc->sc_irq = ia->ia_irq; 699193323Sed sc->sc_drq = ia->ia_drq; 700193323Sed sc->sc_recdrq = recdrq; 701193323Sed 702193323Sed ia->ia_iobase = sc->sc_iobase; 703193323Sed ia->ia_iosize = 16; /* XXX */ 704193323Sed return(1); 705193323Sed} 706 707/* 708 * Test to see if a particular I/O base is valid for the GUS. Return true 709 * if it is. 710 */ 711 712STATIC int 713gus_test_iobase (int iobase) 714{ 715 int i = splgus(); 716 u_char s1, s2; 717 718 /* 719 * Reset GUS to an initial state before we do anything. 720 */ 721 722 delay(500); 723 724 SELECT_GUS_REG(iobase, GUSREG_RESET); 725 outb(iobase+GUS_DATA_HIGH, 0x00); 726 727 delay(500); 728 729 SELECT_GUS_REG(iobase, GUSREG_RESET); 730 outb(iobase+GUS_DATA_HIGH, GUSMASK_MASTER_RESET); 731 732 delay(500); 733 734 splx(i); 735 736 /* 737 * See if we can write to the board's memory 738 */ 739 740 s1 = guspeek(iobase, 0L); 741 s2 = guspeek(iobase, 1L); 742 743 guspoke(iobase, 0L, 0xaa); 744 guspoke(iobase, 1L, 0x55); 745 746 if ((i=(int)guspeek(iobase, 0L)) != 0xaa) { 747 return(0); 748 } 749 750 guspoke(iobase, 0L, s1); 751 guspoke(iobase, 1L, s2); 752 753 return 1; 754} 755 756/* 757 * Setup the GUS for use; called shortly after probe 758 */ 759 760void 761gusattach(parent, self, aux) 762 struct device *parent, *self; 763 void *aux; 764{ 765 register struct gus_softc *sc = (void *) self; 766 register struct isa_attach_args *ia = aux; 767 register int port = ia->ia_iobase; 768 int i; 769 register unsigned char c,d,m; 770 771 /* 772 * Figure out our board rev, and see if we need to initialize the 773 * mixer 774 */ 775 776 delay(500); 777 778 c = inb(port+GUS_BOARD_REV); 779 if (c != 0xff) 780 sc->sc_revision = c; 781 else 782 sc->sc_revision = 0; 783 784 785 SELECT_GUS_REG(port, GUSREG_RESET); 786 outb(port+GUS_DATA_HIGH, 0x00); 787 788 gusreset(sc, GUS_MAX_VOICES); /* initialize all voices */ 789 gusreset(sc, GUS_MIN_VOICES); /* then set to just the ones we use */ 790 791 /* 792 * Setup the IRQ and DRQ lines in software, using values from 793 * config file 794 */ 795 796 m = GUSMASK_LINE_IN|GUSMASK_LINE_OUT; /* disable all */ 797 798 c = ((unsigned char) gus_irq_map[ia->ia_irq]) | GUSMASK_BOTH_RQ; 799 800 if (sc->sc_recdrq == sc->sc_drq) 801 d = (unsigned char) (gus_drq_map[sc->sc_drq] | 802 GUSMASK_BOTH_RQ); 803 else 804 d = (unsigned char) (gus_drq_map[sc->sc_drq] | 805 gus_drq_map[sc->sc_recdrq] << 3); 806 807 /* 808 * Program the IRQ and DMA channels on the GUS. Note that we hardwire 809 * the GUS to only use one IRQ channel, but we give the user the 810 * option of using two DMA channels (the other one given by the flags 811 * option in the config file). Two DMA channels are needed for full- 812 * duplex operation. 813 * 814 * The order of these operations is very magical. 815 */ 816 817 disable_intr(); 818 819 outb(port+GUS_REG_CONTROL, GUS_REG_IRQCTL); 820 outb(port+GUS_MIX_CONTROL, m); 821 outb(port+GUS_IRQCTL_CONTROL, 0x00); 822 outb(port+0x0f, 0x00); 823 824 outb(port+GUS_MIX_CONTROL, m); 825 outb(port+GUS_DMA_CONTROL, d | 0x80); /* magic reset? */ 826 827 outb(port+GUS_MIX_CONTROL, m | GUSMASK_CONTROL_SEL); 828 outb(port+GUS_IRQ_CONTROL, c); 829 830 outb(port+GUS_MIX_CONTROL, m); 831 outb(port+GUS_DMA_CONTROL, d); 832 833 outb(port+GUS_MIX_CONTROL, m | GUSMASK_CONTROL_SEL); 834 outb(port+GUS_IRQ_CONTROL, c); 835 836 outb(port+GUS_VOICE_SELECT, 0x00); 837 838 /* enable line in, line out. leave mic disabled. */ 839 outb(port+GUS_MIX_CONTROL, 840 (m | GUSMASK_LATCHES) & ~(GUSMASK_LINE_OUT|GUSMASK_LINE_IN)); 841 outb(port+GUS_VOICE_SELECT, 0x00); 842 843 enable_intr(); 844 845 sc->sc_mixcontrol = 846 (m | GUSMASK_LATCHES) & ~(GUSMASK_LINE_OUT|GUSMASK_LINE_IN); 847 848 /* XXX WILL THIS ALWAYS WORK THE WAY THEY'RE OVERLAYED?! */ 849 sc->sc_codec.sc_isa = sc->sc_dev.dv_parent; 850 851 if (sc->sc_revision >= 5 && sc->sc_revision <= 9) { 852 sc->sc_flags |= GUS_MIXER_INSTALLED; 853 gus_init_ics2101(sc); 854 } 855 if (sc->sc_revision >= 0xa) { 856 gus_init_cs4231(sc); 857 } 858 859 SELECT_GUS_REG(port, GUSREG_RESET); 860 /* 861 * Check to see how much memory we have on this card; see if any 862 * "mirroring" occurs. We're assuming at least 256K already exists 863 * on the card; otherwise the initial probe would have failed 864 */ 865 866 guspoke(port, 0L, 0x00); 867 for(i = 1; i < 1024; i++) { 868 u_long loc; 869 870 /* 871 * See if we've run into mirroring yet 872 */ 873 874 if (guspeek(port, 0L) != 0) 875 break; 876 877 loc = i << 10; 878 879 guspoke(port, loc, 0xaa); 880 if (guspeek(port, loc) != 0xaa) 881 break; 882 } 883 884 sc->sc_dsize = i; 885 sprintf(gus_device.version, "3.%d", sc->sc_revision); 886 887 printf("\n <Gravis UltraSound version 3.%d, %dKB DRAM, ", 888 sc->sc_revision, sc->sc_dsize); 889 if (HAS_MIXER(sc)) 890 printf("ICS2101 mixer, "); 891 if (HAS_CODEC(sc)) 892 printf("%s codec/mixer, ", sc->sc_codec.chip_name); 893 if (sc->sc_recdrq == sc->sc_drq) { 894 printf("half-duplex"); 895 gus_hw_if.props &= ~AUDIO_PROP_FULLDUPLEX; 896 } else { 897 printf("full-duplex, record drq %d", sc->sc_recdrq); 898 gus_hw_if.props |= AUDIO_PROP_FULLDUPLEX; 899 } 900 901 printf(">\n"); 902 903 /* 904 * Setup a default interrupt handler 905 */ 906 907 /* XXX we shouldn't have to use splgus == splclock, nor should 908 * we use IPL_CLOCK. 909 */ 910 sc->sc_ih = isa_intr_establish(ia->ia_ic, ia->ia_irq, IST_EDGE, 911 IPL_AUDIO, gusintr, sc /* sc->sc_gusdsp */); 912 913 /* 914 * Set some default values 915 */ 916 917 sc->sc_irate = sc->sc_orate = 44100; 918 sc->sc_encoding = AUDIO_ENCODING_SLINEAR_LE; 919 sc->sc_precision = 16; 920 sc->sc_voc[GUS_VOICE_LEFT].voccntl |= GUSMASK_DATA_SIZE16; 921 sc->sc_voc[GUS_VOICE_RIGHT].voccntl |= GUSMASK_DATA_SIZE16; 922 sc->sc_channels = 1; 923 sc->sc_ogain = 340; 924 gus_commit_settings(sc); 925 926 /* 927 * We always put the left channel full left & right channel 928 * full right. 929 * For mono playback, we set up both voices playing the same buffer. 930 */ 931 outb(sc->sc_iobase+GUS_VOICE_SELECT, (unsigned char) GUS_VOICE_LEFT); 932 SELECT_GUS_REG(sc->sc_iobase, GUSREG_PAN_POS); 933 outb(sc->sc_iobase+GUS_DATA_HIGH, GUS_PAN_FULL_LEFT); 934 935 outb(sc->sc_iobase+GUS_VOICE_SELECT, (unsigned char) GUS_VOICE_RIGHT); 936 SELECT_GUS_REG(sc->sc_iobase, GUSREG_PAN_POS); 937 outb(sc->sc_iobase+GUS_DATA_HIGH, GUS_PAN_FULL_RIGHT); 938 939 /* 940 * Attach to the generic audio layer 941 */ 942 943 if (audio_hardware_attach(&gus_hw_if, HAS_CODEC(sc) ? (void *)&sc->sc_codec : (void *)sc) != 0) 944 printf("gus: could not attach to audio pseudo-device driver\n"); 945} 946 947int 948gusopen(dev, flags) 949 dev_t dev; 950 int flags; 951{ 952 int unit = AUDIOUNIT(dev); 953 struct gus_softc *sc; 954 955 DPRINTF(("gusopen() called\n")); 956 957 if (unit >= gus_cd.cd_ndevs) 958 return ENXIO; 959 sc = gus_cd.cd_devs[unit]; 960 if (!sc) 961 return ENXIO; 962 963 if (sc->sc_flags & GUS_OPEN) 964 return EBUSY; 965 966 /* 967 * Some initialization 968 */ 969 970 sc->sc_flags |= GUS_OPEN; 971 sc->sc_dmabuf = 0; 972 sc->sc_playbuf = -1; 973 sc->sc_bufcnt = 0; 974 sc->sc_voc[GUS_VOICE_LEFT].start_addr = GUS_MEM_OFFSET - 1; 975 sc->sc_voc[GUS_VOICE_LEFT].current_addr = GUS_MEM_OFFSET; 976 977 if (HAS_CODEC(sc)) { 978 ad1848_open(&sc->sc_codec, dev, flags); 979 sc->sc_codec.aux1_mute = 0; 980 ad1848_mute_aux1(&sc->sc_codec, 0); /* turn on DAC output */ 981 if (flags & FREAD) { 982 sc->sc_codec.mono_mute = 0; 983 cs4231_mute_mono(&sc->sc_codec, 0); 984 } 985 } else if (flags & FREAD) { 986 /* enable/unmute the microphone */ 987 if (HAS_MIXER(sc)) { 988 gusics_mic_mute(&sc->sc_mixer, 0); 989 } else 990 gus_mic_ctl(sc, SPKR_ON); 991 } 992 if (sc->sc_nbufs == 0) 993 gus_round_blocksize(sc, GUS_BUFFER_MULTIPLE); /* default blksiz */ 994 return 0; 995} 996 997STATIC void 998gus_deinterleave(sc, buf, size) 999 register struct gus_softc *sc; 1000 void *buf; 1001 int size; 1002{ 1003 /* deinterleave the stereo data. We can use sc->sc_deintr_buf 1004 for scratch space. */ 1005 register int i; 1006 1007 if (size > sc->sc_blocksize) { 1008 printf("gus: deinterleave %d > %d\n", size, sc->sc_blocksize); 1009 return; 1010 } else if (size < sc->sc_blocksize) { 1011 DPRINTF(("gus: deinterleave %d < %d\n", size, sc->sc_blocksize)); 1012 } 1013 1014 /* 1015 * size is in bytes. 1016 */ 1017 if (sc->sc_precision == 16) { 1018 register u_short *dei = sc->sc_deintr_buf; 1019 register u_short *sbuf = buf; 1020 size >>= 1; /* bytecnt to shortcnt */ 1021 /* copy 2nd of each pair of samples to the staging area, while 1022 compacting the 1st of each pair into the original area. */ 1023 for (i = 0; i < size/2-1; i++) { 1024 dei[i] = sbuf[i*2+1]; 1025 sbuf[i+1] = sbuf[i*2+2]; 1026 } 1027 /* 1028 * this has copied one less sample than half of the 1029 * buffer. The first sample of the 1st stream was 1030 * already in place and didn't need copying. 1031 * Therefore, we've moved all of the 1st stream's 1032 * samples into place. We have one sample from 2nd 1033 * stream in the last slot of original area, not 1034 * copied to the staging area (But we don't need to!). 1035 * Copy the remainder of the original stream into place. 1036 */ 1037 bcopy(dei, &sbuf[size/2], i * sizeof(short)); 1038 } else { 1039 register u_char *dei = sc->sc_deintr_buf; 1040 register u_char *sbuf = buf; 1041 for (i = 0; i < size/2-1; i++) { 1042 dei[i] = sbuf[i*2+1]; 1043 sbuf[i+1] = sbuf[i*2+2]; 1044 } 1045 bcopy(dei, &sbuf[size/2], i); 1046 } 1047} 1048 1049/* 1050 * Actually output a buffer to the DSP chip 1051 */ 1052 1053int 1054gusmax_dma_output(addr, buf, size, intr, arg) 1055 void * addr; 1056 void *buf; 1057 int size; 1058 void (*intr) __P((void *)); 1059 void *arg; 1060{ 1061 register struct ad1848_softc *ac = addr; 1062 return gus_dma_output(ac->parent, buf, size, intr, arg); 1063} 1064 1065/* 1066 * called at splgus() from interrupt handler. 1067 */ 1068void 1069stereo_dmaintr(arg) 1070 void *arg; 1071{ 1072 struct gus_softc *sc = arg; 1073 struct stereo_dma_intr *sa = &sc->sc_stereo; 1074 1075 DMAPRINTF(("stereo_dmaintr")); 1076 1077 /* 1078 * Put other half in its place, then call the real interrupt routine :) 1079 */ 1080 1081 sc->sc_dmaoutintr = sa->intr; 1082 sc->sc_outarg = sa->arg; 1083 1084#ifdef GUSPLAYDEBUG 1085 if (gusstats) { 1086 microtime(&dmarecords[dmarecord_index].tv); 1087 dmarecords[dmarecord_index].gusaddr = sa->dmabuf; 1088 dmarecords[dmarecord_index].bsdaddr = sa->buffer; 1089 dmarecords[dmarecord_index].count = sa->size; 1090 dmarecords[dmarecord_index].channel = 1; 1091 dmarecords[dmarecord_index].direction = 1; 1092 dmarecord_index = ++dmarecord_index % NDMARECS; 1093 } 1094#endif 1095 1096 gusdmaout(sc, sa->flags, sa->dmabuf, (caddr_t) sa->buffer, sa->size); 1097 1098 sa->flags = 0; 1099 sa->dmabuf = 0; 1100 sa->buffer = 0; 1101 sa->size = 0; 1102 sa->intr = 0; 1103 sa->arg = 0; 1104} 1105 1106/* 1107 * Start up DMA output to the card. 1108 * Called at splgus/splaudio already, either from intr handler or from 1109 * generic audio code. 1110 */ 1111int 1112gus_dma_output(addr, buf, size, intr, arg) 1113 void * addr; 1114 void *buf; 1115 int size; 1116 void (*intr) __P((void *)); 1117 void *arg; 1118{ 1119 struct gus_softc *sc = addr; 1120 u_char *buffer = buf; 1121 u_long boarddma; 1122 int flags; 1123 1124 DMAPRINTF(("gus_dma_output %d @ %p\n", size, buf)); 1125 1126 if (size != sc->sc_blocksize) { 1127 DPRINTF(("gus_dma_output reqsize %d not sc_blocksize %d\n", 1128 size, sc->sc_blocksize)); 1129 return EINVAL; 1130 } 1131 1132 flags = GUSMASK_DMA_WRITE; 1133 if (sc->sc_precision == 16) 1134 flags |= GUSMASK_DMA_DATA_SIZE; 1135 if (sc->sc_encoding == AUDIO_ENCODING_ULAW || 1136 sc->sc_encoding == AUDIO_ENCODING_ULINEAR_BE || 1137 sc->sc_encoding == AUDIO_ENCODING_ULINEAR_LE) 1138 flags |= GUSMASK_DMA_INVBIT; 1139 1140 if (sc->sc_channels == 2) { 1141 if (sc->sc_precision == 16) { 1142 if (size & 3) { 1143 DPRINTF(("gus_dma_output: unpaired 16bit samples")); 1144 size &= 3; 1145 } 1146 } else if (size & 1) { 1147 DPRINTF(("gus_dma_output: unpaired samples")); 1148 size &= 1; 1149 } 1150 if (size == 0) 1151 return 0; 1152 1153 gus_deinterleave(sc, (void *)buffer, size); 1154 1155 size >>= 1; 1156 1157 boarddma = size * sc->sc_dmabuf + GUS_MEM_OFFSET; 1158 1159 sc->sc_stereo.intr = intr; 1160 sc->sc_stereo.arg = arg; 1161 sc->sc_stereo.size = size; 1162 sc->sc_stereo.dmabuf = boarddma + GUS_LEFT_RIGHT_OFFSET; 1163 sc->sc_stereo.buffer = buffer + size; 1164 sc->sc_stereo.flags = flags; 1165 if (gus_dostereo) { 1166 intr = stereo_dmaintr; 1167 arg = sc; 1168 } 1169 } else 1170 boarddma = size * sc->sc_dmabuf + GUS_MEM_OFFSET; 1171 1172 1173 sc->sc_flags |= GUS_LOCKED; 1174 sc->sc_dmaoutintr = intr; 1175 sc->sc_outarg = arg; 1176 1177#ifdef GUSPLAYDEBUG 1178 if (gusstats) { 1179 microtime(&dmarecords[dmarecord_index].tv); 1180 dmarecords[dmarecord_index].gusaddr = boarddma; 1181 dmarecords[dmarecord_index].bsdaddr = buffer; 1182 dmarecords[dmarecord_index].count = size; 1183 dmarecords[dmarecord_index].channel = 0; 1184 dmarecords[dmarecord_index].direction = 1; 1185 dmarecord_index = ++dmarecord_index % NDMARECS; 1186 } 1187#endif 1188 1189 gusdmaout(sc, flags, boarddma, (caddr_t) buffer, size); 1190 1191 return 0; 1192} 1193 1194void 1195gusmax_close(addr) 1196 void *addr; 1197{ 1198 register struct ad1848_softc *ac = addr; 1199 register struct gus_softc *sc = ac->parent; 1200#if 0 1201 ac->aux1_mute = 1; 1202 ad1848_mute_aux1(ac, 1); /* turn off DAC output */ 1203#endif 1204 ad1848_close(ac); 1205 gusclose(sc); 1206} 1207 1208/* 1209 * Close out device stuff. Called at splgus() from generic audio layer. 1210 */ 1211void 1212gusclose(addr) 1213 void *addr; 1214{ 1215 struct gus_softc *sc = addr; 1216 1217 DPRINTF(("gus_close: sc=%p\n", sc)); 1218 1219 1220/* if (sc->sc_flags & GUS_DMAOUT_ACTIVE) */ { 1221 gus_halt_out_dma(sc); 1222 } 1223/* if (sc->sc_flags & GUS_DMAIN_ACTIVE) */ { 1224 gus_halt_in_dma(sc); 1225 } 1226 sc->sc_flags &= ~(GUS_OPEN|GUS_LOCKED|GUS_DMAOUT_ACTIVE|GUS_DMAIN_ACTIVE); 1227 1228 if (sc->sc_deintr_buf) { 1229 FREE(sc->sc_deintr_buf, M_DEVBUF); 1230 sc->sc_deintr_buf = NULL; 1231 } 1232 /* turn off speaker, etc. */ 1233 1234 /* make sure the voices shut up: */ 1235 gus_stop_voice(sc, GUS_VOICE_LEFT, 1); 1236 gus_stop_voice(sc, GUS_VOICE_RIGHT, 0); 1237} 1238 1239/* 1240 * Service interrupts. Farm them off to helper routines if we are using the 1241 * GUS for simple playback/record 1242 */ 1243 1244#ifdef DIAGNOSTIC 1245int gusintrcnt; 1246int gusdmaintrcnt; 1247int gusvocintrcnt; 1248#endif 1249 1250int 1251gusintr(arg) 1252 void *arg; 1253{ 1254 register struct gus_softc *sc = arg; 1255 unsigned char intr; 1256 register int port = sc->sc_iobase; 1257 int retval = 0; 1258 1259 DPRINTF(("gusintr\n")); 1260#ifdef DIAGNOSTIC 1261 gusintrcnt++; 1262#endif 1263 if (HAS_CODEC(sc)) 1264 retval = ad1848_intr(&sc->sc_codec); 1265 if ((intr = inb(port+GUS_IRQ_STATUS)) & GUSMASK_IRQ_DMATC) { 1266 DMAPRINTF(("gusintr dma flags=%x\n", sc->sc_flags)); 1267#ifdef DIAGNOSTIC 1268 gusdmaintrcnt++; 1269#endif 1270 retval += gus_dmaout_intr(sc); 1271 if (sc->sc_flags & GUS_DMAIN_ACTIVE) { 1272 SELECT_GUS_REG(port, GUSREG_SAMPLE_CONTROL); 1273 intr = inb(port+GUS_DATA_HIGH); 1274 if (intr & GUSMASK_SAMPLE_DMATC) { 1275 retval += gus_dmain_intr(sc); 1276 } 1277 } 1278 } 1279 if (intr & (GUSMASK_IRQ_VOICE | GUSMASK_IRQ_VOLUME)) { 1280 DMAPRINTF(("gusintr voice flags=%x\n", sc->sc_flags)); 1281#ifdef DIAGNOSTIC 1282 gusvocintrcnt++; 1283#endif 1284 retval += gus_voice_intr(sc); 1285 } 1286 if (retval) 1287 return 1; 1288 return retval; 1289} 1290 1291int gus_bufcnt[GUS_MEM_FOR_BUFFERS / GUS_BUFFER_MULTIPLE]; 1292int gus_restart; /* how many restarts? */ 1293int gus_stops; /* how many times did voice stop? */ 1294int gus_falsestops; /* stopped but not done? */ 1295int gus_continues; 1296 1297struct playcont { 1298 struct timeval tv; 1299 u_int playbuf; 1300 u_int dmabuf; 1301 u_char bufcnt; 1302 u_char vaction; 1303 u_char voccntl; 1304 u_char volcntl; 1305 u_long curaddr; 1306 u_long endaddr; 1307} playstats[NDMARECS]; 1308 1309int playcntr; 1310 1311STATIC void 1312gus_dmaout_timeout(arg) 1313 void *arg; 1314{ 1315 register struct gus_softc *sc = arg; 1316 register int port = sc->sc_iobase; 1317 int s; 1318 1319 printf("%s: dmaout timeout\n", sc->sc_dev.dv_xname); 1320 /* 1321 * Stop any DMA. 1322 */ 1323 1324 s = splgus(); 1325 SELECT_GUS_REG(port, GUSREG_DMA_CONTROL); 1326 outb(sc->sc_iobase+GUS_DATA_HIGH, 0); 1327 1328#if 0 1329 /* XXX we will dmadone below? */ 1330 isa_dmaabort(sc->sc_dev.dv_parent, sc->sc_drq); 1331#endif 1332 1333 gus_dmaout_dointr(sc); 1334 splx(s); 1335} 1336 1337 1338/* 1339 * Service DMA interrupts. This routine will only get called if we're doing 1340 * a DMA transfer for playback/record requests from the audio layer. 1341 */ 1342 1343STATIC int 1344gus_dmaout_intr(sc) 1345 struct gus_softc *sc; 1346{ 1347 register int port = sc->sc_iobase; 1348 1349 /* 1350 * If we got a DMA transfer complete from the GUS DRAM, then deal 1351 * with it. 1352 */ 1353 1354 SELECT_GUS_REG(port, GUSREG_DMA_CONTROL); 1355 if (inb(port+GUS_DATA_HIGH) & GUSMASK_DMA_IRQPEND) { 1356 untimeout(gus_dmaout_timeout, sc); 1357 gus_dmaout_dointr(sc); 1358 return 1; 1359 } 1360 return 0; 1361} 1362 1363STATIC void 1364gus_dmaout_dointr(sc) 1365 struct gus_softc *sc; 1366{ 1367 register int port = sc->sc_iobase; 1368 1369 /* sc->sc_dmaoutcnt - 1 because DMA controller counts from zero?. */ 1370 isa_dmadone(sc->sc_dev.dv_parent, sc->sc_drq); 1371 sc->sc_flags &= ~GUS_DMAOUT_ACTIVE; /* pending DMA is done */ 1372 DMAPRINTF(("gus_dmaout_dointr %d @ %p\n", sc->sc_dmaoutcnt, 1373 sc->sc_dmaoutaddr)); 1374 1375 /* 1376 * to prevent clicking, we need to copy last sample 1377 * from last buffer to scratch area just before beginning of 1378 * buffer. However, if we're doing formats that are converted by 1379 * the card during the DMA process, we need to pick up the converted 1380 * byte rather than the one we have in memory. 1381 */ 1382 if (sc->sc_dmabuf == sc->sc_nbufs - 1) { 1383 register int i; 1384 switch (sc->sc_encoding) { 1385 case AUDIO_ENCODING_SLINEAR_LE: 1386 case AUDIO_ENCODING_SLINEAR_BE: 1387 if (sc->sc_precision == 8) 1388 goto byte; 1389 /* we have the native format */ 1390 for (i = 1; i <= 2; i++) 1391 guspoke(port, sc->sc_gusaddr - 1392 (sc->sc_nbufs - 1) * sc->sc_chanblocksize - i, 1393 sc->sc_dmaoutaddr[sc->sc_dmaoutcnt-i]); 1394 break; 1395 case AUDIO_ENCODING_ULINEAR_LE: 1396 case AUDIO_ENCODING_ULINEAR_BE: 1397 guspoke(port, sc->sc_gusaddr - 1398 (sc->sc_nbufs - 1) * sc->sc_chanblocksize - 2, 1399 guspeek(port, 1400 sc->sc_gusaddr + sc->sc_chanblocksize - 2)); 1401 case AUDIO_ENCODING_ULAW: 1402 byte: 1403 /* we need to fetch the translated byte, then stuff it. */ 1404 guspoke(port, sc->sc_gusaddr - 1405 (sc->sc_nbufs - 1) * sc->sc_chanblocksize - 1, 1406 guspeek(port, 1407 sc->sc_gusaddr + sc->sc_chanblocksize - 1)); 1408 break; 1409 } 1410 } 1411 /* 1412 * If this is the first half of stereo, "ignore" this one 1413 * and copy out the second half. 1414 */ 1415 if (sc->sc_dmaoutintr == stereo_dmaintr) { 1416 (*sc->sc_dmaoutintr)(sc->sc_outarg); 1417 return; 1418 } 1419 /* 1420 * If the voice is stopped, then start it. Reset the loop 1421 * and roll bits. Call the audio layer routine, since if 1422 * we're starting a stopped voice, that means that the next 1423 * buffer can be filled 1424 */ 1425 1426 sc->sc_flags &= ~GUS_LOCKED; 1427 if (sc->sc_voc[GUS_VOICE_LEFT].voccntl & 1428 GUSMASK_VOICE_STOPPED) { 1429 if (sc->sc_flags & GUS_PLAYING) { 1430 printf("%s: playing yet stopped?\n", sc->sc_dev.dv_xname); 1431 } 1432 sc->sc_bufcnt++; /* another yet to be played */ 1433 gus_start_playing(sc, sc->sc_dmabuf); 1434 gus_restart++; 1435 } else { 1436 /* 1437 * set the sound action based on which buffer we 1438 * just transferred. If we just transferred buffer 0 1439 * we want the sound to loop when it gets to the nth 1440 * buffer; if we just transferred 1441 * any other buffer, we want the sound to roll over 1442 * at least one more time. The voice interrupt 1443 * handlers will take care of accounting & 1444 * setting control bits if it's not caught up to us 1445 * yet. 1446 */ 1447 if (++sc->sc_bufcnt == 2) { 1448 /* 1449 * XXX 1450 * If we're too slow in reaction here, 1451 * the voice could be just approaching the 1452 * end of its run. It should be set to stop, 1453 * so these adjustments might not DTRT. 1454 */ 1455 if (sc->sc_dmabuf == 0 && 1456 sc->sc_playbuf == sc->sc_nbufs - 1) { 1457 /* player is just at the last buf, we're at the 1458 first. Turn on looping, turn off rolling. */ 1459 sc->sc_voc[GUS_VOICE_LEFT].voccntl |= GUSMASK_LOOP_ENABLE; 1460 sc->sc_voc[GUS_VOICE_LEFT].volcntl &= ~GUSMASK_VOICE_ROLL; 1461 playstats[playcntr].vaction = 3; 1462 } else { 1463 /* player is at previous buf: 1464 turn on rolling, turn off looping */ 1465 sc->sc_voc[GUS_VOICE_LEFT].voccntl &= ~GUSMASK_LOOP_ENABLE; 1466 sc->sc_voc[GUS_VOICE_LEFT].volcntl |= GUSMASK_VOICE_ROLL; 1467 playstats[playcntr].vaction = 4; 1468 } 1469#ifdef GUSPLAYDEBUG 1470 if (gusstats) { 1471 microtime(&playstats[playcntr].tv); 1472 playstats[playcntr].endaddr = sc->sc_voc[GUS_VOICE_LEFT].end_addr; 1473 playstats[playcntr].voccntl = sc->sc_voc[GUS_VOICE_LEFT].voccntl; 1474 playstats[playcntr].volcntl = sc->sc_voc[GUS_VOICE_LEFT].volcntl; 1475 playstats[playcntr].playbuf = sc->sc_playbuf; 1476 playstats[playcntr].dmabuf = sc->sc_dmabuf; 1477 playstats[playcntr].bufcnt = sc->sc_bufcnt; 1478 playstats[playcntr].curaddr = gus_get_curaddr(sc, GUS_VOICE_LEFT); 1479 playcntr = ++playcntr % NDMARECS; 1480 } 1481#endif 1482 outb(port+GUS_VOICE_SELECT, GUS_VOICE_LEFT); 1483 SELECT_GUS_REG(port, GUSREG_VOICE_CNTL); 1484 outb(port+GUS_DATA_HIGH, sc->sc_voc[GUS_VOICE_LEFT].voccntl); 1485 SELECT_GUS_REG(port, GUSREG_VOLUME_CONTROL); 1486 outb(port+GUS_DATA_HIGH, sc->sc_voc[GUS_VOICE_LEFT].volcntl); 1487 } 1488 } 1489 gus_bufcnt[sc->sc_bufcnt-1]++; 1490 /* 1491 * flip to the next DMA buffer 1492 */ 1493 1494 sc->sc_dmabuf = ++sc->sc_dmabuf % sc->sc_nbufs; 1495 /* 1496 * See comments below about DMA admission control strategy. 1497 * We can call the upper level here if we have an 1498 * idle buffer (not currently playing) to DMA into. 1499 */ 1500 if (sc->sc_dmaoutintr && sc->sc_bufcnt < sc->sc_nbufs) { 1501 /* clean out to prevent double calls */ 1502 void (*pfunc) __P((void *)) = sc->sc_dmaoutintr; 1503 void *arg = sc->sc_outarg; 1504 1505 sc->sc_outarg = 0; 1506 sc->sc_dmaoutintr = 0; 1507 (*pfunc)(arg); 1508 } 1509} 1510 1511/* 1512 * Service voice interrupts 1513 */ 1514 1515STATIC int 1516gus_voice_intr(sc) 1517 struct gus_softc *sc; 1518{ 1519 register int port = sc->sc_iobase; 1520 int ignore = 0, voice, rval = 0; 1521 unsigned char intr, status; 1522 1523 /* 1524 * The point of this may not be obvious at first. A voice can 1525 * interrupt more than once; according to the GUS SDK we are supposed 1526 * to ignore multiple interrupts for the same voice. 1527 */ 1528 1529 while(1) { 1530 SELECT_GUS_REG(port, GUSREG_IRQ_STATUS); 1531 intr = inb(port+GUS_DATA_HIGH); 1532 1533 if ((intr & (GUSMASK_WIRQ_VOLUME | GUSMASK_WIRQ_VOICE)) 1534 == (GUSMASK_WIRQ_VOLUME | GUSMASK_WIRQ_VOICE)) 1535 /* 1536 * No more interrupts, time to return 1537 */ 1538 return rval; 1539 1540 if ((intr & GUSMASK_WIRQ_VOICE) == 0) { 1541 1542 /* 1543 * We've got a voice interrupt. Ignore previous 1544 * interrupts by the same voice. 1545 */ 1546 1547 rval = 1; 1548 voice = intr & GUSMASK_WIRQ_VOICEMASK; 1549 1550 if ((1 << voice) & ignore) 1551 break; 1552 1553 ignore |= 1 << voice; 1554 1555 /* 1556 * If the voice is stopped, then force it to stop 1557 * (this stops it from continuously generating IRQs) 1558 */ 1559 1560 SELECT_GUS_REG(port, GUSREG_VOICE_CNTL+0x80); 1561 status = inb(port+GUS_DATA_HIGH); 1562 if (status & GUSMASK_VOICE_STOPPED) { 1563 if (voice != GUS_VOICE_LEFT) { 1564 DMAPRINTF(("%s: spurious voice %d stop?\n", 1565 sc->sc_dev.dv_xname, voice)); 1566 gus_stop_voice(sc, voice, 0); 1567 continue; 1568 } 1569 gus_stop_voice(sc, voice, 1); 1570 /* also kill right voice */ 1571 gus_stop_voice(sc, GUS_VOICE_RIGHT, 0); 1572 sc->sc_bufcnt--; /* it finished a buffer */ 1573 if (sc->sc_bufcnt > 0) { 1574 /* 1575 * probably a race to get here: the voice 1576 * stopped while the DMA code was just trying to 1577 * get the next buffer in place. 1578 * Start the voice again. 1579 */ 1580 printf("%s: stopped voice not drained? (%x)\n", 1581 sc->sc_dev.dv_xname, sc->sc_bufcnt); 1582 gus_falsestops++; 1583 1584 sc->sc_playbuf = ++sc->sc_playbuf % sc->sc_nbufs; 1585 gus_start_playing(sc, sc->sc_playbuf); 1586 } else if (sc->sc_bufcnt < 0) { 1587#ifdef DDB 1588 printf("%s: negative bufcnt in stopped voice\n", 1589 sc->sc_dev.dv_xname); 1590 Debugger(); 1591#else 1592 panic("%s: negative bufcnt in stopped voice", 1593 sc->sc_dev.dv_xname); 1594#endif 1595 } else { 1596 sc->sc_playbuf = -1; /* none are active */ 1597 gus_stops++; 1598 } 1599 /* fall through to callback and admit another 1600 buffer.... */ 1601 } else if (sc->sc_bufcnt != 0) { 1602 /* 1603 * This should always be taken if the voice 1604 * is not stopped. 1605 */ 1606 gus_continues++; 1607 if (gus_continue_playing(sc, voice)) { 1608 /* 1609 * we shouldn't have continued--active DMA 1610 * is in the way in the ring, for 1611 * some as-yet undebugged reason. 1612 */ 1613 gus_stop_voice(sc, GUS_VOICE_LEFT, 1); 1614 /* also kill right voice */ 1615 gus_stop_voice(sc, GUS_VOICE_RIGHT, 0); 1616 sc->sc_playbuf = -1; 1617 gus_stops++; 1618 } 1619 } 1620 /* 1621 * call the upper level to send on down another 1622 * block. We do admission rate control as follows: 1623 * 1624 * When starting up output (in the first N 1625 * blocks), call the upper layer after the DMA is 1626 * complete (see above in gus_dmaout_intr()). 1627 * 1628 * When output is already in progress and we have 1629 * no more GUS buffers to use for DMA, the DMA 1630 * output routines do not call the upper layer. 1631 * Instead, we call the DMA completion routine 1632 * here, after the voice interrupts indicating 1633 * that it's finished with a buffer. 1634 * 1635 * However, don't call anything here if the DMA 1636 * output flag is set, (which shouldn't happen) 1637 * because we'll squish somebody else's DMA if 1638 * that's the case. When DMA is done, it will 1639 * call back if there is a spare buffer. 1640 */ 1641 if (sc->sc_dmaoutintr && !(sc->sc_flags & GUS_LOCKED)) { 1642 if (sc->sc_dmaoutintr == stereo_dmaintr) 1643 printf("gusdmaout botch?\n"); 1644 else { 1645 /* clean out to avoid double calls */ 1646 void (*pfunc) __P((void *)) = sc->sc_dmaoutintr; 1647 void *arg = sc->sc_outarg; 1648 1649 sc->sc_outarg = 0; 1650 sc->sc_dmaoutintr = 0; 1651 (*pfunc)(arg); 1652 } 1653 } 1654 } 1655 1656 /* 1657 * Ignore other interrupts for now 1658 */ 1659 } 1660 return 0; 1661} 1662 1663STATIC void 1664gus_start_playing(sc, bufno) 1665struct gus_softc *sc; 1666int bufno; 1667{ 1668 register int port = sc->sc_iobase; 1669 /* 1670 * Start the voices playing, with buffer BUFNO. 1671 */ 1672 1673 /* 1674 * Loop or roll if we have buffers ready. 1675 */ 1676 1677 if (sc->sc_bufcnt == 1) { 1678 sc->sc_voc[GUS_VOICE_LEFT].voccntl &= ~(GUSMASK_LOOP_ENABLE); 1679 sc->sc_voc[GUS_VOICE_LEFT].volcntl &= ~(GUSMASK_VOICE_ROLL); 1680 } else { 1681 if (bufno == sc->sc_nbufs - 1) { 1682 sc->sc_voc[GUS_VOICE_LEFT].voccntl |= GUSMASK_LOOP_ENABLE; 1683 sc->sc_voc[GUS_VOICE_LEFT].volcntl &= ~(GUSMASK_VOICE_ROLL); 1684 } else { 1685 sc->sc_voc[GUS_VOICE_LEFT].voccntl &= ~GUSMASK_LOOP_ENABLE; 1686 sc->sc_voc[GUS_VOICE_LEFT].volcntl |= GUSMASK_VOICE_ROLL; 1687 } 1688 } 1689 1690 outb(port+GUS_VOICE_SELECT, GUS_VOICE_LEFT); 1691 1692 SELECT_GUS_REG(port, GUSREG_VOICE_CNTL); 1693 outb(port+GUS_DATA_HIGH, sc->sc_voc[GUS_VOICE_LEFT].voccntl); 1694 1695 SELECT_GUS_REG(port, GUSREG_VOLUME_CONTROL); 1696 outb(port+GUS_DATA_HIGH, sc->sc_voc[GUS_VOICE_LEFT].volcntl); 1697 1698 sc->sc_voc[GUS_VOICE_LEFT].current_addr = 1699 GUS_MEM_OFFSET + sc->sc_chanblocksize * bufno; 1700 sc->sc_voc[GUS_VOICE_LEFT].end_addr = 1701 sc->sc_voc[GUS_VOICE_LEFT].current_addr + sc->sc_chanblocksize - 1; 1702 sc->sc_voc[GUS_VOICE_RIGHT].current_addr = 1703 sc->sc_voc[GUS_VOICE_LEFT].current_addr + 1704 (gus_dostereo && sc->sc_channels == 2 ? GUS_LEFT_RIGHT_OFFSET : 0); 1705 /* 1706 * set up right channel to just loop forever, no interrupts, 1707 * starting at the buffer we just filled. We'll feed it data 1708 * at the same time as left channel. 1709 */ 1710 sc->sc_voc[GUS_VOICE_RIGHT].voccntl |= GUSMASK_LOOP_ENABLE; 1711 sc->sc_voc[GUS_VOICE_RIGHT].volcntl &= ~(GUSMASK_VOICE_ROLL); 1712 1713#ifdef GUSPLAYDEBUG 1714 if (gusstats) { 1715 microtime(&playstats[playcntr].tv); 1716 playstats[playcntr].curaddr = sc->sc_voc[GUS_VOICE_LEFT].current_addr; 1717 1718 playstats[playcntr].voccntl = sc->sc_voc[GUS_VOICE_LEFT].voccntl; 1719 playstats[playcntr].volcntl = sc->sc_voc[GUS_VOICE_LEFT].volcntl; 1720 playstats[playcntr].endaddr = sc->sc_voc[GUS_VOICE_LEFT].end_addr; 1721 playstats[playcntr].playbuf = bufno; 1722 playstats[playcntr].dmabuf = sc->sc_dmabuf; 1723 playstats[playcntr].bufcnt = sc->sc_bufcnt; 1724 playstats[playcntr].vaction = 5; 1725 playcntr = ++playcntr % NDMARECS; 1726 } 1727#endif 1728 1729 outb(port+GUS_VOICE_SELECT, GUS_VOICE_RIGHT); 1730 SELECT_GUS_REG(port, GUSREG_VOICE_CNTL); 1731 outb(port+GUS_DATA_HIGH, sc->sc_voc[GUS_VOICE_RIGHT].voccntl); 1732 SELECT_GUS_REG(port, GUSREG_VOLUME_CONTROL); 1733 outb(port+GUS_DATA_HIGH, sc->sc_voc[GUS_VOICE_RIGHT].volcntl); 1734 1735 gus_start_voice(sc, GUS_VOICE_RIGHT, 0); 1736 gus_start_voice(sc, GUS_VOICE_LEFT, 1); 1737 if (sc->sc_playbuf == -1) 1738 /* mark start of playing */ 1739 sc->sc_playbuf = bufno; 1740} 1741 1742STATIC int 1743gus_continue_playing(sc, voice) 1744register struct gus_softc *sc; 1745int voice; 1746{ 1747 register int port = sc->sc_iobase; 1748 1749 /* 1750 * stop this voice from interrupting while we work. 1751 */ 1752 1753 SELECT_GUS_REG(port, GUSREG_VOICE_CNTL); 1754 outb(port+GUS_DATA_HIGH, sc->sc_voc[voice].voccntl & ~(GUSMASK_VOICE_IRQ)); 1755 1756 /* 1757 * update playbuf to point to the buffer the hardware just started 1758 * playing 1759 */ 1760 sc->sc_playbuf = ++sc->sc_playbuf % sc->sc_nbufs; 1761 1762 /* 1763 * account for buffer just finished 1764 */ 1765 if (--sc->sc_bufcnt == 0) { 1766 DPRINTF(("gus: bufcnt 0 on continuing voice?\n")); 1767 } 1768 if (sc->sc_playbuf == sc->sc_dmabuf && (sc->sc_flags & GUS_LOCKED)) { 1769 printf("%s: continue into active dmabuf?\n", sc->sc_dev.dv_xname); 1770 return 1; 1771 } 1772 1773 /* 1774 * Select the end of the buffer based on the currently active 1775 * buffer, [plus extra contiguous buffers (if ready)]. 1776 */ 1777 1778 /* 1779 * set endpoint at end of buffer we just started playing. 1780 * 1781 * The total gets -1 because end addrs are one less than you might 1782 * think (the end_addr is the address of the last sample to play) 1783 */ 1784 gus_set_endaddr(sc, voice, GUS_MEM_OFFSET + 1785 sc->sc_chanblocksize * (sc->sc_playbuf + 1) - 1); 1786 1787 if (sc->sc_bufcnt < 2) { 1788 /* 1789 * Clear out the loop and roll flags, and rotate the currently 1790 * playing buffer. That way, if we don't manage to get more 1791 * data before this buffer finishes, we'll just stop. 1792 */ 1793 sc->sc_voc[voice].voccntl &= ~GUSMASK_LOOP_ENABLE; 1794 sc->sc_voc[voice].volcntl &= ~GUSMASK_VOICE_ROLL; 1795 playstats[playcntr].vaction = 0; 1796 } else { 1797 /* 1798 * We have some buffers to play. set LOOP if we're on the 1799 * last buffer in the ring, otherwise set ROLL. 1800 */ 1801 if (sc->sc_playbuf == sc->sc_nbufs - 1) { 1802 sc->sc_voc[voice].voccntl |= GUSMASK_LOOP_ENABLE; 1803 sc->sc_voc[voice].volcntl &= ~GUSMASK_VOICE_ROLL; 1804 playstats[playcntr].vaction = 1; 1805 } else { 1806 sc->sc_voc[voice].voccntl &= ~GUSMASK_LOOP_ENABLE; 1807 sc->sc_voc[voice].volcntl |= GUSMASK_VOICE_ROLL; 1808 playstats[playcntr].vaction = 2; 1809 } 1810 } 1811#ifdef GUSPLAYDEBUG 1812 if (gusstats) { 1813 microtime(&playstats[playcntr].tv); 1814 playstats[playcntr].curaddr = gus_get_curaddr(sc, voice); 1815 1816 playstats[playcntr].voccntl = sc->sc_voc[voice].voccntl; 1817 playstats[playcntr].volcntl = sc->sc_voc[voice].volcntl; 1818 playstats[playcntr].endaddr = sc->sc_voc[voice].end_addr; 1819 playstats[playcntr].playbuf = sc->sc_playbuf; 1820 playstats[playcntr].dmabuf = sc->sc_dmabuf; 1821 playstats[playcntr].bufcnt = sc->sc_bufcnt; 1822 playcntr = ++playcntr % NDMARECS; 1823 } 1824#endif 1825 1826 /* 1827 * (re-)set voice parameters. This will reenable interrupts from this 1828 * voice. 1829 */ 1830 1831 SELECT_GUS_REG(port, GUSREG_VOICE_CNTL); 1832 outb(port+GUS_DATA_HIGH, sc->sc_voc[voice].voccntl); 1833 SELECT_GUS_REG(port, GUSREG_VOLUME_CONTROL); 1834 outb(port+GUS_DATA_HIGH, sc->sc_voc[voice].volcntl); 1835 return 0; 1836} 1837 1838/* 1839 * Send/receive data into GUS's DRAM using DMA. Called at splgus() 1840 */ 1841 1842STATIC void 1843gusdmaout(sc, flags, gusaddr, buffaddr, length) 1844 struct gus_softc *sc; 1845 int flags, length; 1846 u_long gusaddr; 1847 caddr_t buffaddr; 1848{ 1849 register unsigned char c = (unsigned char) flags; 1850 register int port = sc->sc_iobase; 1851 1852 DMAPRINTF(("gusdmaout flags=%x scflags=%x\n", flags, sc->sc_flags)); 1853 1854 sc->sc_gusaddr = gusaddr; 1855 1856 /* 1857 * If we're using a 16 bit DMA channel, we have to jump through some 1858 * extra hoops; this includes translating the DRAM address a bit 1859 */ 1860 1861 if (sc->sc_drq >= 4) { 1862 c |= GUSMASK_DMA_WIDTH; 1863 gusaddr = convert_to_16bit(gusaddr); 1864 } 1865 1866 /* 1867 * Add flag bits that we always set - fast DMA, enable IRQ 1868 */ 1869 1870 c |= GUSMASK_DMA_ENABLE | GUSMASK_DMA_R0 | GUSMASK_DMA_IRQ; 1871 1872 /* 1873 * Make sure the GUS _isn't_ setup for DMA 1874 */ 1875 1876 SELECT_GUS_REG(port, GUSREG_DMA_CONTROL); 1877 outb(port+GUS_DATA_HIGH, 0); 1878 1879 /* 1880 * Tell the PC DMA controller to start doing DMA 1881 */ 1882 1883 sc->sc_dmaoutaddr = (u_char *) buffaddr; 1884 sc->sc_dmaoutcnt = length; 1885 isa_dmastart(sc->sc_dev.dv_parent, sc->sc_drq, buffaddr, length, 1886 NULL, DMAMODE_WRITE, BUS_DMA_NOWAIT); 1887 1888 /* 1889 * Set up DMA address - use the upper 16 bits ONLY 1890 */ 1891 1892 sc->sc_flags |= GUS_DMAOUT_ACTIVE; 1893 1894 SELECT_GUS_REG(port, GUSREG_DMA_START); 1895 outw(port+GUS_DATA_LOW, (int) (gusaddr >> 4)); 1896 1897 /* 1898 * Tell the GUS to start doing DMA 1899 */ 1900 1901 SELECT_GUS_REG(port, GUSREG_DMA_CONTROL); 1902 outb(port+GUS_DATA_HIGH, c); 1903 1904 /* 1905 * XXX If we don't finish in one second, give up... 1906 */ 1907 untimeout(gus_dmaout_timeout, sc); /* flush old one, if there is one */ 1908 timeout(gus_dmaout_timeout, sc, hz); 1909} 1910 1911/* 1912 * Start a voice playing on the GUS. Called from interrupt handler at 1913 * splgus(). 1914 */ 1915 1916STATIC void 1917gus_start_voice(sc, voice, intrs) 1918 struct gus_softc *sc; 1919 int voice; 1920 int intrs; 1921{ 1922 register int port = sc->sc_iobase; 1923 u_long start; 1924 u_long current; 1925 u_long end; 1926 1927 /* 1928 * Pick all the values for the voice out of the gus_voice struct 1929 * and use those to program the voice 1930 */ 1931 1932 start = sc->sc_voc[voice].start_addr; 1933 current = sc->sc_voc[voice].current_addr; 1934 end = sc->sc_voc[voice].end_addr; 1935 1936 /* 1937 * If we're using 16 bit data, mangle the addresses a bit 1938 */ 1939 1940 if (sc->sc_voc[voice].voccntl & GUSMASK_DATA_SIZE16) { 1941 /* -1 on start so that we get onto sample boundary--other 1942 code always sets it for 1-byte rollover protection */ 1943 start = convert_to_16bit(start-1); 1944 current = convert_to_16bit(current); 1945 end = convert_to_16bit(end); 1946 } 1947 1948 /* 1949 * Select the voice we want to use, and program the data addresses 1950 */ 1951 1952 outb(port+GUS_VOICE_SELECT, (unsigned char) voice); 1953 1954 SELECT_GUS_REG(port, GUSREG_START_ADDR_HIGH); 1955 outw(port+GUS_DATA_LOW, ADDR_HIGH(start)); 1956 SELECT_GUS_REG(port, GUSREG_START_ADDR_LOW); 1957 outw(port+GUS_DATA_LOW, ADDR_LOW(start)); 1958 1959 SELECT_GUS_REG(port, GUSREG_CUR_ADDR_HIGH); 1960 outw(port+GUS_DATA_LOW, ADDR_HIGH(current)); 1961 SELECT_GUS_REG(port, GUSREG_CUR_ADDR_LOW); 1962 outw(port+GUS_DATA_LOW, ADDR_LOW(current)); 1963 1964 SELECT_GUS_REG(port, GUSREG_END_ADDR_HIGH); 1965 outw(port+GUS_DATA_LOW, ADDR_HIGH(end)); 1966 SELECT_GUS_REG(port, GUSREG_END_ADDR_LOW); 1967 outw(port+GUS_DATA_LOW, ADDR_LOW(end)); 1968 1969 /* 1970 * (maybe) enable interrupts, disable voice stopping 1971 */ 1972 1973 if (intrs) { 1974 sc->sc_flags |= GUS_PLAYING; /* playing is about to start */ 1975 sc->sc_voc[voice].voccntl |= GUSMASK_VOICE_IRQ; 1976 DMAPRINTF(("gus voice playing=%x\n", sc->sc_flags)); 1977 } else 1978 sc->sc_voc[voice].voccntl &= ~GUSMASK_VOICE_IRQ; 1979 sc->sc_voc[voice].voccntl &= ~(GUSMASK_VOICE_STOPPED | 1980 GUSMASK_STOP_VOICE); 1981 1982 /* 1983 * Tell the GUS about it. Note that we're doing volume ramping here 1984 * from 0 up to the set volume to help reduce clicks. 1985 */ 1986 1987 SELECT_GUS_REG(port, GUSREG_START_VOLUME); 1988 outb(port+GUS_DATA_HIGH, 0x00); 1989 SELECT_GUS_REG(port, GUSREG_END_VOLUME); 1990 outb(port+GUS_DATA_HIGH, sc->sc_voc[voice].current_volume >> 4); 1991 SELECT_GUS_REG(port, GUSREG_CUR_VOLUME); 1992 outw(port+GUS_DATA_LOW, 0x00); 1993 SELECT_GUS_REG(port, GUSREG_VOLUME_RATE); 1994 outb(port+GUS_DATA_HIGH, 63); 1995 1996 SELECT_GUS_REG(port, GUSREG_VOICE_CNTL); 1997 outb(port+GUS_DATA_HIGH, sc->sc_voc[voice].voccntl); 1998 SELECT_GUS_REG(port, GUSREG_VOLUME_CONTROL); 1999 outb(port+GUS_DATA_HIGH, 0x00); 2000 delay(50); 2001 SELECT_GUS_REG(port, GUSREG_VOICE_CNTL); 2002 outb(port+GUS_DATA_HIGH, sc->sc_voc[voice].voccntl); 2003 SELECT_GUS_REG(port, GUSREG_VOLUME_CONTROL); 2004 outb(port+GUS_DATA_HIGH, 0x00); 2005 2006} 2007 2008/* 2009 * Stop a given voice. called at splgus() 2010 */ 2011 2012STATIC void 2013gus_stop_voice(sc, voice, intrs_too) 2014 struct gus_softc *sc; 2015 int voice; 2016 int intrs_too; 2017{ 2018 register int port = sc->sc_iobase; 2019 2020 sc->sc_voc[voice].voccntl |= GUSMASK_VOICE_STOPPED | 2021 GUSMASK_STOP_VOICE; 2022 if (intrs_too) { 2023 sc->sc_voc[voice].voccntl &= ~(GUSMASK_VOICE_IRQ); 2024 /* no more DMA to do */ 2025 sc->sc_flags &= ~GUS_PLAYING; 2026 } 2027 DMAPRINTF(("gusintr voice notplaying=%x\n", sc->sc_flags)); 2028 2029 guspoke(port, 0L, 0); 2030 2031 outb(port+GUS_VOICE_SELECT, (unsigned char) voice); 2032 2033 SELECT_GUS_REG(port, GUSREG_CUR_VOLUME); 2034 outw(port+GUS_DATA_LOW, 0x0000); 2035 SELECT_GUS_REG(port, GUSREG_VOICE_CNTL); 2036 outb(port+GUS_DATA_HIGH, sc->sc_voc[voice].voccntl); 2037 delay(100); 2038 SELECT_GUS_REG(port, GUSREG_CUR_VOLUME); 2039 outw(port+GUS_DATA_LOW, 0x0000); 2040 SELECT_GUS_REG(port, GUSREG_VOICE_CNTL); 2041 outb(port+GUS_DATA_HIGH, sc->sc_voc[voice].voccntl); 2042 2043 SELECT_GUS_REG(port, GUSREG_CUR_ADDR_HIGH); 2044 outw(port+GUS_DATA_LOW, 0x0000); 2045 SELECT_GUS_REG(port, GUSREG_CUR_ADDR_LOW); 2046 outw(port+GUS_DATA_LOW, 0x0000); 2047 2048} 2049 2050 2051/* 2052 * Set the volume of a given voice. Called at splgus(). 2053 */ 2054STATIC void 2055gus_set_volume(sc, voice, volume) 2056 struct gus_softc *sc; 2057 int voice, volume; 2058{ 2059 register int port = sc->sc_iobase; 2060 unsigned int gusvol; 2061 2062 gusvol = gus_log_volumes[volume < 512 ? volume : 511]; 2063 2064 sc->sc_voc[voice].current_volume = gusvol; 2065 2066 outb(port+GUS_VOICE_SELECT, (unsigned char) voice); 2067 2068 SELECT_GUS_REG(port, GUSREG_START_VOLUME); 2069 outb(port+GUS_DATA_HIGH, (unsigned char) (gusvol >> 4)); 2070 2071 SELECT_GUS_REG(port, GUSREG_END_VOLUME); 2072 outb(port+GUS_DATA_HIGH, (unsigned char) (gusvol >> 4)); 2073 2074 SELECT_GUS_REG(port, GUSREG_CUR_VOLUME); 2075 outw(port+GUS_DATA_LOW, gusvol << 4); 2076 delay(500); 2077 outw(port+GUS_DATA_LOW, gusvol << 4); 2078 2079} 2080 2081/* 2082 * Interface to the audio layer. 2083 */ 2084 2085int 2086gusmax_set_params(addr, mode, p, q) 2087 void *addr; 2088 int mode; 2089 struct audio_params *p, *q; 2090{ 2091 register struct ad1848_softc *ac = addr; 2092 register struct gus_softc *sc = ac->parent; 2093 int error; 2094 2095 error = ad1848_set_params(ac, mode, p, q); 2096 if (error) 2097 return error; 2098 error = gus_set_params(sc, mode, p, q); 2099 return error; 2100} 2101 2102int 2103gus_set_params(addr, mode, p, q) 2104 void *addr; 2105 int mode; 2106 struct audio_params *p, *q; 2107{ 2108 register struct gus_softc *sc = addr; 2109 int s; 2110 2111 switch (p->encoding) { 2112 case AUDIO_ENCODING_ULAW: 2113 case AUDIO_ENCODING_SLINEAR_LE: 2114 case AUDIO_ENCODING_ULINEAR_LE: 2115 case AUDIO_ENCODING_SLINEAR_BE: 2116 case AUDIO_ENCODING_ULINEAR_BE: 2117 break; 2118 default: 2119 return (EINVAL); 2120 } 2121 2122 s = splaudio(); 2123 2124 if (p->precision == 8) { 2125 sc->sc_voc[GUS_VOICE_LEFT].voccntl &= ~GUSMASK_DATA_SIZE16; 2126 sc->sc_voc[GUS_VOICE_RIGHT].voccntl &= ~GUSMASK_DATA_SIZE16; 2127 } else { 2128 sc->sc_voc[GUS_VOICE_LEFT].voccntl |= GUSMASK_DATA_SIZE16; 2129 sc->sc_voc[GUS_VOICE_RIGHT].voccntl |= GUSMASK_DATA_SIZE16; 2130 } 2131 2132 sc->sc_encoding = p->encoding; 2133 sc->sc_precision = p->precision; 2134 sc->sc_channels = p->channels; 2135 2136 splx(s); 2137 2138 if (p->sample_rate > gus_max_frequency[sc->sc_voices - GUS_MIN_VOICES]) 2139 p->sample_rate = gus_max_frequency[sc->sc_voices - GUS_MIN_VOICES]; 2140 if (mode == AUMODE_RECORD) 2141 sc->sc_irate = p->sample_rate; 2142 else 2143 sc->sc_orate = p->sample_rate; 2144 2145 switch (p->encoding) { 2146 case AUDIO_ENCODING_ULAW: 2147 p->sw_code = mode == AUMODE_PLAY ? 2148 mulaw_to_ulinear8 : ulinear8_to_mulaw; 2149 break; 2150 case AUDIO_ENCODING_ULINEAR_BE: 2151 case AUDIO_ENCODING_SLINEAR_BE: 2152 p->sw_code = swap_bytes; 2153 break; 2154 default: 2155 p->sw_code = 0; 2156 } 2157 2158 /* Update setting for the other mode. */ 2159 q->encoding = p->encoding; 2160 q->channels = p->channels; 2161 q->precision = p->precision; 2162 return 0; 2163} 2164 2165/* 2166 * Interface to the audio layer - set the blocksize to the correct number 2167 * of units 2168 */ 2169 2170int 2171gusmax_round_blocksize(addr, blocksize) 2172 void * addr; 2173 int blocksize; 2174{ 2175 register struct ad1848_softc *ac = addr; 2176 register struct gus_softc *sc = ac->parent; 2177 2178/* blocksize = ad1848_round_blocksize(ac, blocksize);*/ 2179 return gus_round_blocksize(sc, blocksize); 2180} 2181 2182int 2183gus_round_blocksize(addr, blocksize) 2184 void * addr; 2185 int blocksize; 2186{ 2187 register struct gus_softc *sc = addr; 2188 2189 DPRINTF(("gus_round_blocksize called\n")); 2190 2191 if (sc->sc_encoding == AUDIO_ENCODING_ULAW && blocksize > 32768) 2192 blocksize = 32768; 2193 else if (blocksize > 65536) 2194 blocksize = 65536; 2195 2196 if ((blocksize % GUS_BUFFER_MULTIPLE) != 0) 2197 blocksize = (blocksize / GUS_BUFFER_MULTIPLE + 1) * 2198 GUS_BUFFER_MULTIPLE; 2199 2200 /* set up temporary buffer to hold the deinterleave, if necessary 2201 for stereo output */ 2202 if (sc->sc_deintr_buf) { 2203 FREE(sc->sc_deintr_buf, M_DEVBUF); 2204 sc->sc_deintr_buf = NULL; 2205 } 2206 MALLOC(sc->sc_deintr_buf, void *, blocksize>>1, M_DEVBUF, M_WAITOK); 2207 2208 sc->sc_blocksize = blocksize; 2209 /* multi-buffering not quite working yet. */ 2210 sc->sc_nbufs = /*GUS_MEM_FOR_BUFFERS / blocksize*/ 2; 2211 2212 gus_set_chan_addrs(sc); 2213 2214 return blocksize; 2215} 2216 2217int 2218gus_get_out_gain(addr) 2219 caddr_t addr; 2220{ 2221 register struct gus_softc *sc = (struct gus_softc *) addr; 2222 2223 DPRINTF(("gus_get_out_gain called\n")); 2224 return sc->sc_ogain / 2; 2225} 2226 2227STATIC inline void gus_set_voices(sc, voices) 2228struct gus_softc *sc; 2229int voices; 2230{ 2231 register int port = sc->sc_iobase; 2232 /* 2233 * Select the active number of voices 2234 */ 2235 2236 SELECT_GUS_REG(port, GUSREG_ACTIVE_VOICES); 2237 outb(port+GUS_DATA_HIGH, (voices-1) | 0xc0); 2238 2239 sc->sc_voices = voices; 2240} 2241 2242/* 2243 * Actually set the settings of various values on the card 2244 */ 2245 2246int 2247gusmax_commit_settings(addr) 2248 void * addr; 2249{ 2250 register struct ad1848_softc *ac = addr; 2251 register struct gus_softc *sc = ac->parent; 2252 2253 (void) ad1848_commit_settings(ac); 2254 return gus_commit_settings(sc); 2255} 2256 2257/* 2258 * Commit the settings. Called at normal IPL. 2259 */ 2260int 2261gus_commit_settings(addr) 2262 void * addr; 2263{ 2264 register struct gus_softc *sc = addr; 2265 int s; 2266 2267 DPRINTF(("gus_commit_settings called (gain = %d)\n",sc->sc_ogain)); 2268 2269 2270 s = splgus(); 2271 2272 gus_set_recrate(sc, sc->sc_irate); 2273 gus_set_volume(sc, GUS_VOICE_LEFT, sc->sc_ogain); 2274 gus_set_volume(sc, GUS_VOICE_RIGHT, sc->sc_ogain); 2275 gus_set_samprate(sc, GUS_VOICE_LEFT, sc->sc_orate); 2276 gus_set_samprate(sc, GUS_VOICE_RIGHT, sc->sc_orate); 2277 splx(s); 2278 gus_set_chan_addrs(sc); 2279 2280 return 0; 2281} 2282 2283STATIC void 2284gus_set_chan_addrs(sc) 2285struct gus_softc *sc; 2286{ 2287 /* 2288 * We use sc_nbufs * blocksize bytes of storage in the on-board GUS 2289 * ram. 2290 * For mono, each of the sc_nbufs buffers is DMA'd to in one chunk, 2291 * and both left & right channels play the same buffer. 2292 * 2293 * For stereo, each channel gets a contiguous half of the memory, 2294 * and each has sc_nbufs buffers of size blocksize/2. 2295 * Stereo data are deinterleaved in main memory before the DMA out 2296 * routines are called to queue the output. 2297 * 2298 * The blocksize per channel is kept in sc_chanblocksize. 2299 */ 2300 if (sc->sc_channels == 2) 2301 sc->sc_chanblocksize = sc->sc_blocksize/2; 2302 else 2303 sc->sc_chanblocksize = sc->sc_blocksize; 2304 2305 sc->sc_voc[GUS_VOICE_LEFT].start_addr = GUS_MEM_OFFSET - 1; 2306 sc->sc_voc[GUS_VOICE_RIGHT].start_addr = 2307 (gus_dostereo && sc->sc_channels == 2 ? GUS_LEFT_RIGHT_OFFSET : 0) 2308 + GUS_MEM_OFFSET - 1; 2309 sc->sc_voc[GUS_VOICE_RIGHT].current_addr = 2310 sc->sc_voc[GUS_VOICE_RIGHT].start_addr + 1; 2311 sc->sc_voc[GUS_VOICE_RIGHT].end_addr = 2312 sc->sc_voc[GUS_VOICE_RIGHT].start_addr + 2313 sc->sc_nbufs * sc->sc_chanblocksize; 2314 2315} 2316 2317/* 2318 * Set the sample rate of the given voice. Called at splgus(). 2319 */ 2320 2321STATIC void 2322gus_set_samprate(sc, voice, freq) 2323 struct gus_softc *sc; 2324 int voice, freq; 2325{ 2326 register int port = sc->sc_iobase; 2327 unsigned int fc; 2328 u_long temp, f = (u_long) freq; 2329 2330 /* 2331 * calculate fc based on the number of active voices; 2332 * we need to use longs to preserve enough bits 2333 */ 2334 2335 temp = (u_long) gus_max_frequency[sc->sc_voices-GUS_MIN_VOICES]; 2336 2337 fc = (unsigned int)(((f << 9L) + (temp >> 1L)) / temp); 2338 2339 fc <<= 1; 2340 2341 2342 /* 2343 * Program the voice frequency, and set it in the voice data record 2344 */ 2345 2346 outb(port+GUS_VOICE_SELECT, (unsigned char) voice); 2347 SELECT_GUS_REG(port, GUSREG_FREQ_CONTROL); 2348 outw(port+GUS_DATA_LOW, fc); 2349 2350 sc->sc_voc[voice].rate = freq; 2351 2352} 2353 2354/* 2355 * Set the sample rate of the recording frequency. Formula is from the GUS 2356 * SDK. Called at splgus(). 2357 */ 2358 2359STATIC void 2360gus_set_recrate(sc, rate) 2361 struct gus_softc *sc; 2362 u_long rate; 2363{ 2364 register int port = sc->sc_iobase; 2365 u_char realrate; 2366 DPRINTF(("gus_set_recrate %lu\n", rate)); 2367 2368#if 0 2369 realrate = 9878400/(16*(rate+2)); /* formula from GUS docs */ 2370#endif 2371 realrate = (9878400 >> 4)/rate - 2; /* formula from code, sigh. */ 2372 2373 SELECT_GUS_REG(port, GUSREG_SAMPLE_FREQ); 2374 outb(port+GUS_DATA_HIGH, realrate); 2375} 2376 2377/* 2378 * Interface to the audio layer - turn the output on or off. Note that some 2379 * of these bits are flipped in the register 2380 */ 2381 2382int 2383gusmax_speaker_ctl(addr, newstate) 2384 void * addr; 2385 int newstate; 2386{ 2387 register struct ad1848_softc *sc = addr; 2388 return gus_speaker_ctl(sc->parent, newstate); 2389} 2390 2391int 2392gus_speaker_ctl(addr, newstate) 2393 void * addr; 2394 int newstate; 2395{ 2396 register struct gus_softc *sc = (struct gus_softc *) addr; 2397 2398 /* Line out bit is flipped: 0 enables, 1 disables */ 2399 if ((newstate == SPKR_ON) && 2400 (sc->sc_mixcontrol & GUSMASK_LINE_OUT)) { 2401 sc->sc_mixcontrol &= ~GUSMASK_LINE_OUT; 2402 outb(sc->sc_iobase+GUS_MIX_CONTROL, sc->sc_mixcontrol); 2403 } 2404 if ((newstate == SPKR_OFF) && 2405 (sc->sc_mixcontrol & GUSMASK_LINE_OUT) == 0) { 2406 sc->sc_mixcontrol |= GUSMASK_LINE_OUT; 2407 outb(sc->sc_iobase+GUS_MIX_CONTROL, sc->sc_mixcontrol); 2408 } 2409 2410 return 0; 2411} 2412 2413STATIC int 2414gus_linein_ctl(addr, newstate) 2415 void * addr; 2416 int newstate; 2417{ 2418 register struct gus_softc *sc = (struct gus_softc *) addr; 2419 2420 /* Line in bit is flipped: 0 enables, 1 disables */ 2421 if ((newstate == SPKR_ON) && 2422 (sc->sc_mixcontrol & GUSMASK_LINE_IN)) { 2423 sc->sc_mixcontrol &= ~GUSMASK_LINE_IN; 2424 outb(sc->sc_iobase+GUS_MIX_CONTROL, sc->sc_mixcontrol); 2425 } 2426 if ((newstate == SPKR_OFF) && 2427 (sc->sc_mixcontrol & GUSMASK_LINE_IN) == 0) { 2428 sc->sc_mixcontrol |= GUSMASK_LINE_IN; 2429 outb(sc->sc_iobase+GUS_MIX_CONTROL, sc->sc_mixcontrol); 2430 } 2431 2432 return 0; 2433} 2434 2435STATIC int 2436gus_mic_ctl(addr, newstate) 2437 void * addr; 2438 int newstate; 2439{ 2440 register struct gus_softc *sc = (struct gus_softc *) addr; 2441 2442 /* Mic bit is normal: 1 enables, 0 disables */ 2443 if ((newstate == SPKR_ON) && 2444 (sc->sc_mixcontrol & GUSMASK_MIC_IN) == 0) { 2445 sc->sc_mixcontrol |= GUSMASK_MIC_IN; 2446 outb(sc->sc_iobase+GUS_MIX_CONTROL, sc->sc_mixcontrol); 2447 } 2448 if ((newstate == SPKR_OFF) && 2449 (sc->sc_mixcontrol & GUSMASK_MIC_IN)) { 2450 sc->sc_mixcontrol &= ~GUSMASK_MIC_IN; 2451 outb(sc->sc_iobase+GUS_MIX_CONTROL, sc->sc_mixcontrol); 2452 } 2453 2454 return 0; 2455} 2456 2457/* 2458 * Set the end address of a give voice. Called at splgus() 2459 */ 2460 2461STATIC void 2462gus_set_endaddr(sc, voice, addr) 2463 struct gus_softc *sc; 2464 int voice; 2465 u_long addr; 2466{ 2467 register int port = sc->sc_iobase; 2468 2469 sc->sc_voc[voice].end_addr = addr; 2470 2471 if (sc->sc_voc[voice].voccntl & GUSMASK_DATA_SIZE16) 2472 addr = convert_to_16bit(addr); 2473 2474 SELECT_GUS_REG(port, GUSREG_END_ADDR_HIGH); 2475 outw(port+GUS_DATA_LOW, ADDR_HIGH(addr)); 2476 SELECT_GUS_REG(port, GUSREG_END_ADDR_LOW); 2477 outw(port+GUS_DATA_LOW, ADDR_LOW(addr)); 2478 2479} 2480 2481#ifdef GUSPLAYDEBUG 2482/* 2483 * Set current address. called at splgus() 2484 */ 2485STATIC void 2486gus_set_curaddr(sc, voice, addr) 2487 struct gus_softc *sc; 2488 int voice; 2489 u_long addr; 2490{ 2491 register int port = sc->sc_iobase; 2492 2493 sc->sc_voc[voice].current_addr = addr; 2494 2495 if (sc->sc_voc[voice].voccntl & GUSMASK_DATA_SIZE16) 2496 addr = convert_to_16bit(addr); 2497 2498 outb(port+GUS_VOICE_SELECT, (unsigned char) voice); 2499 2500 SELECT_GUS_REG(port, GUSREG_CUR_ADDR_HIGH); 2501 outw(port+GUS_DATA_LOW, ADDR_HIGH(addr)); 2502 SELECT_GUS_REG(port, GUSREG_CUR_ADDR_LOW); 2503 outw(port+GUS_DATA_LOW, ADDR_LOW(addr)); 2504 2505} 2506 2507/* 2508 * Get current GUS playback address. Called at splgus(). 2509 */ 2510STATIC u_long 2511gus_get_curaddr(sc, voice) 2512 struct gus_softc *sc; 2513 int voice; 2514{ 2515 register int port = sc->sc_iobase; 2516 u_long addr; 2517 2518 outb(port+GUS_VOICE_SELECT, (unsigned char) voice); 2519 SELECT_GUS_REG(port, GUSREG_CUR_ADDR_HIGH|GUSREG_READ); 2520 addr = (inw(port+GUS_DATA_LOW) & 0x1fff) << 7; 2521 SELECT_GUS_REG(port, GUSREG_CUR_ADDR_LOW|GUSREG_READ); 2522 addr |= (inw(port+GUS_DATA_LOW) >> 9L) & 0x7f; 2523 2524 if (sc->sc_voc[voice].voccntl & GUSMASK_DATA_SIZE16) 2525 addr = (addr & 0xc0000) | ((addr & 0x1ffff) << 1); /* undo 16-bit change */ 2526 DPRINTF(("gus voice %d curaddr %ld end_addr %ld\n", 2527 voice, addr, sc->sc_voc[voice].end_addr)); 2528 /* XXX sanity check the address? */ 2529 2530 return(addr); 2531} 2532#endif 2533 2534/* 2535 * Convert an address value to a "16 bit" value - why this is necessary I 2536 * have NO idea 2537 */ 2538 2539STATIC u_long 2540convert_to_16bit(address) 2541 u_long address; 2542{ 2543 u_long old_address; 2544 2545 old_address = address; 2546 address >>= 1; 2547 address &= 0x0001ffffL; 2548 address |= (old_address & 0x000c0000L); 2549 2550 return (address); 2551} 2552 2553/* 2554 * Write a value into the GUS's DRAM 2555 */ 2556 2557STATIC void 2558guspoke(port, address, value) 2559 int port; 2560 long address; 2561 unsigned char value; 2562{ 2563 2564 /* 2565 * Select the DRAM address 2566 */ 2567 2568 SELECT_GUS_REG(port, GUSREG_DRAM_ADDR_LOW); 2569 outw(port+GUS_DATA_LOW, (unsigned int) (address & 0xffff)); 2570 SELECT_GUS_REG(port, GUSREG_DRAM_ADDR_HIGH); 2571 outb(port+GUS_DATA_HIGH, (unsigned char) ((address >> 16) & 0xff)); 2572 2573 /* 2574 * Actually write the data 2575 */ 2576 2577 outb(port+GUS_DRAM_DATA, value); 2578} 2579 2580/* 2581 * Read a value from the GUS's DRAM 2582 */ 2583 2584STATIC unsigned char 2585guspeek(port, address) 2586 int port; 2587 u_long address; 2588{ 2589 2590 /* 2591 * Select the DRAM address 2592 */ 2593 2594 SELECT_GUS_REG(port, GUSREG_DRAM_ADDR_LOW); 2595 outw(port+GUS_DATA_LOW, (unsigned int) (address & 0xffff)); 2596 SELECT_GUS_REG(port, GUSREG_DRAM_ADDR_HIGH); 2597 outb(port+GUS_DATA_HIGH, (unsigned char) ((address >> 16) & 0xff)); 2598 2599 /* 2600 * Read in the data from the board 2601 */ 2602 2603 return (unsigned char) inb(port+GUS_DRAM_DATA); 2604} 2605 2606/* 2607 * Reset the Gravis UltraSound card, completely 2608 */ 2609 2610STATIC void 2611gusreset(sc, voices) 2612 struct gus_softc *sc; 2613 int voices; 2614{ 2615 register int port = sc->sc_iobase; 2616 int i,s; 2617 2618 s = splgus(); 2619 2620 /* 2621 * Reset the GF1 chip 2622 */ 2623 2624 SELECT_GUS_REG(port, GUSREG_RESET); 2625 outb(port+GUS_DATA_HIGH, 0x00); 2626 2627 delay(500); 2628 2629 /* 2630 * Release reset 2631 */ 2632 2633 SELECT_GUS_REG(port, GUSREG_RESET); 2634 outb(port+GUS_DATA_HIGH, GUSMASK_MASTER_RESET); 2635 2636 delay(500); 2637 2638 /* 2639 * Reset MIDI port as well 2640 */ 2641 2642 outb(GUS_MIDI_CONTROL,MIDI_RESET); 2643 2644 delay(500); 2645 2646 outb(GUS_MIDI_CONTROL,0x00); 2647 2648 /* 2649 * Clear interrupts 2650 */ 2651 2652 SELECT_GUS_REG(port, GUSREG_DMA_CONTROL); 2653 outb(port+GUS_DATA_HIGH, 0x00); 2654 SELECT_GUS_REG(port, GUSREG_TIMER_CONTROL); 2655 outb(port+GUS_DATA_HIGH, 0x00); 2656 SELECT_GUS_REG(port, GUSREG_SAMPLE_CONTROL); 2657 outb(port+GUS_DATA_HIGH, 0x00); 2658 2659 gus_set_voices(sc, voices); 2660 2661 inb(port+GUS_IRQ_STATUS); 2662 SELECT_GUS_REG(port, GUSREG_DMA_CONTROL); 2663 inb(port+GUS_DATA_HIGH); 2664 SELECT_GUS_REG(port, GUSREG_SAMPLE_CONTROL); 2665 inb(port+GUS_DATA_HIGH); 2666 SELECT_GUS_REG(port, GUSREG_IRQ_STATUS); 2667 inb(port+GUS_DATA_HIGH); 2668 2669 /* 2670 * Reset voice specific information 2671 */ 2672 2673 for(i = 0; i < voices; i++) { 2674 outb(port+GUS_VOICE_SELECT, (unsigned char) i); 2675 2676 SELECT_GUS_REG(port, GUSREG_VOICE_CNTL); 2677 2678 sc->sc_voc[i].voccntl = GUSMASK_VOICE_STOPPED | 2679 GUSMASK_STOP_VOICE; 2680 2681 outb(port+GUS_DATA_HIGH, sc->sc_voc[i].voccntl); 2682 2683 sc->sc_voc[i].volcntl = GUSMASK_VOLUME_STOPPED | 2684 GUSMASK_STOP_VOLUME; 2685 2686 SELECT_GUS_REG(port, GUSREG_VOLUME_CONTROL); 2687 outb(port+GUS_DATA_HIGH, sc->sc_voc[i].volcntl); 2688 2689 delay(100); 2690 2691 gus_set_samprate(sc, i, 8000); 2692 SELECT_GUS_REG(port, GUSREG_START_ADDR_HIGH); 2693 outw(port+GUS_DATA_LOW, 0x0000); 2694 SELECT_GUS_REG(port, GUSREG_START_ADDR_LOW); 2695 outw(port+GUS_DATA_LOW, 0x0000); 2696 SELECT_GUS_REG(port, GUSREG_END_ADDR_HIGH); 2697 outw(port+GUS_DATA_LOW, 0x0000); 2698 SELECT_GUS_REG(port, GUSREG_END_ADDR_LOW); 2699 outw(port+GUS_DATA_LOW, 0x0000); 2700 SELECT_GUS_REG(port, GUSREG_VOLUME_RATE); 2701 outb(port+GUS_DATA_HIGH, 0x01); 2702 SELECT_GUS_REG(port, GUSREG_START_VOLUME); 2703 outb(port+GUS_DATA_HIGH, 0x10); 2704 SELECT_GUS_REG(port, GUSREG_END_VOLUME); 2705 outb(port+GUS_DATA_HIGH, 0xe0); 2706 SELECT_GUS_REG(port, GUSREG_CUR_VOLUME); 2707 outw(port+GUS_DATA_LOW, 0x0000); 2708 2709 SELECT_GUS_REG(port, GUSREG_CUR_ADDR_HIGH); 2710 outw(port+GUS_DATA_LOW, 0x0000); 2711 SELECT_GUS_REG(port, GUSREG_CUR_ADDR_LOW); 2712 outw(port+GUS_DATA_LOW, 0x0000); 2713 SELECT_GUS_REG(port, GUSREG_PAN_POS); 2714 outb(port+GUS_DATA_HIGH, 0x07); 2715 } 2716 2717 /* 2718 * Clear out any pending IRQs 2719 */ 2720 2721 inb(port+GUS_IRQ_STATUS); 2722 SELECT_GUS_REG(port, GUSREG_DMA_CONTROL); 2723 inb(port+GUS_DATA_HIGH); 2724 SELECT_GUS_REG(port, GUSREG_SAMPLE_CONTROL); 2725 inb(port+GUS_DATA_HIGH); 2726 SELECT_GUS_REG(port, GUSREG_IRQ_STATUS); 2727 inb(port+GUS_DATA_HIGH); 2728 2729 SELECT_GUS_REG(port, GUSREG_RESET); 2730 outb(port+GUS_DATA_HIGH, GUSMASK_MASTER_RESET | GUSMASK_DAC_ENABLE | 2731 GUSMASK_IRQ_ENABLE); 2732 2733 splx(s); 2734} 2735 2736 2737STATIC void 2738gus_init_cs4231(sc) 2739 struct gus_softc *sc; 2740{ 2741 register int port = sc->sc_iobase; 2742 u_char ctrl; 2743 2744 ctrl = (port & 0xf0) >> 4; /* set port address middle nibble */ 2745 /* 2746 * The codec is a bit weird--swapped dma channels. 2747 */ 2748 ctrl |= GUS_MAX_CODEC_ENABLE; 2749 if (sc->sc_drq >= 4) 2750 ctrl |= GUS_MAX_RECCHAN16; 2751 if (sc->sc_recdrq >= 4) 2752 ctrl |= GUS_MAX_PLAYCHAN16; 2753 2754 outb(port+GUS_MAX_CTRL, ctrl); 2755 2756 sc->sc_codec.sc_iot = sc->sc_iot; 2757 sc->sc_codec.sc_iobase = port+GUS_MAX_CODEC_BASE; 2758 2759 if (ad1848_probe(&sc->sc_codec) == 0) { 2760 sc->sc_flags &= ~GUS_CODEC_INSTALLED; 2761 } else { 2762 struct ad1848_volume vol = {AUDIO_MAX_GAIN, AUDIO_MAX_GAIN}; 2763 struct audio_hw_if gusmax_hw_if = { 2764 gusopen, 2765 gusmax_close, 2766 NULL, /* drain */ 2767 2768 gus_query_encoding, /* query encoding */ 2769 2770 gusmax_set_params, 2771 2772 gusmax_round_blocksize, 2773 2774 gusmax_set_out_port, 2775 gusmax_get_out_port, 2776 gusmax_set_in_port, 2777 gusmax_get_in_port, 2778 2779 gusmax_commit_settings, 2780 2781 NULL, 2782 NULL, 2783 2784 gusmax_dma_output, 2785 gusmax_dma_input, 2786 gusmax_halt_out_dma, 2787 gusmax_halt_in_dma, 2788 gusmax_cont_out_dma, 2789 gusmax_cont_in_dma, 2790 2791 gusmax_speaker_ctl, 2792 2793 gus_getdev, 2794 NULL, 2795 gusmax_mixer_set_port, 2796 gusmax_mixer_get_port, 2797 gusmax_mixer_query_devinfo, 2798 NULL, 2799 NULL, 2800 NULL, 2801 AUDIO_PROP_FULLDUPLEX, 2802 0, 2803 }; 2804 sc->sc_flags |= GUS_CODEC_INSTALLED; 2805 sc->sc_codec.parent = sc; 2806 sc->sc_codec.sc_drq = sc->sc_recdrq; 2807 sc->sc_codec.sc_recdrq = sc->sc_drq; 2808 gus_hw_if = gusmax_hw_if; 2809 /* enable line in and mic in the GUS mixer; the codec chip 2810 will do the real mixing for them. */ 2811 sc->sc_mixcontrol &= ~GUSMASK_LINE_IN; /* 0 enables. */ 2812 sc->sc_mixcontrol |= GUSMASK_MIC_IN; /* 1 enables. */ 2813 outb(sc->sc_iobase+GUS_MIX_CONTROL, sc->sc_mixcontrol); 2814 2815 ad1848_attach(&sc->sc_codec); 2816 /* turn on pre-MUX microphone gain. */ 2817 ad1848_set_mic_gain(&sc->sc_codec, &vol); 2818 } 2819} 2820 2821 2822/* 2823 * Return info about the audio device, for the AUDIO_GETINFO ioctl 2824 */ 2825 2826int 2827gus_getdev(addr, dev) 2828 void * addr; 2829 struct audio_device *dev; 2830{ 2831 *dev = gus_device; 2832 return 0; 2833} 2834 2835/* 2836 * stubs (XXX) 2837 */ 2838 2839int 2840gus_set_in_gain(addr, gain, balance) 2841 caddr_t addr; 2842 u_int gain; 2843 u_char balance; 2844{ 2845 DPRINTF(("gus_set_in_gain called\n")); 2846 return 0; 2847} 2848 2849int 2850gus_get_in_gain(addr) 2851 caddr_t addr; 2852{ 2853 DPRINTF(("gus_get_in_gain called\n")); 2854 return 0; 2855} 2856 2857int 2858gusmax_set_out_port(addr, port) 2859 void * addr; 2860 int port; 2861{ 2862 register struct ad1848_softc *sc = addr; 2863 return gus_set_out_port(sc->parent, port); 2864} 2865 2866int 2867gus_set_out_port(addr, port) 2868 void * addr; 2869 int port; 2870{ 2871 register struct gus_softc *sc = addr; 2872 DPRINTF(("gus_set_out_port called\n")); 2873 sc->sc_out_port = port; 2874 2875 return 0; 2876} 2877 2878int 2879gusmax_get_out_port(addr) 2880 void * addr; 2881{ 2882 register struct ad1848_softc *sc = addr; 2883 return gus_get_out_port(sc->parent); 2884} 2885 2886int 2887gus_get_out_port(addr) 2888 void * addr; 2889{ 2890 register struct gus_softc *sc = addr; 2891 DPRINTF(("gus_get_out_port() called\n")); 2892 return sc->sc_out_port; 2893} 2894 2895int 2896gusmax_set_in_port(addr, port) 2897 void * addr; 2898 int port; 2899{ 2900 register struct ad1848_softc *sc = addr; 2901 DPRINTF(("gusmax_set_in_port: %d\n", port)); 2902 2903 switch(port) { 2904 case MIC_IN_PORT: 2905 case LINE_IN_PORT: 2906 case AUX1_IN_PORT: 2907 case DAC_IN_PORT: 2908 break; 2909 default: 2910 return(EINVAL); 2911 /*NOTREACHED*/ 2912 } 2913 return(ad1848_set_rec_port(sc, port)); 2914} 2915 2916int 2917gusmax_get_in_port(addr) 2918 void * addr; 2919{ 2920 register struct ad1848_softc *sc = addr; 2921 int port; 2922 2923 port = ad1848_get_rec_port(sc); 2924 DPRINTF(("gusmax_get_in_port: %d\n", port)); 2925 2926 return(port); 2927} 2928 2929int 2930gus_set_in_port(addr, port) 2931 void * addr; 2932 int port; 2933{ 2934 register struct gus_softc *sc = addr; 2935 DPRINTF(("gus_set_in_port called\n")); 2936 /* 2937 * On the GUS with ICS mixer, the ADC input is after the mixer stage, 2938 * so we can't set the input port. 2939 * 2940 * On the GUS with CS4231 codec/mixer, see gusmax_set_in_port(). 2941 */ 2942 sc->sc_in_port = port; 2943 2944 return 0; 2945} 2946 2947 2948int 2949gus_get_in_port(addr) 2950 void * addr; 2951{ 2952 register struct gus_softc *sc = addr; 2953 DPRINTF(("gus_get_in_port called\n")); 2954 return sc->sc_in_port; 2955} 2956 2957 2958int 2959gusmax_dma_input(addr, buf, size, callback, arg) 2960 void * addr; 2961 void *buf; 2962 int size; 2963 void (*callback) __P((void *)); 2964 void *arg; 2965{ 2966 register struct ad1848_softc *sc = addr; 2967 return gus_dma_input(sc->parent, buf, size, callback, arg); 2968} 2969 2970/* 2971 * Start sampling the input source into the requested DMA buffer. 2972 * Called at splgus(), either from top-half or from interrupt handler. 2973 */ 2974int 2975gus_dma_input(addr, buf, size, callback, arg) 2976 void * addr; 2977 void *buf; 2978 int size; 2979 void (*callback) __P((void *)); 2980 void *arg; 2981{ 2982 register struct gus_softc *sc = addr; 2983 register int port = sc->sc_iobase; 2984 register u_char dmac; 2985 DMAPRINTF(("gus_dma_input called\n")); 2986 2987 /* 2988 * Sample SIZE bytes of data from the card, into buffer at BUF. 2989 */ 2990 2991 if (sc->sc_precision == 16) 2992 return EINVAL; /* XXX */ 2993 2994 /* set DMA modes */ 2995 dmac = GUSMASK_SAMPLE_IRQ|GUSMASK_SAMPLE_START; 2996 if (sc->sc_recdrq >= 4) 2997 dmac |= GUSMASK_SAMPLE_DATA16; 2998 if (sc->sc_encoding == AUDIO_ENCODING_ULAW || 2999 sc->sc_encoding == AUDIO_ENCODING_ULINEAR_LE || 3000 sc->sc_encoding == AUDIO_ENCODING_ULINEAR_BE) 3001 dmac |= GUSMASK_SAMPLE_INVBIT; 3002 if (sc->sc_channels == 2) 3003 dmac |= GUSMASK_SAMPLE_STEREO; 3004 isa_dmastart(sc->sc_dev.dv_parent, sc->sc_recdrq, buf, size, 3005 NULL, DMAMODE_READ, BUS_DMA_NOWAIT); 3006 3007 DMAPRINTF(("gus_dma_input isa_dmastarted\n")); 3008 sc->sc_flags |= GUS_DMAIN_ACTIVE; 3009 sc->sc_dmainintr = callback; 3010 sc->sc_inarg = arg; 3011 sc->sc_dmaincnt = size; 3012 sc->sc_dmainaddr = buf; 3013 3014 SELECT_GUS_REG(port, GUSREG_SAMPLE_CONTROL); 3015 outb(port+GUS_DATA_HIGH, dmac); /* Go! */ 3016 3017 3018 DMAPRINTF(("gus_dma_input returning\n")); 3019 3020 return 0; 3021} 3022 3023STATIC int 3024gus_dmain_intr(sc) 3025 struct gus_softc *sc; 3026{ 3027 void (*callback) __P((void *)); 3028 void *arg; 3029 3030 DMAPRINTF(("gus_dmain_intr called\n")); 3031 if (sc->sc_dmainintr) { 3032 isa_dmadone(sc->sc_dev.dv_parent, sc->sc_recdrq); 3033 callback = sc->sc_dmainintr; 3034 arg = sc->sc_inarg; 3035 3036 sc->sc_dmainaddr = 0; 3037 sc->sc_dmaincnt = 0; 3038 sc->sc_dmainintr = 0; 3039 sc->sc_inarg = 0; 3040 3041 sc->sc_flags &= ~GUS_DMAIN_ACTIVE; 3042 DMAPRINTF(("calling dmain_intr callback %p(%p)\n", callback, arg)); 3043 (*callback)(arg); 3044 return 1; 3045 } else { 3046 DMAPRINTF(("gus_dmain_intr false?\n")); 3047 return 0; /* XXX ??? */ 3048 } 3049} 3050 3051int 3052gusmax_halt_out_dma(addr) 3053 void * addr; 3054{ 3055 register struct ad1848_softc *sc = addr; 3056 return gus_halt_out_dma(sc->parent); 3057} 3058 3059 3060int 3061gusmax_halt_in_dma(addr) 3062 void * addr; 3063{ 3064 register struct ad1848_softc *sc = addr; 3065 return gus_halt_in_dma(sc->parent); 3066} 3067 3068int 3069gusmax_cont_out_dma(addr) 3070 void * addr; 3071{ 3072 register struct ad1848_softc *sc = addr; 3073 return gus_cont_out_dma(sc->parent); 3074} 3075 3076int 3077gusmax_cont_in_dma(addr) 3078 void * addr; 3079{ 3080 register struct ad1848_softc *sc = addr; 3081 return gus_cont_in_dma(sc->parent); 3082} 3083 3084/* 3085 * Stop any DMA output. Called at splgus(). 3086 */ 3087int 3088gus_halt_out_dma(addr) 3089 void * addr; 3090{ 3091 register struct gus_softc *sc = addr; 3092 register int port = sc->sc_iobase; 3093 3094 DMAPRINTF(("gus_halt_out_dma called\n")); 3095 /* 3096 * Make sure the GUS _isn't_ setup for DMA 3097 */ 3098 3099 SELECT_GUS_REG(port, GUSREG_DMA_CONTROL); 3100 outb(sc->sc_iobase+GUS_DATA_HIGH, 0); 3101 3102 untimeout(gus_dmaout_timeout, sc); 3103 isa_dmaabort(sc->sc_dev.dv_parent, sc->sc_drq); 3104 sc->sc_flags &= ~(GUS_DMAOUT_ACTIVE|GUS_LOCKED); 3105 sc->sc_dmaoutintr = 0; 3106 sc->sc_outarg = 0; 3107 sc->sc_dmaoutaddr = 0; 3108 sc->sc_dmaoutcnt = 0; 3109 sc->sc_dmabuf = 0; 3110 sc->sc_bufcnt = 0; 3111 sc->sc_playbuf = -1; 3112 /* also stop playing */ 3113 gus_stop_voice(sc, GUS_VOICE_LEFT, 1); 3114 gus_stop_voice(sc, GUS_VOICE_RIGHT, 0); 3115 3116 return 0; 3117} 3118 3119/* 3120 * Stop any DMA output. Called at splgus(). 3121 */ 3122int 3123gus_halt_in_dma(addr) 3124 void * addr; 3125{ 3126 register struct gus_softc *sc = addr; 3127 register int port = sc->sc_iobase; 3128 DMAPRINTF(("gus_halt_in_dma called\n")); 3129 3130 /* 3131 * Make sure the GUS _isn't_ setup for DMA 3132 */ 3133 3134 SELECT_GUS_REG(port, GUSREG_SAMPLE_CONTROL); 3135 outb(port+GUS_DATA_HIGH, 3136 inb(port+GUS_DATA_HIGH) & ~(GUSMASK_SAMPLE_START|GUSMASK_SAMPLE_IRQ)); 3137 3138 isa_dmaabort(sc->sc_dev.dv_parent, sc->sc_recdrq); 3139 sc->sc_flags &= ~GUS_DMAIN_ACTIVE; 3140 sc->sc_dmainintr = 0; 3141 sc->sc_inarg = 0; 3142 sc->sc_dmainaddr = 0; 3143 sc->sc_dmaincnt = 0; 3144 3145 return 0; 3146} 3147 3148int 3149gus_cont_out_dma(addr) 3150 void * addr; 3151{ 3152 DPRINTF(("gus_cont_out_dma called\n")); 3153 return EOPNOTSUPP; 3154} 3155 3156int 3157gus_cont_in_dma(addr) 3158 void * addr; 3159{ 3160 DPRINTF(("gus_cont_in_dma called\n")); 3161 return EOPNOTSUPP; 3162} 3163 3164 3165STATIC __inline int 3166gus_to_vol(cp, vol) 3167 mixer_ctrl_t *cp; 3168 struct ad1848_volume *vol; 3169{ 3170 if (cp->un.value.num_channels == 1) { 3171 vol->left = vol->right = cp->un.value.level[AUDIO_MIXER_LEVEL_MONO]; 3172 return(1); 3173 } 3174 else if (cp->un.value.num_channels == 2) { 3175 vol->left = cp->un.value.level[AUDIO_MIXER_LEVEL_LEFT]; 3176 vol->right = cp->un.value.level[AUDIO_MIXER_LEVEL_RIGHT]; 3177 return(1); 3178 } 3179 return(0); 3180} 3181 3182STATIC __inline int 3183gus_from_vol(cp, vol) 3184 mixer_ctrl_t *cp; 3185 struct ad1848_volume *vol; 3186{ 3187 if (cp->un.value.num_channels == 1) { 3188 cp->un.value.level[AUDIO_MIXER_LEVEL_MONO] = vol->left; 3189 return(1); 3190 } 3191 else if (cp->un.value.num_channels == 2) { 3192 cp->un.value.level[AUDIO_MIXER_LEVEL_LEFT] = vol->left; 3193 cp->un.value.level[AUDIO_MIXER_LEVEL_RIGHT] = vol->right; 3194 return(1); 3195 } 3196 return(0); 3197} 3198 3199STATIC int 3200gusmax_mixer_get_port(addr, cp) 3201 void *addr; 3202 mixer_ctrl_t *cp; 3203{ 3204 register struct ad1848_softc *ac = addr; 3205 register struct gus_softc *sc = ac->parent; 3206 struct ad1848_volume vol; 3207 int error = EINVAL; 3208 3209 DPRINTF(("gusmax_mixer_get_port: port=%d\n", cp->dev)); 3210 3211 switch (cp->dev) { 3212#if 0 /* use mono level instead */ 3213 case GUSMAX_MIC_IN_LVL: /* Microphone */ 3214 if (cp->type == AUDIO_MIXER_VALUE) { 3215 error = ad1848_get_mic_gain(ac, &vol); 3216 if (!error) 3217 gus_from_vol(cp, &vol); 3218 } 3219 break; 3220#endif 3221 3222 case GUSMAX_DAC_LVL: /* dac out */ 3223 if (cp->type == AUDIO_MIXER_VALUE) { 3224 error = ad1848_get_aux1_gain(ac, &vol); 3225 if (!error) 3226 gus_from_vol(cp, &vol); 3227 } 3228 break; 3229 3230 case GUSMAX_LINE_IN_LVL: /* line in */ 3231 if (cp->type == AUDIO_MIXER_VALUE) { 3232 error = cs4231_get_linein_gain(ac, &vol); 3233 if (!error) 3234 gus_from_vol(cp, &vol); 3235 } 3236 break; 3237 3238 case GUSMAX_MONO_LVL: /* mono */ 3239 if (cp->type == AUDIO_MIXER_VALUE && 3240 cp->un.value.num_channels == 1) { 3241 error = cs4231_get_mono_gain(ac, &vol); 3242 if (!error) 3243 gus_from_vol(cp, &vol); 3244 } 3245 break; 3246 3247 case GUSMAX_CD_LVL: /* CD */ 3248 if (cp->type == AUDIO_MIXER_VALUE) { 3249 error = ad1848_get_aux2_gain(ac, &vol); 3250 if (!error) 3251 gus_from_vol(cp, &vol); 3252 } 3253 break; 3254 3255 case GUSMAX_MONITOR_LVL: /* monitor level */ 3256 if (cp->type == AUDIO_MIXER_VALUE && 3257 cp->un.value.num_channels == 1) { 3258 error = ad1848_get_mon_gain(ac, &vol); 3259 if (!error) 3260 cp->un.value.level[AUDIO_MIXER_LEVEL_MONO] = 3261 vol.left; 3262 } 3263 break; 3264 3265 case GUSMAX_OUT_LVL: /* output level */ 3266 if (cp->type == AUDIO_MIXER_VALUE) { 3267 error = ad1848_get_out_gain(ac, &vol); 3268 if (!error) 3269 gus_from_vol(cp, &vol); 3270 } 3271 break; 3272 3273 case GUSMAX_SPEAKER_LVL: /* fake speaker for mute naming */ 3274 if (cp->type == AUDIO_MIXER_VALUE) { 3275 if (sc->sc_mixcontrol & GUSMASK_LINE_OUT) 3276 vol.left = vol.right = AUDIO_MAX_GAIN; 3277 else 3278 vol.left = vol.right = AUDIO_MIN_GAIN; 3279 error = 0; 3280 gus_from_vol(cp, &vol); 3281 } 3282 break; 3283 3284 case GUSMAX_LINE_IN_MUTE: 3285 if (cp->type == AUDIO_MIXER_ENUM) { 3286 cp->un.ord = ac->line_mute; 3287 error = 0; 3288 } 3289 break; 3290 3291 3292 case GUSMAX_DAC_MUTE: 3293 if (cp->type == AUDIO_MIXER_ENUM) { 3294 cp->un.ord = ac->aux1_mute; 3295 error = 0; 3296 } 3297 break; 3298 3299 case GUSMAX_CD_MUTE: 3300 if (cp->type == AUDIO_MIXER_ENUM) { 3301 cp->un.ord = ac->aux2_mute; 3302 error = 0; 3303 } 3304 break; 3305 3306 case GUSMAX_MONO_MUTE: 3307 if (cp->type == AUDIO_MIXER_ENUM) { 3308 cp->un.ord = ac->mono_mute; 3309 error = 0; 3310 } 3311 break; 3312 3313 case GUSMAX_MONITOR_MUTE: 3314 if (cp->type == AUDIO_MIXER_ENUM) { 3315 cp->un.ord = ac->mon_mute; 3316 error = 0; 3317 } 3318 break; 3319 3320 case GUSMAX_SPEAKER_MUTE: 3321 if (cp->type == AUDIO_MIXER_ENUM) { 3322 cp->un.ord = sc->sc_mixcontrol & GUSMASK_LINE_OUT ? 1 : 0; 3323 error = 0; 3324 } 3325 break; 3326 3327 case GUSMAX_REC_LVL: /* record level */ 3328 if (cp->type == AUDIO_MIXER_VALUE) { 3329 error = ad1848_get_rec_gain(ac, &vol); 3330 if (!error) 3331 gus_from_vol(cp, &vol); 3332 } 3333 break; 3334 3335 case GUSMAX_RECORD_SOURCE: 3336 if (cp->type == AUDIO_MIXER_ENUM) { 3337 cp->un.ord = ad1848_get_rec_port(ac); 3338 error = 0; 3339 } 3340 break; 3341 3342 default: 3343 error = ENXIO; 3344 break; 3345 } 3346 3347 return(error); 3348} 3349 3350STATIC int 3351gus_mixer_get_port(addr, cp) 3352 void *addr; 3353 mixer_ctrl_t *cp; 3354{ 3355 register struct gus_softc *sc = addr; 3356 register struct ics2101_softc *ic = &sc->sc_mixer; 3357 struct ad1848_volume vol; 3358 int error = EINVAL; 3359 3360 DPRINTF(("gus_mixer_get_port: dev=%d type=%d\n", cp->dev, cp->type)); 3361 3362 if (!HAS_MIXER(sc) && cp->dev > GUSICS_MASTER_MUTE) 3363 return ENXIO; 3364 3365 switch (cp->dev) { 3366 3367 case GUSICS_MIC_IN_MUTE: /* Microphone */ 3368 if (cp->type == AUDIO_MIXER_ENUM) { 3369 if (HAS_MIXER(sc)) 3370 cp->un.ord = ic->sc_mute[GUSMIX_CHAN_MIC][ICSMIX_LEFT]; 3371 else 3372 cp->un.ord = 3373 sc->sc_mixcontrol & GUSMASK_MIC_IN ? 0 : 1; 3374 error = 0; 3375 } 3376 break; 3377 3378 case GUSICS_LINE_IN_MUTE: 3379 if (cp->type == AUDIO_MIXER_ENUM) { 3380 if (HAS_MIXER(sc)) 3381 cp->un.ord = ic->sc_mute[GUSMIX_CHAN_LINE][ICSMIX_LEFT]; 3382 else 3383 cp->un.ord = 3384 sc->sc_mixcontrol & GUSMASK_LINE_IN ? 1 : 0; 3385 error = 0; 3386 } 3387 break; 3388 3389 case GUSICS_MASTER_MUTE: 3390 if (cp->type == AUDIO_MIXER_ENUM) { 3391 if (HAS_MIXER(sc)) 3392 cp->un.ord = ic->sc_mute[GUSMIX_CHAN_MASTER][ICSMIX_LEFT]; 3393 else 3394 cp->un.ord = 3395 sc->sc_mixcontrol & GUSMASK_LINE_OUT ? 1 : 0; 3396 error = 0; 3397 } 3398 break; 3399 3400 case GUSICS_DAC_MUTE: 3401 if (cp->type == AUDIO_MIXER_ENUM) { 3402 cp->un.ord = ic->sc_mute[GUSMIX_CHAN_DAC][ICSMIX_LEFT]; 3403 error = 0; 3404 } 3405 break; 3406 3407 case GUSICS_CD_MUTE: 3408 if (cp->type == AUDIO_MIXER_ENUM) { 3409 cp->un.ord = ic->sc_mute[GUSMIX_CHAN_CD][ICSMIX_LEFT]; 3410 error = 0; 3411 } 3412 break; 3413 3414 case GUSICS_MASTER_LVL: 3415 if (cp->type == AUDIO_MIXER_VALUE) { 3416 vol.left = ic->sc_setting[GUSMIX_CHAN_MASTER][ICSMIX_LEFT]; 3417 vol.right = ic->sc_setting[GUSMIX_CHAN_MASTER][ICSMIX_RIGHT]; 3418 if (gus_from_vol(cp, &vol)) 3419 error = 0; 3420 } 3421 break; 3422 3423 case GUSICS_MIC_IN_LVL: /* Microphone */ 3424 if (cp->type == AUDIO_MIXER_VALUE) { 3425 vol.left = ic->sc_setting[GUSMIX_CHAN_MIC][ICSMIX_LEFT]; 3426 vol.right = ic->sc_setting[GUSMIX_CHAN_MIC][ICSMIX_RIGHT]; 3427 if (gus_from_vol(cp, &vol)) 3428 error = 0; 3429 } 3430 break; 3431 3432 case GUSICS_LINE_IN_LVL: /* line in */ 3433 if (cp->type == AUDIO_MIXER_VALUE) { 3434 vol.left = ic->sc_setting[GUSMIX_CHAN_LINE][ICSMIX_LEFT]; 3435 vol.right = ic->sc_setting[GUSMIX_CHAN_LINE][ICSMIX_RIGHT]; 3436 if (gus_from_vol(cp, &vol)) 3437 error = 0; 3438 } 3439 break; 3440 3441 3442 case GUSICS_CD_LVL: 3443 if (cp->type == AUDIO_MIXER_VALUE) { 3444 vol.left = ic->sc_setting[GUSMIX_CHAN_CD][ICSMIX_LEFT]; 3445 vol.right = ic->sc_setting[GUSMIX_CHAN_CD][ICSMIX_RIGHT]; 3446 if (gus_from_vol(cp, &vol)) 3447 error = 0; 3448 } 3449 break; 3450 3451 case GUSICS_DAC_LVL: /* dac out */ 3452 if (cp->type == AUDIO_MIXER_VALUE) { 3453 vol.left = ic->sc_setting[GUSMIX_CHAN_DAC][ICSMIX_LEFT]; 3454 vol.right = ic->sc_setting[GUSMIX_CHAN_DAC][ICSMIX_RIGHT]; 3455 if (gus_from_vol(cp, &vol)) 3456 error = 0; 3457 } 3458 break; 3459 3460 3461 case GUSICS_RECORD_SOURCE: 3462 if (cp->type == AUDIO_MIXER_ENUM) { 3463 /* Can't set anything else useful, sigh. */ 3464 cp->un.ord = 0; 3465 } 3466 break; 3467 3468 default: 3469 return ENXIO; 3470 /*NOTREACHED*/ 3471 } 3472 return error; 3473} 3474 3475STATIC void 3476gusics_master_mute(ic, mute) 3477 struct ics2101_softc *ic; 3478 int mute; 3479{ 3480 ics2101_mix_mute(ic, GUSMIX_CHAN_MASTER, ICSMIX_LEFT, mute); 3481 ics2101_mix_mute(ic, GUSMIX_CHAN_MASTER, ICSMIX_RIGHT, mute); 3482} 3483 3484STATIC void 3485gusics_mic_mute(ic, mute) 3486 struct ics2101_softc *ic; 3487 int mute; 3488{ 3489 ics2101_mix_mute(ic, GUSMIX_CHAN_MIC, ICSMIX_LEFT, mute); 3490 ics2101_mix_mute(ic, GUSMIX_CHAN_MIC, ICSMIX_RIGHT, mute); 3491} 3492 3493STATIC void 3494gusics_linein_mute(ic, mute) 3495 struct ics2101_softc *ic; 3496 int mute; 3497{ 3498 ics2101_mix_mute(ic, GUSMIX_CHAN_LINE, ICSMIX_LEFT, mute); 3499 ics2101_mix_mute(ic, GUSMIX_CHAN_LINE, ICSMIX_RIGHT, mute); 3500} 3501 3502STATIC void 3503gusics_cd_mute(ic, mute) 3504 struct ics2101_softc *ic; 3505 int mute; 3506{ 3507 ics2101_mix_mute(ic, GUSMIX_CHAN_CD, ICSMIX_LEFT, mute); 3508 ics2101_mix_mute(ic, GUSMIX_CHAN_CD, ICSMIX_RIGHT, mute); 3509} 3510 3511STATIC void 3512gusics_dac_mute(ic, mute) 3513 struct ics2101_softc *ic; 3514 int mute; 3515{ 3516 ics2101_mix_mute(ic, GUSMIX_CHAN_DAC, ICSMIX_LEFT, mute); 3517 ics2101_mix_mute(ic, GUSMIX_CHAN_DAC, ICSMIX_RIGHT, mute); 3518} 3519 3520STATIC int 3521gusmax_mixer_set_port(addr, cp) 3522 void *addr; 3523 mixer_ctrl_t *cp; 3524{ 3525 register struct ad1848_softc *ac = addr; 3526 register struct gus_softc *sc = ac->parent; 3527 struct ad1848_volume vol; 3528 int error = EINVAL; 3529 3530 DPRINTF(("gusmax_mixer_set_port: dev=%d type=%d\n", cp->dev, cp->type)); 3531 3532 switch (cp->dev) { 3533#if 0 3534 case GUSMAX_MIC_IN_LVL: /* Microphone */ 3535 if (cp->type == AUDIO_MIXER_VALUE && 3536 cp->un.value.num_channels == 1) { 3537 /* XXX enable/disable pre-MUX fixed gain */ 3538 if (gus_to_vol(cp, &vol)) 3539 error = ad1848_set_mic_gain(ac, &vol); 3540 } 3541 break; 3542#endif 3543 3544 case GUSMAX_DAC_LVL: /* dac out */ 3545 if (cp->type == AUDIO_MIXER_VALUE) { 3546 if (gus_to_vol(cp, &vol)) 3547 error = ad1848_set_aux1_gain(ac, &vol); 3548 } 3549 break; 3550 3551 case GUSMAX_LINE_IN_LVL: /* line in */ 3552 if (cp->type == AUDIO_MIXER_VALUE) { 3553 if (gus_to_vol(cp, &vol)) 3554 error = cs4231_set_linein_gain(ac, &vol); 3555 } 3556 break; 3557 3558 case GUSMAX_MONO_LVL: /* mic/mono in */ 3559 if (cp->type == AUDIO_MIXER_VALUE && 3560 cp->un.value.num_channels == 1) { 3561 if (gus_to_vol(cp, &vol)) 3562 error = cs4231_set_mono_gain(ac, &vol); 3563 } 3564 break; 3565 3566 case GUSMAX_CD_LVL: /* CD: AUX2 */ 3567 if (cp->type == AUDIO_MIXER_VALUE) { 3568 if (gus_to_vol(cp, &vol)) 3569 error = ad1848_set_aux2_gain(ac, &vol); 3570 } 3571 break; 3572 3573 case GUSMAX_MONITOR_LVL: 3574 if (cp->type == AUDIO_MIXER_VALUE && 3575 cp->un.value.num_channels == 1) { 3576 vol.left = cp->un.value.level[AUDIO_MIXER_LEVEL_MONO]; 3577 error = ad1848_set_mon_gain(ac, &vol); 3578 } 3579 break; 3580 3581 case GUSMAX_OUT_LVL: /* output volume */ 3582 if (cp->type == AUDIO_MIXER_VALUE) { 3583 if (gus_to_vol(cp, &vol)) 3584 error = ad1848_set_out_gain(ac, &vol); 3585 } 3586 break; 3587 3588 case GUSMAX_SPEAKER_LVL: 3589 if (cp->type == AUDIO_MIXER_VALUE && 3590 cp->un.value.num_channels == 1) { 3591 if (gus_to_vol(cp, &vol)) { 3592 gus_speaker_ctl(sc, vol.left > AUDIO_MIN_GAIN ? 3593 SPKR_ON : SPKR_OFF); 3594 error = 0; 3595 } 3596 } 3597 break; 3598 3599 case GUSMAX_LINE_IN_MUTE: 3600 if (cp->type == AUDIO_MIXER_ENUM) { 3601 ac->line_mute = cp->un.ord ? 1 : 0; 3602 DPRINTF(("line mute %d\n", cp->un.ord)); 3603 cs4231_mute_line(ac, ac->line_mute); 3604 gus_linein_ctl(sc, ac->line_mute ? SPKR_OFF : SPKR_ON); 3605 error = 0; 3606 } 3607 break; 3608 3609 case GUSMAX_DAC_MUTE: 3610 if (cp->type == AUDIO_MIXER_ENUM) { 3611 ac->aux1_mute = cp->un.ord ? 1 : 0; 3612 DPRINTF(("dac mute %d\n", cp->un.ord)); 3613 ad1848_mute_aux1(ac, ac->aux1_mute); 3614 error = 0; 3615 } 3616 break; 3617 3618 case GUSMAX_CD_MUTE: 3619 if (cp->type == AUDIO_MIXER_ENUM) { 3620 ac->aux2_mute = cp->un.ord ? 1 : 0; 3621 DPRINTF(("cd mute %d\n", cp->un.ord)); 3622 ad1848_mute_aux2(ac, ac->aux2_mute); 3623 error = 0; 3624 } 3625 break; 3626 3627 case GUSMAX_MONO_MUTE: /* Microphone */ 3628 if (cp->type == AUDIO_MIXER_ENUM) { 3629 ac->mono_mute = cp->un.ord ? 1 : 0; 3630 DPRINTF(("mono mute %d\n", cp->un.ord)); 3631 cs4231_mute_mono(ac, ac->mono_mute); 3632 gus_mic_ctl(sc, ac->mono_mute ? SPKR_OFF : SPKR_ON); 3633 error = 0; 3634 } 3635 break; 3636 3637 case GUSMAX_MONITOR_MUTE: 3638 if (cp->type == AUDIO_MIXER_ENUM) { 3639 ac->mon_mute = cp->un.ord ? 1 : 0; 3640 DPRINTF(("mono mute %d\n", cp->un.ord)); 3641 cs4231_mute_monitor(ac, ac->mon_mute); 3642 error = 0; 3643 } 3644 break; 3645 3646 case GUSMAX_SPEAKER_MUTE: 3647 if (cp->type == AUDIO_MIXER_ENUM) { 3648 gus_speaker_ctl(sc, cp->un.ord ? SPKR_OFF : SPKR_ON); 3649 error = 0; 3650 } 3651 break; 3652 3653 case GUSMAX_REC_LVL: /* record level */ 3654 if (cp->type == AUDIO_MIXER_VALUE) { 3655 if (gus_to_vol(cp, &vol)) 3656 error = ad1848_set_rec_gain(ac, &vol); 3657 } 3658 break; 3659 3660 case GUSMAX_RECORD_SOURCE: 3661 if (cp->type == AUDIO_MIXER_ENUM) { 3662 error = ad1848_set_rec_port(ac, cp->un.ord); 3663 } 3664 break; 3665 3666 default: 3667 return ENXIO; 3668 /*NOTREACHED*/ 3669 } 3670 return error; 3671} 3672 3673STATIC int 3674gus_mixer_set_port(addr, cp) 3675 void *addr; 3676 mixer_ctrl_t *cp; 3677{ 3678 register struct gus_softc *sc = addr; 3679 register struct ics2101_softc *ic = &sc->sc_mixer; 3680 struct ad1848_volume vol; 3681 int error = EINVAL; 3682 3683 DPRINTF(("gus_mixer_set_port: dev=%d type=%d\n", cp->dev, cp->type)); 3684 3685 if (!HAS_MIXER(sc) && cp->dev > GUSICS_MASTER_MUTE) 3686 return ENXIO; 3687 3688 switch (cp->dev) { 3689 3690 case GUSICS_MIC_IN_MUTE: /* Microphone */ 3691 if (cp->type == AUDIO_MIXER_ENUM) { 3692 DPRINTF(("mic mute %d\n", cp->un.ord)); 3693 if (HAS_MIXER(sc)) { 3694 gusics_mic_mute(ic, cp->un.ord); 3695 } 3696 gus_mic_ctl(sc, cp->un.ord ? SPKR_OFF : SPKR_ON); 3697 error = 0; 3698 } 3699 break; 3700 3701 case GUSICS_LINE_IN_MUTE: 3702 if (cp->type == AUDIO_MIXER_ENUM) { 3703 DPRINTF(("linein mute %d\n", cp->un.ord)); 3704 if (HAS_MIXER(sc)) { 3705 gusics_linein_mute(ic, cp->un.ord); 3706 } 3707 gus_linein_ctl(sc, cp->un.ord ? SPKR_OFF : SPKR_ON); 3708 error = 0; 3709 } 3710 break; 3711 3712 case GUSICS_MASTER_MUTE: 3713 if (cp->type == AUDIO_MIXER_ENUM) { 3714 DPRINTF(("master mute %d\n", cp->un.ord)); 3715 if (HAS_MIXER(sc)) { 3716 gusics_master_mute(ic, cp->un.ord); 3717 } 3718 gus_speaker_ctl(sc, cp->un.ord ? SPKR_OFF : SPKR_ON); 3719 error = 0; 3720 } 3721 break; 3722 3723 case GUSICS_DAC_MUTE: 3724 if (cp->type == AUDIO_MIXER_ENUM) { 3725 gusics_dac_mute(ic, cp->un.ord); 3726 error = 0; 3727 } 3728 break; 3729 3730 case GUSICS_CD_MUTE: 3731 if (cp->type == AUDIO_MIXER_ENUM) { 3732 gusics_cd_mute(ic, cp->un.ord); 3733 error = 0; 3734 } 3735 break; 3736 3737 case GUSICS_MASTER_LVL: 3738 if (cp->type == AUDIO_MIXER_VALUE) { 3739 if (gus_to_vol(cp, &vol)) { 3740 ics2101_mix_attenuate(ic, 3741 GUSMIX_CHAN_MASTER, 3742 ICSMIX_LEFT, 3743 vol.left); 3744 ics2101_mix_attenuate(ic, 3745 GUSMIX_CHAN_MASTER, 3746 ICSMIX_RIGHT, 3747 vol.right); 3748 error = 0; 3749 } 3750 } 3751 break; 3752 3753 case GUSICS_MIC_IN_LVL: /* Microphone */ 3754 if (cp->type == AUDIO_MIXER_VALUE) { 3755 if (gus_to_vol(cp, &vol)) { 3756 ics2101_mix_attenuate(ic, 3757 GUSMIX_CHAN_MIC, 3758 ICSMIX_LEFT, 3759 vol.left); 3760 ics2101_mix_attenuate(ic, 3761 GUSMIX_CHAN_MIC, 3762 ICSMIX_RIGHT, 3763 vol.right); 3764 error = 0; 3765 } 3766 } 3767 break; 3768 3769 case GUSICS_LINE_IN_LVL: /* line in */ 3770 if (cp->type == AUDIO_MIXER_VALUE) { 3771 if (gus_to_vol(cp, &vol)) { 3772 ics2101_mix_attenuate(ic, 3773 GUSMIX_CHAN_LINE, 3774 ICSMIX_LEFT, 3775 vol.left); 3776 ics2101_mix_attenuate(ic, 3777 GUSMIX_CHAN_LINE, 3778 ICSMIX_RIGHT, 3779 vol.right); 3780 error = 0; 3781 } 3782 } 3783 break; 3784 3785 3786 case GUSICS_CD_LVL: 3787 if (cp->type == AUDIO_MIXER_VALUE) { 3788 if (gus_to_vol(cp, &vol)) { 3789 ics2101_mix_attenuate(ic, 3790 GUSMIX_CHAN_CD, 3791 ICSMIX_LEFT, 3792 vol.left); 3793 ics2101_mix_attenuate(ic, 3794 GUSMIX_CHAN_CD, 3795 ICSMIX_RIGHT, 3796 vol.right); 3797 error = 0; 3798 } 3799 } 3800 break; 3801 3802 case GUSICS_DAC_LVL: /* dac out */ 3803 if (cp->type == AUDIO_MIXER_VALUE) { 3804 if (gus_to_vol(cp, &vol)) { 3805 ics2101_mix_attenuate(ic, 3806 GUSMIX_CHAN_DAC, 3807 ICSMIX_LEFT, 3808 vol.left); 3809 ics2101_mix_attenuate(ic, 3810 GUSMIX_CHAN_DAC, 3811 ICSMIX_RIGHT, 3812 vol.right); 3813 error = 0; 3814 } 3815 } 3816 break; 3817 3818 3819 case GUSICS_RECORD_SOURCE: 3820 if (cp->type == AUDIO_MIXER_ENUM && cp->un.ord == 0) { 3821 /* Can't set anything else useful, sigh. */ 3822 error = 0; 3823 } 3824 break; 3825 3826 default: 3827 return ENXIO; 3828 /*NOTREACHED*/ 3829 } 3830 return error; 3831} 3832 3833STATIC int 3834gusmax_mixer_query_devinfo(addr, dip) 3835 void *addr; 3836 register mixer_devinfo_t *dip; 3837{ 3838 DPRINTF(("gusmax_query_devinfo: index=%d\n", dip->index)); 3839 3840 switch(dip->index) { 3841#if 0 3842 case GUSMAX_MIC_IN_LVL: /* Microphone */ 3843 dip->type = AUDIO_MIXER_VALUE; 3844 dip->mixer_class = GUSMAX_INPUT_CLASS; 3845 dip->prev = AUDIO_MIXER_LAST; 3846 dip->next = GUSMAX_MIC_IN_MUTE; 3847 strcpy(dip->label.name, AudioNmicrophone); 3848 dip->un.v.num_channels = 2; 3849 strcpy(dip->un.v.units.name, AudioNvolume); 3850 break; 3851#endif 3852 3853 case GUSMAX_MONO_LVL: /* mono/microphone mixer */ 3854 dip->type = AUDIO_MIXER_VALUE; 3855 dip->mixer_class = GUSMAX_INPUT_CLASS; 3856 dip->prev = AUDIO_MIXER_LAST; 3857 dip->next = GUSMAX_MONO_MUTE; 3858 strcpy(dip->label.name, AudioNmicrophone); 3859 dip->un.v.num_channels = 1; 3860 strcpy(dip->un.v.units.name, AudioNvolume); 3861 break; 3862 3863 case GUSMAX_DAC_LVL: /* dacout */ 3864 dip->type = AUDIO_MIXER_VALUE; 3865 dip->mixer_class = GUSMAX_INPUT_CLASS; 3866 dip->prev = AUDIO_MIXER_LAST; 3867 dip->next = GUSMAX_DAC_MUTE; 3868 strcpy(dip->label.name, AudioNdac); 3869 dip->un.v.num_channels = 2; 3870 strcpy(dip->un.v.units.name, AudioNvolume); 3871 break; 3872 3873 case GUSMAX_LINE_IN_LVL: /* line */ 3874 dip->type = AUDIO_MIXER_VALUE; 3875 dip->mixer_class = GUSMAX_INPUT_CLASS; 3876 dip->prev = AUDIO_MIXER_LAST; 3877 dip->next = GUSMAX_LINE_IN_MUTE; 3878 strcpy(dip->label.name, AudioNline); 3879 dip->un.v.num_channels = 2; 3880 strcpy(dip->un.v.units.name, AudioNvolume); 3881 break; 3882 3883 case GUSMAX_CD_LVL: /* cd */ 3884 dip->type = AUDIO_MIXER_VALUE; 3885 dip->mixer_class = GUSMAX_INPUT_CLASS; 3886 dip->prev = AUDIO_MIXER_LAST; 3887 dip->next = GUSMAX_CD_MUTE; 3888 strcpy(dip->label.name, AudioNcd); 3889 dip->un.v.num_channels = 2; 3890 strcpy(dip->un.v.units.name, AudioNvolume); 3891 break; 3892 3893 3894 case GUSMAX_MONITOR_LVL: /* monitor level */ 3895 dip->type = AUDIO_MIXER_VALUE; 3896 dip->mixer_class = GUSMAX_MONITOR_CLASS; 3897 dip->next = GUSMAX_MONITOR_MUTE; 3898 dip->prev = AUDIO_MIXER_LAST; 3899 strcpy(dip->label.name, AudioNmonitor); 3900 dip->un.v.num_channels = 1; 3901 strcpy(dip->un.v.units.name, AudioNvolume); 3902 break; 3903 3904 case GUSMAX_OUT_LVL: /* cs4231 output volume: not useful? */ 3905 dip->type = AUDIO_MIXER_VALUE; 3906 dip->mixer_class = GUSMAX_MONITOR_CLASS; 3907 dip->prev = dip->next = AUDIO_MIXER_LAST; 3908 strcpy(dip->label.name, AudioNoutput); 3909 dip->un.v.num_channels = 2; 3910 strcpy(dip->un.v.units.name, AudioNvolume); 3911 break; 3912 3913 case GUSMAX_SPEAKER_LVL: /* fake speaker volume */ 3914 dip->type = AUDIO_MIXER_VALUE; 3915 dip->mixer_class = GUSMAX_MONITOR_CLASS; 3916 dip->prev = AUDIO_MIXER_LAST; 3917 dip->next = GUSMAX_SPEAKER_MUTE; 3918 strcpy(dip->label.name, AudioNspeaker); 3919 dip->un.v.num_channels = 2; 3920 strcpy(dip->un.v.units.name, AudioNvolume); 3921 break; 3922 3923 case GUSMAX_LINE_IN_MUTE: 3924 dip->mixer_class = GUSMAX_INPUT_CLASS; 3925 dip->type = AUDIO_MIXER_ENUM; 3926 dip->prev = GUSMAX_LINE_IN_LVL; 3927 dip->next = AUDIO_MIXER_LAST; 3928 goto mute; 3929 3930 case GUSMAX_DAC_MUTE: 3931 dip->mixer_class = GUSMAX_INPUT_CLASS; 3932 dip->type = AUDIO_MIXER_ENUM; 3933 dip->prev = GUSMAX_DAC_LVL; 3934 dip->next = AUDIO_MIXER_LAST; 3935 goto mute; 3936 3937 case GUSMAX_CD_MUTE: 3938 dip->mixer_class = GUSMAX_INPUT_CLASS; 3939 dip->type = AUDIO_MIXER_ENUM; 3940 dip->prev = GUSMAX_CD_LVL; 3941 dip->next = AUDIO_MIXER_LAST; 3942 goto mute; 3943 3944 case GUSMAX_MONO_MUTE: 3945 dip->mixer_class = GUSMAX_INPUT_CLASS; 3946 dip->type = AUDIO_MIXER_ENUM; 3947 dip->prev = GUSMAX_MONO_LVL; 3948 dip->next = AUDIO_MIXER_LAST; 3949 goto mute; 3950 3951 case GUSMAX_MONITOR_MUTE: 3952 dip->mixer_class = GUSMAX_OUTPUT_CLASS; 3953 dip->type = AUDIO_MIXER_ENUM; 3954 dip->prev = GUSMAX_MONITOR_LVL; 3955 dip->next = AUDIO_MIXER_LAST; 3956 goto mute; 3957 3958 case GUSMAX_SPEAKER_MUTE: 3959 dip->mixer_class = GUSMAX_OUTPUT_CLASS; 3960 dip->type = AUDIO_MIXER_ENUM; 3961 dip->prev = GUSMAX_SPEAKER_LVL; 3962 dip->next = AUDIO_MIXER_LAST; 3963 mute: 3964 strcpy(dip->label.name, AudioNmute); 3965 dip->un.e.num_mem = 2; 3966 strcpy(dip->un.e.member[0].label.name, AudioNoff); 3967 dip->un.e.member[0].ord = 0; 3968 strcpy(dip->un.e.member[1].label.name, AudioNon); 3969 dip->un.e.member[1].ord = 1; 3970 break; 3971 3972 case GUSMAX_REC_LVL: /* record level */ 3973 dip->type = AUDIO_MIXER_VALUE; 3974 dip->mixer_class = GUSMAX_RECORD_CLASS; 3975 dip->prev = AUDIO_MIXER_LAST; 3976 dip->next = GUSMAX_RECORD_SOURCE; 3977 strcpy(dip->label.name, AudioNrecord); 3978 dip->un.v.num_channels = 2; 3979 strcpy(dip->un.v.units.name, AudioNvolume); 3980 break; 3981 3982 case GUSMAX_RECORD_SOURCE: 3983 dip->mixer_class = GUSMAX_RECORD_CLASS; 3984 dip->type = AUDIO_MIXER_ENUM; 3985 dip->prev = GUSMAX_REC_LVL; 3986 dip->next = AUDIO_MIXER_LAST; 3987 strcpy(dip->label.name, AudioNsource); 3988 dip->un.e.num_mem = 4; 3989 strcpy(dip->un.e.member[0].label.name, AudioNoutput); 3990 dip->un.e.member[0].ord = DAC_IN_PORT; 3991 strcpy(dip->un.e.member[1].label.name, AudioNmicrophone); 3992 dip->un.e.member[1].ord = MIC_IN_PORT; 3993 strcpy(dip->un.e.member[2].label.name, AudioNdac); 3994 dip->un.e.member[2].ord = AUX1_IN_PORT; 3995 strcpy(dip->un.e.member[3].label.name, AudioNline); 3996 dip->un.e.member[3].ord = LINE_IN_PORT; 3997 break; 3998 3999 case GUSMAX_INPUT_CLASS: /* input class descriptor */ 4000 dip->type = AUDIO_MIXER_CLASS; 4001 dip->mixer_class = GUSMAX_INPUT_CLASS; 4002 dip->next = dip->prev = AUDIO_MIXER_LAST; 4003 strcpy(dip->label.name, AudioCInputs); 4004 break; 4005 4006 case GUSMAX_OUTPUT_CLASS: /* output class descriptor */ 4007 dip->type = AUDIO_MIXER_CLASS; 4008 dip->mixer_class = GUSMAX_OUTPUT_CLASS; 4009 dip->next = dip->prev = AUDIO_MIXER_LAST; 4010 strcpy(dip->label.name, AudioCOutputs); 4011 break; 4012 4013 case GUSMAX_MONITOR_CLASS: /* monitor class descriptor */ 4014 dip->type = AUDIO_MIXER_CLASS; 4015 dip->mixer_class = GUSMAX_MONITOR_CLASS; 4016 dip->next = dip->prev = AUDIO_MIXER_LAST; 4017 strcpy(dip->label.name, AudioCMonitor); 4018 break; 4019 4020 case GUSMAX_RECORD_CLASS: /* record source class */ 4021 dip->type = AUDIO_MIXER_CLASS; 4022 dip->mixer_class = GUSMAX_RECORD_CLASS; 4023 dip->next = dip->prev = AUDIO_MIXER_LAST; 4024 strcpy(dip->label.name, AudioCRecord); 4025 break; 4026 4027 default: 4028 return ENXIO; 4029 /*NOTREACHED*/ 4030 } 4031 DPRINTF(("AUDIO_MIXER_DEVINFO: name=%s\n", dip->label.name)); 4032 return 0; 4033} 4034 4035STATIC int 4036gus_mixer_query_devinfo(addr, dip) 4037 void *addr; 4038 register mixer_devinfo_t *dip; 4039{ 4040 register struct gus_softc *sc = addr; 4041 4042 DPRINTF(("gusmax_query_devinfo: index=%d\n", dip->index)); 4043 4044 if (!HAS_MIXER(sc) && dip->index > GUSICS_MASTER_MUTE) 4045 return ENXIO; 4046 4047 switch(dip->index) { 4048 4049 case GUSICS_MIC_IN_LVL: /* Microphone */ 4050 dip->type = AUDIO_MIXER_VALUE; 4051 dip->mixer_class = GUSICS_INPUT_CLASS; 4052 dip->prev = AUDIO_MIXER_LAST; 4053 dip->next = GUSICS_MIC_IN_MUTE; 4054 strcpy(dip->label.name, AudioNmicrophone); 4055 dip->un.v.num_channels = 2; 4056 strcpy(dip->un.v.units.name, AudioNvolume); 4057 break; 4058 4059 case GUSICS_LINE_IN_LVL: /* line */ 4060 dip->type = AUDIO_MIXER_VALUE; 4061 dip->mixer_class = GUSICS_INPUT_CLASS; 4062 dip->prev = AUDIO_MIXER_LAST; 4063 dip->next = GUSICS_LINE_IN_MUTE; 4064 strcpy(dip->label.name, AudioNline); 4065 dip->un.v.num_channels = 2; 4066 strcpy(dip->un.v.units.name, AudioNvolume); 4067 break; 4068 4069 case GUSICS_CD_LVL: /* cd */ 4070 dip->type = AUDIO_MIXER_VALUE; 4071 dip->mixer_class = GUSICS_INPUT_CLASS; 4072 dip->prev = AUDIO_MIXER_LAST; 4073 dip->next = GUSICS_CD_MUTE; 4074 strcpy(dip->label.name, AudioNcd); 4075 dip->un.v.num_channels = 2; 4076 strcpy(dip->un.v.units.name, AudioNvolume); 4077 break; 4078 4079 case GUSICS_DAC_LVL: /* dacout */ 4080 dip->type = AUDIO_MIXER_VALUE; 4081 dip->mixer_class = GUSICS_INPUT_CLASS; 4082 dip->prev = AUDIO_MIXER_LAST; 4083 dip->next = GUSICS_DAC_MUTE; 4084 strcpy(dip->label.name, AudioNdac); 4085 dip->un.v.num_channels = 2; 4086 strcpy(dip->un.v.units.name, AudioNvolume); 4087 break; 4088 4089 case GUSICS_MASTER_LVL: /* master output */ 4090 dip->type = AUDIO_MIXER_VALUE; 4091 dip->mixer_class = GUSICS_OUTPUT_CLASS; 4092 dip->prev = AUDIO_MIXER_LAST; 4093 dip->next = GUSICS_MASTER_MUTE; 4094 strcpy(dip->label.name, AudioNvolume); 4095 dip->un.v.num_channels = 2; 4096 strcpy(dip->un.v.units.name, AudioNvolume); 4097 break; 4098 4099 4100 case GUSICS_LINE_IN_MUTE: 4101 dip->mixer_class = GUSICS_INPUT_CLASS; 4102 dip->type = AUDIO_MIXER_ENUM; 4103 dip->prev = GUSICS_LINE_IN_LVL; 4104 dip->next = AUDIO_MIXER_LAST; 4105 goto mute; 4106 4107 case GUSICS_DAC_MUTE: 4108 dip->mixer_class = GUSICS_INPUT_CLASS; 4109 dip->type = AUDIO_MIXER_ENUM; 4110 dip->prev = GUSICS_DAC_LVL; 4111 dip->next = AUDIO_MIXER_LAST; 4112 goto mute; 4113 4114 case GUSICS_CD_MUTE: 4115 dip->mixer_class = GUSICS_INPUT_CLASS; 4116 dip->type = AUDIO_MIXER_ENUM; 4117 dip->prev = GUSICS_CD_LVL; 4118 dip->next = AUDIO_MIXER_LAST; 4119 goto mute; 4120 4121 case GUSICS_MIC_IN_MUTE: 4122 dip->mixer_class = GUSICS_INPUT_CLASS; 4123 dip->type = AUDIO_MIXER_ENUM; 4124 dip->prev = GUSICS_MIC_IN_LVL; 4125 dip->next = AUDIO_MIXER_LAST; 4126 goto mute; 4127 4128 case GUSICS_MASTER_MUTE: 4129 dip->mixer_class = GUSICS_OUTPUT_CLASS; 4130 dip->type = AUDIO_MIXER_ENUM; 4131 dip->prev = GUSICS_MASTER_LVL; 4132 dip->next = AUDIO_MIXER_LAST; 4133mute: 4134 strcpy(dip->label.name, AudioNmute); 4135 dip->un.e.num_mem = 2; 4136 strcpy(dip->un.e.member[0].label.name, AudioNoff); 4137 dip->un.e.member[0].ord = 0; 4138 strcpy(dip->un.e.member[1].label.name, AudioNon); 4139 dip->un.e.member[1].ord = 1; 4140 break; 4141 4142 case GUSICS_RECORD_SOURCE: 4143 dip->mixer_class = GUSICS_RECORD_CLASS; 4144 dip->type = AUDIO_MIXER_ENUM; 4145 dip->prev = dip->next = AUDIO_MIXER_LAST; 4146 strcpy(dip->label.name, AudioNsource); 4147 dip->un.e.num_mem = 1; 4148 strcpy(dip->un.e.member[0].label.name, AudioNoutput); 4149 dip->un.e.member[0].ord = GUSICS_MASTER_LVL; 4150 break; 4151 4152 case GUSICS_INPUT_CLASS: 4153 dip->type = AUDIO_MIXER_CLASS; 4154 dip->mixer_class = GUSICS_INPUT_CLASS; 4155 dip->next = dip->prev = AUDIO_MIXER_LAST; 4156 strcpy(dip->label.name, AudioCInputs); 4157 break; 4158 4159 case GUSICS_OUTPUT_CLASS: 4160 dip->type = AUDIO_MIXER_CLASS; 4161 dip->mixer_class = GUSICS_OUTPUT_CLASS; 4162 dip->next = dip->prev = AUDIO_MIXER_LAST; 4163 strcpy(dip->label.name, AudioCOutputs); 4164 break; 4165 4166 case GUSICS_RECORD_CLASS: 4167 dip->type = AUDIO_MIXER_CLASS; 4168 dip->mixer_class = GUSICS_RECORD_CLASS; 4169 dip->next = dip->prev = AUDIO_MIXER_LAST; 4170 strcpy(dip->label.name, AudioCRecord); 4171 break; 4172 4173 default: 4174 return ENXIO; 4175 /*NOTREACHED*/ 4176 } 4177 DPRINTF(("AUDIO_MIXER_DEVINFO: name=%s\n", dip->label.name)); 4178 return 0; 4179} 4180 4181STATIC int 4182gus_query_encoding(addr, fp) 4183 void *addr; 4184 struct audio_encoding *fp; 4185{ 4186 switch (fp->index) { 4187 case 0: 4188 strcpy(fp->name, AudioEmulaw); 4189 fp->encoding = AUDIO_ENCODING_ULAW; 4190 fp->precision = 8; 4191 fp->flags = AUDIO_ENCODINGFLAG_EMULATED; 4192 break; 4193 case 1: 4194 strcpy(fp->name, AudioElinear); 4195 fp->encoding = AUDIO_ENCODING_SLINEAR; 4196 fp->precision = 8; 4197 fp->flags = 0; 4198 break; 4199 case 2: 4200 strcpy(fp->name, AudioElinear_le); 4201 fp->encoding = AUDIO_ENCODING_SLINEAR_LE; 4202 fp->precision = 16; 4203 fp->flags = 0; 4204 break; 4205 case 3: 4206 strcpy(fp->name, AudioEulinear); 4207 fp->encoding = AUDIO_ENCODING_ULINEAR; 4208 fp->precision = 8; 4209 fp->flags = 0; 4210 break; 4211 case 4: 4212 strcpy(fp->name, AudioEulinear_le); 4213 fp->encoding = AUDIO_ENCODING_ULINEAR_LE; 4214 fp->precision = 16; 4215 fp->flags = 0; 4216 break; 4217 case 5: 4218 strcpy(fp->name, AudioElinear_be); 4219 fp->encoding = AUDIO_ENCODING_SLINEAR_BE; 4220 fp->precision = 16; 4221 fp->flags = AUDIO_ENCODINGFLAG_EMULATED; 4222 break; 4223 case 6: 4224 strcpy(fp->name, AudioEulinear_be); 4225 fp->encoding = AUDIO_ENCODING_ULINEAR_BE; 4226 fp->precision = 16; 4227 fp->flags = AUDIO_ENCODINGFLAG_EMULATED; 4228 break; 4229 default: 4230 return(EINVAL); 4231 /*NOTREACHED*/ 4232 } 4233 return (0); 4234} 4235 4236/* 4237 * Setup the ICS mixer in "transparent" mode: reset everything to a sensible 4238 * level. Levels as suggested by GUS SDK code. 4239 */ 4240 4241STATIC void 4242gus_init_ics2101(sc) 4243 struct gus_softc *sc; 4244{ 4245 register int port = sc->sc_iobase; 4246 register struct ics2101_softc *ic = &sc->sc_mixer; 4247 sc->sc_mixer.sc_selio = port+GUS_MIXER_SELECT; 4248 sc->sc_mixer.sc_dataio = port+GUS_MIXER_DATA; 4249 sc->sc_mixer.sc_flags = (sc->sc_revision == 5) ? ICS_FLIP : 0; 4250 4251 ics2101_mix_attenuate(ic, 4252 GUSMIX_CHAN_MIC, 4253 ICSMIX_LEFT, 4254 ICSMIX_MIN_ATTN); 4255 ics2101_mix_attenuate(ic, 4256 GUSMIX_CHAN_MIC, 4257 ICSMIX_RIGHT, 4258 ICSMIX_MIN_ATTN); 4259 /* 4260 * Start with microphone muted by the mixer... 4261 */ 4262 gusics_mic_mute(ic, 1); 4263 4264 /* ... and enabled by the GUS master mix control */ 4265 gus_mic_ctl(sc, SPKR_ON); 4266 4267 ics2101_mix_attenuate(ic, 4268 GUSMIX_CHAN_LINE, 4269 ICSMIX_LEFT, 4270 ICSMIX_MIN_ATTN); 4271 ics2101_mix_attenuate(ic, 4272 GUSMIX_CHAN_LINE, 4273 ICSMIX_RIGHT, 4274 ICSMIX_MIN_ATTN); 4275 4276 ics2101_mix_attenuate(ic, 4277 GUSMIX_CHAN_CD, 4278 ICSMIX_LEFT, 4279 ICSMIX_MIN_ATTN); 4280 ics2101_mix_attenuate(ic, 4281 GUSMIX_CHAN_CD, 4282 ICSMIX_RIGHT, 4283 ICSMIX_MIN_ATTN); 4284 4285 ics2101_mix_attenuate(ic, 4286 GUSMIX_CHAN_DAC, 4287 ICSMIX_LEFT, 4288 ICSMIX_MIN_ATTN); 4289 ics2101_mix_attenuate(ic, 4290 GUSMIX_CHAN_DAC, 4291 ICSMIX_RIGHT, 4292 ICSMIX_MIN_ATTN); 4293 4294 ics2101_mix_attenuate(ic, 4295 ICSMIX_CHAN_4, 4296 ICSMIX_LEFT, 4297 ICSMIX_MAX_ATTN); 4298 ics2101_mix_attenuate(ic, 4299 ICSMIX_CHAN_4, 4300 ICSMIX_RIGHT, 4301 ICSMIX_MAX_ATTN); 4302 4303 ics2101_mix_attenuate(ic, 4304 GUSMIX_CHAN_MASTER, 4305 ICSMIX_LEFT, 4306 ICSMIX_MIN_ATTN); 4307 ics2101_mix_attenuate(ic, 4308 GUSMIX_CHAN_MASTER, 4309 ICSMIX_RIGHT, 4310 ICSMIX_MIN_ATTN); 4311 /* unmute other stuff: */ 4312 gusics_cd_mute(ic, 0); 4313 gusics_dac_mute(ic, 0); 4314 gusics_linein_mute(ic, 0); 4315 return; 4316} 4317 4318 4319#endif /* NGUS */ 4320