[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.26

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

CVSweb <webmaster@jp.NetBSD.org>