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