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