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

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

CVSweb <webmaster@jp.NetBSD.org>