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