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