[BACK]Return to gus.c CVS log [TXT][DIR] Up to [cvs.NetBSD.org] / src / sys / dev / isa

Annotation of src/sys/dev/isa/gus.c, Revision 1.19

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

CVSweb <webmaster@jp.NetBSD.org>