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

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

CVSweb <webmaster@jp.NetBSD.org>