[BACK]Return to ess.c CVS log [TXT][DIR] Up to [local] / sys / dev / isa

Annotation of sys/dev/isa/ess.c, Revision 1.1.1.1

1.1       nbrk        1: /*     $OpenBSD: ess.c,v 1.11 2006/02/22 19:43:42 miod Exp $   */
                      2: /*     $NetBSD: ess.c,v 1.44.4.1 1999/06/21 01:18:00 thorpej Exp $     */
                      3:
                      4: /*
                      5:  * Copyright 1997
                      6:  * Digital Equipment Corporation. All rights reserved.
                      7:  *
                      8:  * This software is furnished under license and may be used and
                      9:  * copied only in accordance with the following terms and conditions.
                     10:  * Subject to these conditions, you may download, copy, install,
                     11:  * use, modify and distribute this software in source and/or binary
                     12:  * form. No title or ownership is transferred hereby.
                     13:  *
                     14:  * 1) Any source code used, modified or distributed must reproduce
                     15:  *    and retain this copyright notice and list of conditions as
                     16:  *    they appear in the source file.
                     17:  *
                     18:  * 2) No right is granted to use any trade name, trademark, or logo of
                     19:  *    Digital Equipment Corporation. Neither the "Digital Equipment
                     20:  *    Corporation" name nor any trademark or logo of Digital Equipment
                     21:  *    Corporation may be used to endorse or promote products derived
                     22:  *    from this software without the prior written permission of
                     23:  *    Digital Equipment Corporation.
                     24:  *
                     25:  * 3) This software is provided "AS-IS" and any express or implied
                     26:  *    warranties, including but not limited to, any implied warranties
                     27:  *    of merchantability, fitness for a particular purpose, or
                     28:  *    non-infringement are disclaimed. In no event shall DIGITAL be
                     29:  *    liable for any damages whatsoever, and in particular, DIGITAL
                     30:  *    shall not be liable for special, indirect, consequential, or
                     31:  *    incidental damages or damages for lost profits, loss of
                     32:  *    revenue or loss of use, whether such damages arise in contract,
                     33:  *    negligence, tort, under statute, in equity, at law or otherwise,
                     34:  *    even if advised of the possibility of such damage.
                     35:  */
                     36:
                     37: /*
                     38: **++
                     39: **
                     40: **  ess.c
                     41: **
                     42: **  FACILITY:
                     43: **
                     44: **     DIGITAL Network Appliance Reference Design (DNARD)
                     45: **
                     46: **  MODULE DESCRIPTION:
                     47: **
                     48: **     This module contains the device driver for the ESS
                     49: **     Technologies 1888/1887/888 sound chip. The code in sbdsp.c was
                     50: **     used as a reference point when implementing this driver.
                     51: **
                     52: **  AUTHORS:
                     53: **
                     54: **     Blair Fidler    Software Engineering Australia
                     55: **                     Gold Coast, Australia.
                     56: **
                     57: **  CREATION DATE:
                     58: **
                     59: **     March 10, 1997.
                     60: **
                     61: **  MODIFICATION HISTORY:
                     62: **
                     63: **     Heavily modified by Lennart Augustsson and Charles M. Hannum for
                     64: **     bus_dma, changes to audio interface, and many bug fixes.
                     65: **     ESS1788 support by Nathan J. Williams and Charles M. Hannum.
                     66: **--
                     67: */
                     68:
                     69: #include <sys/param.h>
                     70: #include <sys/systm.h>
                     71: #include <sys/errno.h>
                     72: #include <sys/ioctl.h>
                     73: #include <sys/syslog.h>
                     74: #include <sys/device.h>
                     75: #include <sys/proc.h>
                     76: #include <sys/kernel.h>
                     77: #include <sys/timeout.h>
                     78:
                     79: #include <machine/cpu.h>
                     80: #include <machine/intr.h>
                     81: #include <machine/bus.h>
                     82:
                     83: #include <sys/audioio.h>
                     84: #include <dev/audio_if.h>
                     85: #include <dev/auconv.h>
                     86: #include <dev/mulaw.h>
                     87:
                     88: #include <dev/isa/isavar.h>
                     89: #include <dev/isa/isadmavar.h>
                     90:
                     91: #include <dev/isa/essvar.h>
                     92: #include <dev/isa/essreg.h>
                     93:
                     94: #ifdef AUDIO_DEBUG
                     95: #define DPRINTF(x)     if (essdebug) printf x
                     96: #define DPRINTFN(n,x)  if (essdebug>(n)) printf x
                     97: int    essdebug = 0;
                     98: #else
                     99: #define DPRINTF(x)
                    100: #define DPRINTFN(n,x)
                    101: #endif
                    102:
                    103: #if 0
                    104: unsigned uuu;
                    105: #define EREAD1(t, h, a) (uuu=bus_space_read_1(t, h, a),printf("EREAD  %02x=%02x\n", ((int)h&0xfff)+a, uuu),uuu)
                    106: #define EWRITE1(t, h, a, d) (printf("EWRITE %02x=%02x\n", ((int)h & 0xfff)+a, d), bus_space_write_1(t, h, a, d))
                    107: #else
                    108: #define EREAD1(t, h, a) bus_space_read_1(t, h, a)
                    109: #define EWRITE1(t, h, a, d) bus_space_write_1(t, h, a, d)
                    110: #endif
                    111:
                    112: struct cfdriver ess_cd = {
                    113:        NULL, "ess", DV_DULL
                    114: };
                    115:
                    116: int    ess_setup_sc(struct ess_softc *, int);
                    117:
                    118: int    ess_open(void *, int);
                    119: void   ess_1788_close(void *);
                    120: void   ess_1888_close(void *);
                    121: int    ess_getdev(void *, struct audio_device *);
                    122: int    ess_drain(void *);
                    123:
                    124: int    ess_query_encoding(void *, struct audio_encoding *);
                    125:
                    126: int    ess_set_params(void *, int, int, struct audio_params *,
                    127:            struct audio_params *);
                    128:
                    129: int    ess_round_blocksize(void *, int);
                    130:
                    131: int    ess_audio1_trigger_output(void *, void *, void *, int,
                    132:            void (*)(void *), void *, struct audio_params *);
                    133: int    ess_audio2_trigger_output(void *, void *, void *, int,
                    134:            void (*)(void *), void *, struct audio_params *);
                    135: int    ess_audio1_trigger_input(void *, void *, void *, int,
                    136:            void (*)(void *), void *, struct audio_params *);
                    137: int    ess_audio1_halt(void *);
                    138: int    ess_audio2_halt(void *);
                    139: int    ess_audio1_intr(void *);
                    140: int    ess_audio2_intr(void *);
                    141: void   ess_audio1_poll(void *);
                    142: void   ess_audio2_poll(void *);
                    143:
                    144: int    ess_speaker_ctl(void *, int);
                    145:
                    146: int    ess_getdev(void *, struct audio_device *);
                    147:
                    148: int    ess_set_port(void *, mixer_ctrl_t *);
                    149: int    ess_get_port(void *, mixer_ctrl_t *);
                    150:
                    151: void   *ess_malloc(void *, int, size_t, int, int);
                    152: void   ess_free(void *, void *, int);
                    153: size_t ess_round_buffersize(void *, int, size_t);
                    154: paddr_t        ess_mappage(void *, void *, off_t, int);
                    155:
                    156:
                    157: int    ess_query_devinfo(void *, mixer_devinfo_t *);
                    158: int    ess_1788_get_props(void *);
                    159: int    ess_1888_get_props(void *);
                    160:
                    161: void   ess_speaker_on(struct ess_softc *);
                    162: void   ess_speaker_off(struct ess_softc *);
                    163:
                    164: int    ess_config_addr(struct ess_softc *);
                    165: void   ess_config_irq(struct ess_softc *);
                    166: void   ess_config_drq(struct ess_softc *);
                    167: void   ess_setup(struct ess_softc *);
                    168: int    ess_identify(struct ess_softc *);
                    169:
                    170: int    ess_reset(struct ess_softc *);
                    171: void   ess_set_gain(struct ess_softc *, int, int);
                    172: int    ess_set_in_port(struct ess_softc *, int);
                    173: int    ess_set_in_ports(struct ess_softc *, int);
                    174: u_int  ess_srtotc(u_int);
                    175: u_int  ess_srtofc(u_int);
                    176: u_char ess_get_dsp_status(struct ess_softc *);
                    177: u_char ess_dsp_read_ready(struct ess_softc *);
                    178: u_char ess_dsp_write_ready(struct ess_softc *);
                    179: int    ess_rdsp(struct ess_softc *);
                    180: int    ess_wdsp(struct ess_softc *, u_char);
                    181: u_char ess_read_x_reg(struct ess_softc *, u_char);
                    182: int    ess_write_x_reg(struct ess_softc *, u_char, u_char);
                    183: void   ess_clear_xreg_bits(struct ess_softc *, u_char, u_char);
                    184: void   ess_set_xreg_bits(struct ess_softc *, u_char, u_char);
                    185: u_char ess_read_mix_reg(struct ess_softc *, u_char);
                    186: void   ess_write_mix_reg(struct ess_softc *, u_char, u_char);
                    187: void   ess_clear_mreg_bits(struct ess_softc *, u_char, u_char);
                    188: void   ess_set_mreg_bits(struct ess_softc *, u_char, u_char);
                    189: void   ess_read_multi_mix_reg(struct ess_softc *, u_char, u_int8_t *, bus_size_t);
                    190:
                    191: static char *essmodel[] = {
                    192:        "unsupported",
                    193:        "1888",
                    194:        "1887",
                    195:        "888",
                    196:        "1788",
                    197:        "1869",
                    198:        "1879",
                    199:        "1868",
                    200:        "1878",
                    201: };
                    202:
                    203: struct audio_device ess_device = {
                    204:        "ESS Technology",
                    205:        "x",
                    206:        "ess"
                    207: };
                    208:
                    209: /*
                    210:  * Define our interface to the higher level audio driver.
                    211:  */
                    212:
                    213: struct audio_hw_if ess_1788_hw_if = {
                    214:        ess_open,
                    215:        ess_1788_close,
                    216:        ess_drain,
                    217:        ess_query_encoding,
                    218:        ess_set_params,
                    219:        ess_round_blocksize,
                    220:        NULL,
                    221:        NULL,
                    222:        NULL,
                    223:        NULL,
                    224:        NULL,
                    225:        ess_audio1_halt,
                    226:        ess_audio1_halt,
                    227:        ess_speaker_ctl,
                    228:        ess_getdev,
                    229:        NULL,
                    230:        ess_set_port,
                    231:        ess_get_port,
                    232:        ess_query_devinfo,
                    233:        ess_malloc,
                    234:        ess_free,
                    235:        ess_round_buffersize,
                    236:        ess_mappage,
                    237:        ess_1788_get_props,
                    238:        ess_audio1_trigger_output,
                    239:        ess_audio1_trigger_input,
                    240: };
                    241:
                    242: struct audio_hw_if ess_1888_hw_if = {
                    243:        ess_open,
                    244:        ess_1888_close,
                    245:        ess_drain,
                    246:        ess_query_encoding,
                    247:        ess_set_params,
                    248:        ess_round_blocksize,
                    249:        NULL,
                    250:        NULL,
                    251:        NULL,
                    252:        NULL,
                    253:        NULL,
                    254:        ess_audio2_halt,
                    255:        ess_audio1_halt,
                    256:        ess_speaker_ctl,
                    257:        ess_getdev,
                    258:        NULL,
                    259:        ess_set_port,
                    260:        ess_get_port,
                    261:        ess_query_devinfo,
                    262:        ess_malloc,
                    263:        ess_free,
                    264:        ess_round_buffersize,
                    265:        ess_mappage,
                    266:        ess_1888_get_props,
                    267:        ess_audio2_trigger_output,
                    268:        ess_audio1_trigger_input,
                    269: };
                    270:
                    271: #ifdef AUDIO_DEBUG
                    272: void ess_printsc(struct ess_softc *);
                    273: void ess_dump_mixer(struct ess_softc *);
                    274:
                    275: void
                    276: ess_printsc(sc)
                    277:        struct ess_softc *sc;
                    278: {
                    279:        int i;
                    280:
                    281:        printf("open %d iobase 0x%x outport %u inport %u speaker %s\n",
                    282:               (int)sc->sc_open, sc->sc_iobase, sc->out_port,
                    283:               sc->in_port, sc->spkr_state ? "on" : "off");
                    284:
                    285:        printf("audio1: dmachan %d irq %d nintr %lu intr %p arg %p\n",
                    286:               sc->sc_audio1.drq, sc->sc_audio1.irq, sc->sc_audio1.nintr,
                    287:               sc->sc_audio1.intr, sc->sc_audio1.arg);
                    288:
                    289:        if (!ESS_USE_AUDIO1(sc->sc_model)) {
                    290:                printf("audio2: dmachan %d irq %d nintr %lu intr %p arg %p\n",
                    291:                       sc->sc_audio2.drq, sc->sc_audio2.irq, sc->sc_audio2.nintr,
                    292:                       sc->sc_audio2.intr, sc->sc_audio2.arg);
                    293:        }
                    294:
                    295:        printf("gain:");
                    296:        for (i = 0; i < sc->ndevs; i++)
                    297:                printf(" %u,%u", sc->gain[i][ESS_LEFT], sc->gain[i][ESS_RIGHT]);
                    298:        printf("\n");
                    299: }
                    300:
                    301: void
                    302: ess_dump_mixer(sc)
                    303:        struct ess_softc *sc;
                    304: {
                    305:        printf("ESS_DAC_PLAY_VOL: mix reg 0x%02x=0x%02x\n",
                    306:               0x7C, ess_read_mix_reg(sc, 0x7C));
                    307:        printf("ESS_MIC_PLAY_VOL: mix reg 0x%02x=0x%02x\n",
                    308:               0x1A, ess_read_mix_reg(sc, 0x1A));
                    309:        printf("ESS_LINE_PLAY_VOL: mix reg 0x%02x=0x%02x\n",
                    310:               0x3E, ess_read_mix_reg(sc, 0x3E));
                    311:        printf("ESS_SYNTH_PLAY_VOL: mix reg 0x%02x=0x%02x\n",
                    312:               0x36, ess_read_mix_reg(sc, 0x36));
                    313:        printf("ESS_CD_PLAY_VOL: mix reg 0x%02x=0x%02x\n",
                    314:               0x38, ess_read_mix_reg(sc, 0x38));
                    315:        printf("ESS_AUXB_PLAY_VOL: mix reg 0x%02x=0x%02x\n",
                    316:               0x3A, ess_read_mix_reg(sc, 0x3A));
                    317:        printf("ESS_MASTER_VOL: mix reg 0x%02x=0x%02x\n",
                    318:               0x32, ess_read_mix_reg(sc, 0x32));
                    319:        printf("ESS_PCSPEAKER_VOL: mix reg 0x%02x=0x%02x\n",
                    320:               0x3C, ess_read_mix_reg(sc, 0x3C));
                    321:        printf("ESS_DAC_REC_VOL: mix reg 0x%02x=0x%02x\n",
                    322:               0x69, ess_read_mix_reg(sc, 0x69));
                    323:        printf("ESS_MIC_REC_VOL: mix reg 0x%02x=0x%02x\n",
                    324:               0x68, ess_read_mix_reg(sc, 0x68));
                    325:        printf("ESS_LINE_REC_VOL: mix reg 0x%02x=0x%02x\n",
                    326:               0x6E, ess_read_mix_reg(sc, 0x6E));
                    327:        printf("ESS_SYNTH_REC_VOL: mix reg 0x%02x=0x%02x\n",
                    328:               0x6B, ess_read_mix_reg(sc, 0x6B));
                    329:        printf("ESS_CD_REC_VOL: mix reg 0x%02x=0x%02x\n",
                    330:               0x6A, ess_read_mix_reg(sc, 0x6A));
                    331:        printf("ESS_AUXB_REC_VOL: mix reg 0x%02x=0x%02x\n",
                    332:               0x6C, ess_read_mix_reg(sc, 0x6C));
                    333:        printf("ESS_RECORD_VOL: x reg 0x%02x=0x%02x\n",
                    334:               0xB4, ess_read_x_reg(sc, 0xB4));
                    335:        printf("Audio 1 play vol (unused): mix reg 0x%02x=0x%02x\n",
                    336:               0x14, ess_read_mix_reg(sc, 0x14));
                    337:
                    338:        printf("ESS_MIC_PREAMP: x reg 0x%02x=0x%02x\n",
                    339:               ESS_XCMD_PREAMP_CTRL, ess_read_x_reg(sc, ESS_XCMD_PREAMP_CTRL));
                    340:        printf("ESS_RECORD_MONITOR: x reg 0x%02x=0x%02x\n",
                    341:               ESS_XCMD_AUDIO_CTRL, ess_read_x_reg(sc, ESS_XCMD_AUDIO_CTRL));
                    342:        printf("Record source: mix reg 0x%02x=0x%02x, 0x%02x=0x%02x\n",
                    343:               ESS_MREG_ADC_SOURCE, ess_read_mix_reg(sc, ESS_MREG_ADC_SOURCE),
                    344:               ESS_MREG_AUDIO2_CTRL2, ess_read_mix_reg(sc, ESS_MREG_AUDIO2_CTRL2));
                    345: }
                    346:
                    347: #endif
                    348:
                    349: /*
                    350:  * Configure the ESS chip for the desired audio base address.
                    351:  */
                    352: int
                    353: ess_config_addr(sc)
                    354:        struct ess_softc *sc;
                    355: {
                    356:        int iobase = sc->sc_iobase;
                    357:        bus_space_tag_t iot = sc->sc_iot;
                    358:
                    359:        /*
                    360:         * Configure using the System Control Register method.  This
                    361:         * method is used when the AMODE line is tied high, which is
                    362:         * the case for the Shark, but not for the evaluation board.
                    363:         */
                    364:
                    365:        bus_space_handle_t scr_access_ioh;
                    366:        bus_space_handle_t scr_ioh;
                    367:        u_short scr_value;
                    368:
                    369:        /*
                    370:         * Set the SCR bit to enable audio.
                    371:         */
                    372:        scr_value = ESS_SCR_AUDIO_ENABLE;
                    373:
                    374:        /*
                    375:         * Set the SCR bits necessary to select the specified audio
                    376:         * base address.
                    377:         */
                    378:        switch(iobase) {
                    379:        case 0x220:
                    380:                scr_value |= ESS_SCR_AUDIO_220;
                    381:                break;
                    382:        case 0x230:
                    383:                scr_value |= ESS_SCR_AUDIO_230;
                    384:                break;
                    385:        case 0x240:
                    386:                scr_value |= ESS_SCR_AUDIO_240;
                    387:                break;
                    388:        case 0x250:
                    389:                scr_value |= ESS_SCR_AUDIO_250;
                    390:                break;
                    391:        default:
                    392:                printf("ess: configured iobase 0x%x invalid\n", iobase);
                    393:                return (1);
                    394:                break;
                    395:        }
                    396:
                    397:        /*
                    398:         * Get a mapping for the System Control Register (SCR) access
                    399:         * registers and the SCR data registers.
                    400:         */
                    401:        if (bus_space_map(iot, ESS_SCR_ACCESS_BASE, ESS_SCR_ACCESS_PORTS,
                    402:                          0, &scr_access_ioh)) {
                    403:                printf("ess: can't map SCR access registers\n");
                    404:                return (1);
                    405:        }
                    406:        if (bus_space_map(iot, ESS_SCR_BASE, ESS_SCR_PORTS,
                    407:                          0, &scr_ioh)) {
                    408:                printf("ess: can't map SCR registers\n");
                    409:                bus_space_unmap(iot, scr_access_ioh, ESS_SCR_ACCESS_PORTS);
                    410:                return (1);
                    411:        }
                    412:
                    413:        /* Unlock the SCR. */
                    414:        EWRITE1(iot, scr_access_ioh, ESS_SCR_UNLOCK, 0);
                    415:
                    416:        /* Write the base address information into SCR[0]. */
                    417:        EWRITE1(iot, scr_ioh, ESS_SCR_INDEX, 0);
                    418:        EWRITE1(iot, scr_ioh, ESS_SCR_DATA, scr_value);
                    419:
                    420:        /* Lock the SCR. */
                    421:        EWRITE1(iot, scr_access_ioh, ESS_SCR_LOCK, 0);
                    422:
                    423:        /* Unmap the SCR access ports and the SCR data ports. */
                    424:        bus_space_unmap(iot, scr_access_ioh, ESS_SCR_ACCESS_PORTS);
                    425:        bus_space_unmap(iot, scr_ioh, ESS_SCR_PORTS);
                    426:
                    427:        return 0;
                    428: }
                    429:
                    430:
                    431: /*
                    432:  * Configure the ESS chip for the desired IRQ and DMA channels.
                    433:  * ESS  ISA
                    434:  * --------
                    435:  * IRQA irq9
                    436:  * IRQB irq5
                    437:  * IRQC irq7
                    438:  * IRQD irq10
                    439:  * IRQE irq15
                    440:  *
                    441:  * DRQA drq0
                    442:  * DRQB drq1
                    443:  * DRQC drq3
                    444:  * DRQD drq5
                    445:  */
                    446: void
                    447: ess_config_irq(sc)
                    448:        struct ess_softc *sc;
                    449: {
                    450:        int v;
                    451:
                    452:        DPRINTFN(2,("ess_config_irq\n"));
                    453:
                    454:        if (sc->sc_model == ESS_1887 &&
                    455:            sc->sc_audio1.irq == sc->sc_audio2.irq &&
                    456:            sc->sc_audio1.irq != -1) {
                    457:                /* Use new method, both interrupts are the same. */
                    458:                v = ESS_IS_SELECT_IRQ;  /* enable intrs */
                    459:                switch (sc->sc_audio1.irq) {
                    460:                case 5:
                    461:                        v |= ESS_IS_INTRB;
                    462:                        break;
                    463:                case 7:
                    464:                        v |= ESS_IS_INTRC;
                    465:                        break;
                    466:                case 9:
                    467:                        v |= ESS_IS_INTRA;
                    468:                        break;
                    469:                case 10:
                    470:                        v |= ESS_IS_INTRD;
                    471:                        break;
                    472:                case 15:
                    473:                        v |= ESS_IS_INTRE;
                    474:                        break;
                    475: #ifdef DIAGNOSTIC
                    476:                default:
                    477:                        printf("ess_config_irq: configured irq %d not supported for Audio 1\n",
                    478:                               sc->sc_audio1.irq);
                    479:                        return;
                    480: #endif
                    481:                }
                    482:                /* Set the IRQ */
                    483:                ess_write_mix_reg(sc, ESS_MREG_INTR_ST, v);
                    484:                return;
                    485:        }
                    486:
                    487:        if (sc->sc_model == ESS_1887) {
                    488:                /* Tell the 1887 to use the old interrupt method. */
                    489:                ess_write_mix_reg(sc, ESS_MREG_INTR_ST, ESS_IS_ES1888);
                    490:        }
                    491:
                    492:        if (sc->sc_audio1.polled) {
                    493:                /* Turn off Audio1 interrupts. */
                    494:                v = 0;
                    495:        } else {
                    496:                /* Configure Audio 1 for the appropriate IRQ line. */
                    497:                v = ESS_IRQ_CTRL_MASK | ESS_IRQ_CTRL_EXT; /* All intrs on */
                    498:                switch (sc->sc_audio1.irq) {
                    499:                case 5:
                    500:                        v |= ESS_IRQ_CTRL_INTRB;
                    501:                        break;
                    502:                case 7:
                    503:                        v |= ESS_IRQ_CTRL_INTRC;
                    504:                        break;
                    505:                case 9:
                    506:                        v |= ESS_IRQ_CTRL_INTRA;
                    507:                        break;
                    508:                case 10:
                    509:                        v |= ESS_IRQ_CTRL_INTRD;
                    510:                        break;
                    511: #ifdef DIAGNOSTIC
                    512:                default:
                    513:                        printf("ess: configured irq %d not supported for Audio 1\n",
                    514:                               sc->sc_audio1.irq);
                    515:                        return;
                    516: #endif
                    517:                }
                    518:        }
                    519:        ess_write_x_reg(sc, ESS_XCMD_IRQ_CTRL, v);
                    520:
                    521:        if (ESS_USE_AUDIO1(sc->sc_model))
                    522:                return;
                    523:
                    524:        if (sc->sc_audio2.polled) {
                    525:                /* Turn off Audio2 interrupts. */
                    526:                ess_clear_mreg_bits(sc, ESS_MREG_AUDIO2_CTRL2,
                    527:                                    ESS_AUDIO2_CTRL2_IRQ2_ENABLE);
                    528:        } else {
                    529:                /* Audio2 is hardwired to INTRE in this mode. */
                    530:                ess_set_mreg_bits(sc, ESS_MREG_AUDIO2_CTRL2,
                    531:                                  ESS_AUDIO2_CTRL2_IRQ2_ENABLE);
                    532:        }
                    533: }
                    534:
                    535:
                    536: void
                    537: ess_config_drq(sc)
                    538:        struct ess_softc *sc;
                    539: {
                    540:        int v;
                    541:
                    542:        DPRINTFN(2,("ess_config_drq\n"));
                    543:
                    544:        /* Configure Audio 1 (record) for DMA on the appropriate channel. */
                    545:        v = ESS_DRQ_CTRL_PU | ESS_DRQ_CTRL_EXT;
                    546:        switch (sc->sc_audio1.drq) {
                    547:        case 0:
                    548:                v |= ESS_DRQ_CTRL_DRQA;
                    549:                break;
                    550:        case 1:
                    551:                v |= ESS_DRQ_CTRL_DRQB;
                    552:                break;
                    553:        case 3:
                    554:                v |= ESS_DRQ_CTRL_DRQC;
                    555:                break;
                    556: #ifdef DIAGNOSTIC
                    557:        default:
                    558:                printf("ess_config_drq: configured dma chan %d not supported for Audio 1\n",
                    559:                       sc->sc_audio1.drq);
                    560:                return;
                    561: #endif
                    562:        }
                    563:        /* Set DRQ1 */
                    564:        ess_write_x_reg(sc, ESS_XCMD_DRQ_CTRL, v);
                    565:
                    566:        if (ESS_USE_AUDIO1(sc->sc_model))
                    567:                return;
                    568:
                    569:        /* Configure DRQ2 */
                    570:        v = ESS_AUDIO2_CTRL3_DRQ_PD;
                    571:        switch (sc->sc_audio2.drq) {
                    572:        case 0:
                    573:                v |= ESS_AUDIO2_CTRL3_DRQA;
                    574:                break;
                    575:        case 1:
                    576:                v |= ESS_AUDIO2_CTRL3_DRQB;
                    577:                break;
                    578:        case 3:
                    579:                v |= ESS_AUDIO2_CTRL3_DRQC;
                    580:                break;
                    581:        case 5:
                    582:                v |= ESS_AUDIO2_CTRL3_DRQD;
                    583:                break;
                    584: #ifdef DIAGNOSTIC
                    585:        default:
                    586:                printf("ess_config_drq: configured dma chan %d not supported for Audio 2\n",
                    587:                       sc->sc_audio2.drq);
                    588:                return;
                    589: #endif
                    590:        }
                    591:        ess_write_mix_reg(sc, ESS_MREG_AUDIO2_CTRL3, v);
                    592:        /* Enable DMA 2 */
                    593:        ess_set_mreg_bits(sc, ESS_MREG_AUDIO2_CTRL2,
                    594:                          ESS_AUDIO2_CTRL2_DMA_ENABLE);
                    595: }
                    596:
                    597: /*
                    598:  * Set up registers after a reset.
                    599:  */
                    600: void
                    601: ess_setup(sc)
                    602:        struct ess_softc *sc;
                    603: {
                    604:
                    605:        ess_config_irq(sc);
                    606:        ess_config_drq(sc);
                    607:
                    608:        DPRINTFN(2,("ess_setup: done\n"));
                    609: }
                    610:
                    611: /*
                    612:  * Determine the model of ESS chip we are talking to.  Currently we
                    613:  * only support ES1888, ES1887 and ES888.  The method of determining
                    614:  * the chip is based on the information on page 27 of the ES1887 data
                    615:  * sheet.
                    616:  *
                    617:  * This routine sets the values of sc->sc_model and sc->sc_version.
                    618:  */
                    619: int
                    620: ess_identify(sc)
                    621:        struct ess_softc *sc;
                    622: {
                    623:        u_char reg1;
                    624:        u_char reg2;
                    625:        u_char reg3;
                    626:        u_int8_t ident[4];
                    627:
                    628:        sc->sc_model = ESS_UNSUPPORTED;
                    629:        sc->sc_version = 0;
                    630:
                    631:        memset(ident, 0, sizeof(ident));
                    632:
                    633:        /*
                    634:         * 1. Check legacy ID bytes.  These should be 0x68 0x8n, where
                    635:         *    n >= 8 for an ES1887 or an ES888.  Other values indicate
                    636:         *    earlier (unsupported) chips.
                    637:         */
                    638:        ess_wdsp(sc, ESS_ACMD_LEGACY_ID);
                    639:
                    640:        if ((reg1 = ess_rdsp(sc)) != 0x68) {
                    641:                printf("ess: First ID byte wrong (0x%02x)\n", reg1);
                    642:                return 1;
                    643:        }
                    644:
                    645:        reg2 = ess_rdsp(sc);
                    646:        if (((reg2 & 0xf0) != 0x80) ||
                    647:            ((reg2 & 0x0f) < 8)) {
                    648:                printf("ess: Second ID byte wrong (0x%02x)\n", reg2);
                    649:                return 1;
                    650:        }
                    651:
                    652:        /*
                    653:         * Store the ID bytes as the version.
                    654:         */
                    655:        sc->sc_version = (reg1 << 8) + reg2;
                    656:
                    657:
                    658:        /*
                    659:         * 2. Verify we can change bit 2 in mixer register 0x64.  This
                    660:         *    should be possible on all supported chips.
                    661:         */
                    662:        reg1 = ess_read_mix_reg(sc, ESS_MREG_VOLUME_CTRL);
                    663:        reg2 = reg1 ^ 0x04;  /* toggle bit 2 */
                    664:
                    665:        ess_write_mix_reg(sc, ESS_MREG_VOLUME_CTRL, reg2);
                    666:
                    667:        if (ess_read_mix_reg(sc, ESS_MREG_VOLUME_CTRL) != reg2) {
                    668:                printf("ess: Hardware error (unable to toggle bit 2 of mixer register 0x64)\n");
                    669:                return 1;
                    670:        }
                    671:
                    672:        /*
                    673:         * Restore the original value of mixer register 0x64.
                    674:         */
                    675:        ess_write_mix_reg(sc, ESS_MREG_VOLUME_CTRL, reg1);
                    676:
                    677:
                    678:        /*
                    679:         * 3. Verify we can change the value of mixer register
                    680:         *    ESS_MREG_SAMPLE_RATE.
                    681:         *    This is possible on the 1888/1887/888, but not on the 1788.
                    682:         *    It is not necessary to restore the value of this mixer register.
                    683:         */
                    684:        reg1 = ess_read_mix_reg(sc, ESS_MREG_SAMPLE_RATE);
                    685:        reg2 = reg1 ^ 0xff;  /* toggle all bits */
                    686:
                    687:        ess_write_mix_reg(sc, ESS_MREG_SAMPLE_RATE, reg2);
                    688:
                    689:        if (ess_read_mix_reg(sc, ESS_MREG_SAMPLE_RATE) != reg2) {
                    690:                /* If we got this far before failing, it's a 1788. */
                    691:                sc->sc_model = ESS_1788;
                    692:
                    693:                /*
                    694:                 * Identify ESS model for ES18[67]8.
                    695:                 */
                    696:                ess_read_multi_mix_reg(sc, 0x40, ident, sizeof(ident));
                    697:                if(ident[0] == 0x18) {
                    698:                        switch(ident[1]) {
                    699:                        case 0x68:
                    700:                                sc->sc_model = ESS_1868;
                    701:                                break;
                    702:                        case 0x78:
                    703:                                sc->sc_model = ESS_1878;
                    704:                                break;
                    705:                        }
                    706:                }
                    707:        } else {
                    708:                /*
                    709:                 * 4. Determine if we can change bit 5 in mixer register 0x64.
                    710:                 *    This determines whether we have an ES1887:
                    711:                 *
                    712:                 *    - can change indicates ES1887
                    713:                 *    - can't change indicates ES1888 or ES888
                    714:                 */
                    715:                reg1 = ess_read_mix_reg(sc, ESS_MREG_VOLUME_CTRL);
                    716:                reg2 = reg1 ^ 0x20;  /* toggle bit 5 */
                    717:
                    718:                ess_write_mix_reg(sc, ESS_MREG_VOLUME_CTRL, reg2);
                    719:
                    720:                if (ess_read_mix_reg(sc, ESS_MREG_VOLUME_CTRL) == reg2) {
                    721:                        sc->sc_model = ESS_1887;
                    722:
                    723:                        /*
                    724:                         * Restore the original value of mixer register 0x64.
                    725:                         */
                    726:                        ess_write_mix_reg(sc, ESS_MREG_VOLUME_CTRL, reg1);
                    727:
                    728:                        /*
                    729:                         * Identify ESS model for ES18[67]9.
                    730:                         */
                    731:                        ess_read_multi_mix_reg(sc, 0x40, ident, sizeof(ident));
                    732:                        if(ident[0] == 0x18) {
                    733:                                switch(ident[1]) {
                    734:                                case 0x69:
                    735:                                        sc->sc_model = ESS_1869;
                    736:                                        break;
                    737:                                case 0x79:
                    738:                                        sc->sc_model = ESS_1879;
                    739:                                        break;
                    740:                                }
                    741:                        }
                    742:                } else {
                    743:                        /*
                    744:                         * 5. Determine if we can change the value of mixer
                    745:                         *    register 0x69 independently of mixer register
                    746:                         *    0x68. This determines which chip we have:
                    747:                         *
                    748:                         *    - can modify idependently indicates ES888
                    749:                         *    - register 0x69 is an alias of 0x68 indicates ES1888
                    750:                         */
                    751:                        reg1 = ess_read_mix_reg(sc, 0x68);
                    752:                        reg2 = ess_read_mix_reg(sc, 0x69);
                    753:                        reg3 = reg2 ^ 0xff;  /* toggle all bits */
                    754:
                    755:                        /*
                    756:                         * Write different values to each register.
                    757:                         */
                    758:                        ess_write_mix_reg(sc, 0x68, reg2);
                    759:                        ess_write_mix_reg(sc, 0x69, reg3);
                    760:
                    761:                        if (ess_read_mix_reg(sc, 0x68) == reg2 &&
                    762:                            ess_read_mix_reg(sc, 0x69) == reg3)
                    763:                                sc->sc_model = ESS_888;
                    764:                        else
                    765:                                sc->sc_model = ESS_1888;
                    766:
                    767:                        /*
                    768:                         * Restore the original value of the registers.
                    769:                         */
                    770:                        ess_write_mix_reg(sc, 0x68, reg1);
                    771:                        ess_write_mix_reg(sc, 0x69, reg2);
                    772:                }
                    773:        }
                    774:
                    775:        return 0;
                    776: }
                    777:
                    778:
                    779: int
                    780: ess_setup_sc(sc, doinit)
                    781:        struct ess_softc *sc;
                    782:        int doinit;
                    783: {
                    784:        /* Reset the chip. */
                    785:        if (ess_reset(sc) != 0) {
                    786:                DPRINTF(("ess_setup_sc: couldn't reset chip\n"));
                    787:                return (1);
                    788:        }
                    789:
                    790:        /* Identify the ESS chip, and check that it is supported. */
                    791:        if (ess_identify(sc)) {
                    792:                DPRINTF(("ess_setup_sc: couldn't identify\n"));
                    793:                return (1);
                    794:        }
                    795:
                    796:        return (0);
                    797: }
                    798:
                    799: /*
                    800:  * Probe for the ESS hardware.
                    801:  */
                    802: int
                    803: essmatch(sc)
                    804:        struct ess_softc *sc;
                    805: {
                    806:        if (!ESS_BASE_VALID(sc->sc_iobase)) {
                    807:                printf("ess: configured iobase 0x%x invalid\n", sc->sc_iobase);
                    808:                return (0);
                    809:        }
                    810:
                    811:        /* Configure the ESS chip for the desired audio base address. */
                    812:        if (ess_config_addr(sc))
                    813:                return (0);
                    814:
                    815:        if (ess_setup_sc(sc, 1))
                    816:                return (0);
                    817:
                    818:        if (sc->sc_model == ESS_UNSUPPORTED) {
                    819:                DPRINTF(("ess: Unsupported model\n"));
                    820:                return (0);
                    821:        }
                    822:
                    823:        /* Check that requested DMA channels are valid and different. */
                    824:        if (!ESS_DRQ1_VALID(sc->sc_audio1.drq)) {
                    825:                printf("ess: record drq %d invalid\n", sc->sc_audio1.drq);
                    826:                return (0);
                    827:        }
                    828:        if (!isa_drq_isfree(sc->sc_isa, sc->sc_audio1.drq))
                    829:                return (0);
                    830:        if (!ESS_USE_AUDIO1(sc->sc_model)) {
                    831:                if (!ESS_DRQ2_VALID(sc->sc_audio2.drq)) {
                    832:                        printf("ess: play drq %d invalid\n", sc->sc_audio2.drq);
                    833:                        return (0);
                    834:                }
                    835:                if (sc->sc_audio1.drq == sc->sc_audio2.drq) {
                    836:                        printf("ess: play and record drq both %d\n",
                    837:                               sc->sc_audio1.drq);
                    838:                        return (0);
                    839:                }
                    840:                if (!isa_drq_isfree(sc->sc_isa, sc->sc_audio2.drq))
                    841:                        return (0);
                    842:        }
                    843:
                    844:        /*
                    845:         * The 1887 has an additional IRQ mode where both channels are mapped
                    846:         * to the same IRQ.
                    847:         */
                    848:        if (sc->sc_model == ESS_1887 &&
                    849:            sc->sc_audio1.irq == sc->sc_audio2.irq &&
                    850:            sc->sc_audio1.irq != -1 &&
                    851:            ESS_IRQ12_VALID(sc->sc_audio1.irq))
                    852:                goto irq_not1888;
                    853:
                    854:        /* Check that requested IRQ lines are valid and different. */
                    855:        if (sc->sc_audio1.irq != -1 &&
                    856:            !ESS_IRQ1_VALID(sc->sc_audio1.irq)) {
                    857:                printf("ess: record irq %d invalid\n", sc->sc_audio1.irq);
                    858:                return (0);
                    859:        }
                    860:        if (!ESS_USE_AUDIO1(sc->sc_model)) {
                    861:                if (sc->sc_audio2.irq != -1 &&
                    862:                    !ESS_IRQ2_VALID(sc->sc_audio2.irq)) {
                    863:                        printf("ess: play irq %d invalid\n", sc->sc_audio2.irq);
                    864:                        return (0);
                    865:                }
                    866:                if (sc->sc_audio1.irq == sc->sc_audio2.irq &&
                    867:                    sc->sc_audio1.irq != -1) {
                    868:                        printf("ess: play and record irq both %d\n",
                    869:                               sc->sc_audio1.irq);
                    870:                        return (0);
                    871:                }
                    872:        }
                    873:
                    874: irq_not1888:
                    875:        /* XXX should we check IRQs as well? */
                    876:
                    877:        return (1);
                    878: }
                    879:
                    880:
                    881: /*
                    882:  * Attach hardware to driver, attach hardware driver to audio
                    883:  * pseudo-device driver.
                    884:  */
                    885: void
                    886: essattach(sc)
                    887:        struct ess_softc *sc;
                    888: {
                    889:        struct audio_attach_args arg;
                    890:        struct audio_params pparams, rparams;
                    891:        int i;
                    892:        u_int v;
                    893:
                    894:        if (ess_setup_sc(sc, 0)) {
                    895:                printf(": setup failed\n");
                    896:                return;
                    897:        }
                    898:
                    899:        printf(": ESS Technology ES%s [version 0x%04x]\n",
                    900:               essmodel[sc->sc_model], sc->sc_version);
                    901:
                    902:        sc->sc_audio1.polled = sc->sc_audio1.irq == -1;
                    903:        if (!sc->sc_audio1.polled) {
                    904:                sc->sc_audio1.ih = isa_intr_establish(sc->sc_ic,
                    905:                    sc->sc_audio1.irq, sc->sc_audio1.ist, IPL_AUDIO,
                    906:                    ess_audio1_intr, sc, sc->sc_dev.dv_xname);
                    907:                printf("%s: audio1 interrupting at irq %d\n",
                    908:                    sc->sc_dev.dv_xname, sc->sc_audio1.irq);
                    909:        } else
                    910:                printf("%s: audio1 polled\n", sc->sc_dev.dv_xname);
                    911:        if (isa_dmamap_create(sc->sc_isa, sc->sc_audio1.drq,
                    912:            MAX_ISADMA, BUS_DMA_NOWAIT|BUS_DMA_ALLOCNOW)) {
                    913:                printf("%s: can't create map for drq %d\n",
                    914:                       sc->sc_dev.dv_xname, sc->sc_audio1.drq);
                    915:                return;
                    916:        }
                    917:
                    918:        if (!ESS_USE_AUDIO1(sc->sc_model)) {
                    919:                sc->sc_audio2.polled = sc->sc_audio2.irq == -1;
                    920:                if (!sc->sc_audio2.polled) {
                    921:                        sc->sc_audio2.ih = isa_intr_establish(sc->sc_ic,
                    922:                            sc->sc_audio2.irq, sc->sc_audio2.ist, IPL_AUDIO,
                    923:                            ess_audio2_intr, sc, sc->sc_dev.dv_xname);
                    924:                        printf("%s: audio2 interrupting at irq %d\n",
                    925:                            sc->sc_dev.dv_xname, sc->sc_audio2.irq);
                    926:                } else
                    927:                        printf("%s: audio2 polled\n", sc->sc_dev.dv_xname);
                    928:                if (isa_dmamap_create(sc->sc_isa, sc->sc_audio2.drq,
                    929:                    MAX_ISADMA, BUS_DMA_NOWAIT|BUS_DMA_ALLOCNOW)) {
                    930:                        printf("%s: can't create map for drq %d\n",
                    931:                               sc->sc_dev.dv_xname, sc->sc_audio2.drq);
                    932:                        return;
                    933:                }
                    934:        }
                    935:
                    936:        timeout_set(&sc->sc_tmo1, ess_audio1_poll, sc);
                    937:        timeout_set(&sc->sc_tmo2, ess_audio2_poll, sc);
                    938:
                    939:        /*
                    940:         * Set record and play parameters to default values defined in
                    941:         * generic audio driver.
                    942:         */
                    943:        pparams = audio_default;
                    944:        rparams = audio_default;
                    945:        ess_set_params(sc, AUMODE_RECORD|AUMODE_PLAY, 0, &pparams, &rparams);
                    946:
                    947:        /* Do a hardware reset on the mixer. */
                    948:        ess_write_mix_reg(sc, ESS_MIX_RESET, ESS_MIX_RESET);
                    949:
                    950:        /*
                    951:         * Set volume of Audio 1 to zero and disable Audio 1 DAC input
                    952:         * to playback mixer, since playback is always through Audio 2.
                    953:         */
                    954:        if (!ESS_USE_AUDIO1(sc->sc_model))
                    955:                ess_write_mix_reg(sc, ESS_MREG_VOLUME_VOICE, 0);
                    956:        ess_wdsp(sc, ESS_ACMD_DISABLE_SPKR);
                    957:
                    958:        if (ESS_USE_AUDIO1(sc->sc_model)) {
                    959:                ess_write_mix_reg(sc, ESS_MREG_ADC_SOURCE, ESS_SOURCE_MIC);
                    960:                sc->in_port = ESS_SOURCE_MIC;
                    961:                sc->ndevs = ESS_1788_NDEVS;
                    962:        } else {
                    963:                /*
                    964:                 * Set hardware record source to use output of the record
                    965:                 * mixer. We do the selection of record source in software by
                    966:                 * setting the gain of the unused sources to zero. (See
                    967:                 * ess_set_in_ports.)
                    968:                 */
                    969:                ess_write_mix_reg(sc, ESS_MREG_ADC_SOURCE, ESS_SOURCE_MIXER);
                    970:                sc->in_mask = 1 << ESS_MIC_REC_VOL;
                    971:                sc->ndevs = ESS_1888_NDEVS;
                    972:                ess_clear_mreg_bits(sc, ESS_MREG_AUDIO2_CTRL2, 0x10);
                    973:                ess_set_mreg_bits(sc, ESS_MREG_AUDIO2_CTRL2, 0x08);
                    974:        }
                    975:
                    976:        /*
                    977:         * Set gain on each mixer device to a sensible value.
                    978:         * Devices not normally used are turned off, and other devices
                    979:         * are set to 50% volume.
                    980:         */
                    981:        for (i = 0; i < sc->ndevs; i++) {
                    982:                switch (i) {
                    983:                case ESS_MIC_PLAY_VOL:
                    984:                case ESS_LINE_PLAY_VOL:
                    985:                case ESS_CD_PLAY_VOL:
                    986:                case ESS_AUXB_PLAY_VOL:
                    987:                case ESS_DAC_REC_VOL:
                    988:                case ESS_LINE_REC_VOL:
                    989:                case ESS_SYNTH_REC_VOL:
                    990:                case ESS_CD_REC_VOL:
                    991:                case ESS_AUXB_REC_VOL:
                    992:                        v = 0;
                    993:                        break;
                    994:                default:
                    995:                        v = ESS_4BIT_GAIN(AUDIO_MAX_GAIN / 2);
                    996:                        break;
                    997:                }
                    998:                sc->gain[i][ESS_LEFT] = sc->gain[i][ESS_RIGHT] = v;
                    999:                ess_set_gain(sc, i, 1);
                   1000:        }
                   1001:
                   1002:        ess_setup(sc);
                   1003:
                   1004:        /* Disable the speaker until the device is opened.  */
                   1005:        ess_speaker_off(sc);
                   1006:        sc->spkr_state = SPKR_OFF;
                   1007:
                   1008:        snprintf(ess_device.name, sizeof ess_device.name, "ES%s",
                   1009:            essmodel[sc->sc_model]);
                   1010:        snprintf(ess_device.version, sizeof ess_device.version, "0x%04x",
                   1011:            sc->sc_version);
                   1012:
                   1013:        if (ESS_USE_AUDIO1(sc->sc_model))
                   1014:                audio_attach_mi(&ess_1788_hw_if, sc, &sc->sc_dev);
                   1015:        else
                   1016:                audio_attach_mi(&ess_1888_hw_if, sc, &sc->sc_dev);
                   1017:
                   1018:        arg.type = AUDIODEV_TYPE_OPL;
                   1019:        arg.hwif = 0;
                   1020:        arg.hdl = 0;
                   1021:        (void)config_found(&sc->sc_dev, &arg, audioprint);
                   1022:
                   1023: #ifdef AUDIO_DEBUG
                   1024:        if (essdebug > 0)
                   1025:                ess_printsc(sc);
                   1026: #endif
                   1027: }
                   1028:
                   1029: /*
                   1030:  * Various routines to interface to higher level audio driver
                   1031:  */
                   1032:
                   1033: int
                   1034: ess_open(addr, flags)
                   1035:        void *addr;
                   1036:        int flags;
                   1037: {
                   1038:        struct ess_softc *sc = addr;
                   1039:
                   1040:        DPRINTF(("ess_open: sc=%p\n", sc));
                   1041:
                   1042:        if (sc->sc_open != 0 || ess_reset(sc) != 0)
                   1043:                return ENXIO;
                   1044:
                   1045:        ess_setup(sc);          /* because we did a reset */
                   1046:
                   1047:        sc->sc_open = 1;
                   1048:
                   1049:        DPRINTF(("ess_open: opened\n"));
                   1050:
                   1051:        return (0);
                   1052: }
                   1053:
                   1054: void
                   1055: ess_1788_close(addr)
                   1056:        void *addr;
                   1057: {
                   1058:        struct ess_softc *sc = addr;
                   1059:
                   1060:        DPRINTF(("ess_1788_close: sc=%p\n", sc));
                   1061:
                   1062:        ess_speaker_off(sc);
                   1063:        sc->spkr_state = SPKR_OFF;
                   1064:
                   1065:        ess_audio1_halt(sc);
                   1066:
                   1067:        sc->sc_open = 0;
                   1068:        DPRINTF(("ess_1788_close: closed\n"));
                   1069: }
                   1070:
                   1071: void
                   1072: ess_1888_close(addr)
                   1073:        void *addr;
                   1074: {
                   1075:        struct ess_softc *sc = addr;
                   1076:
                   1077:        DPRINTF(("ess_1888_close: sc=%p\n", sc));
                   1078:
                   1079:        ess_speaker_off(sc);
                   1080:        sc->spkr_state = SPKR_OFF;
                   1081:
                   1082:        ess_audio1_halt(sc);
                   1083:        ess_audio2_halt(sc);
                   1084:
                   1085:        sc->sc_open = 0;
                   1086:        DPRINTF(("ess_1888_close: closed\n"));
                   1087: }
                   1088:
                   1089: /*
                   1090:  * Wait for FIFO to drain, and analog section to settle.
                   1091:  * XXX should check FIFO empty bit.
                   1092:  */
                   1093: int
                   1094: ess_drain(addr)
                   1095:        void *addr;
                   1096: {
                   1097:        tsleep(addr, PWAIT | PCATCH, "essdr", hz/20); /* XXX */
                   1098:        return (0);
                   1099: }
                   1100:
                   1101: /* XXX should use reference count */
                   1102: int
                   1103: ess_speaker_ctl(addr, newstate)
                   1104:        void *addr;
                   1105:        int newstate;
                   1106: {
                   1107:        struct ess_softc *sc = addr;
                   1108:
                   1109:        if ((newstate == SPKR_ON) && (sc->spkr_state == SPKR_OFF)) {
                   1110:                ess_speaker_on(sc);
                   1111:                sc->spkr_state = SPKR_ON;
                   1112:        }
                   1113:        if ((newstate == SPKR_OFF) && (sc->spkr_state == SPKR_ON)) {
                   1114:                ess_speaker_off(sc);
                   1115:                sc->spkr_state = SPKR_OFF;
                   1116:        }
                   1117:        return (0);
                   1118: }
                   1119:
                   1120: int
                   1121: ess_getdev(addr, retp)
                   1122:        void *addr;
                   1123:        struct audio_device *retp;
                   1124: {
                   1125:        *retp = ess_device;
                   1126:        return (0);
                   1127: }
                   1128:
                   1129: int
                   1130: ess_query_encoding(addr, fp)
                   1131:        void *addr;
                   1132:        struct audio_encoding *fp;
                   1133: {
                   1134:        /*struct ess_softc *sc = addr;*/
                   1135:
                   1136:        switch (fp->index) {
                   1137:        case 0:
                   1138:                strlcpy(fp->name, AudioEulinear, sizeof fp->name);
                   1139:                fp->encoding = AUDIO_ENCODING_ULINEAR;
                   1140:                fp->precision = 8;
                   1141:                fp->flags = 0;
                   1142:                return (0);
                   1143:        case 1:
                   1144:                strlcpy(fp->name, AudioEmulaw, sizeof fp->name);
                   1145:                fp->encoding = AUDIO_ENCODING_ULAW;
                   1146:                fp->precision = 8;
                   1147:                fp->flags = AUDIO_ENCODINGFLAG_EMULATED;
                   1148:                return (0);
                   1149:        case 2:
                   1150:                strlcpy(fp->name, AudioEalaw, sizeof fp->name);
                   1151:                fp->encoding = AUDIO_ENCODING_ALAW;
                   1152:                fp->precision = 8;
                   1153:                fp->flags = AUDIO_ENCODINGFLAG_EMULATED;
                   1154:                return (0);
                   1155:        case 3:
                   1156:                strlcpy(fp->name, AudioEslinear, sizeof fp->name);
                   1157:                fp->encoding = AUDIO_ENCODING_SLINEAR;
                   1158:                fp->precision = 8;
                   1159:                fp->flags = 0;
                   1160:                return (0);
                   1161:        case 4:
                   1162:                strlcpy(fp->name, AudioEslinear_le, sizeof fp->name);
                   1163:                fp->encoding = AUDIO_ENCODING_SLINEAR_LE;
                   1164:                fp->precision = 16;
                   1165:                fp->flags = 0;
                   1166:                return (0);
                   1167:        case 5:
                   1168:                strlcpy(fp->name, AudioEulinear_le, sizeof fp->name);
                   1169:                fp->encoding = AUDIO_ENCODING_ULINEAR_LE;
                   1170:                fp->precision = 16;
                   1171:                fp->flags = 0;
                   1172:                return (0);
                   1173:        case 6:
                   1174:                strlcpy(fp->name, AudioEslinear_be, sizeof fp->name);
                   1175:                fp->encoding = AUDIO_ENCODING_SLINEAR_BE;
                   1176:                fp->precision = 16;
                   1177:                fp->flags = AUDIO_ENCODINGFLAG_EMULATED;
                   1178:                return (0);
                   1179:        case 7:
                   1180:                strlcpy(fp->name, AudioEulinear_be, sizeof fp->name);
                   1181:                fp->encoding = AUDIO_ENCODING_ULINEAR_BE;
                   1182:                fp->precision = 16;
                   1183:                fp->flags = AUDIO_ENCODINGFLAG_EMULATED;
                   1184:                return (0);
                   1185:        default:
                   1186:                return EINVAL;
                   1187:        }
                   1188:        return (0);
                   1189: }
                   1190:
                   1191: int
                   1192: ess_set_params(addr, setmode, usemode, play, rec)
                   1193:        void *addr;
                   1194:        int setmode, usemode;
                   1195:        struct audio_params *play, *rec;
                   1196: {
                   1197:        struct ess_softc *sc = addr;
                   1198:        struct audio_params *p;
                   1199:        int mode;
                   1200:        int rate;
                   1201:
                   1202:        DPRINTF(("ess_set_params: set=%d use=%d\n", setmode, usemode));
                   1203:
                   1204:        /*
                   1205:         * The ES1887 manual (page 39, `Full-Duplex DMA Mode') claims that in
                   1206:         * full-duplex operation the sample rates must be the same for both
                   1207:         * channels.  This appears to be false; the only bit in common is the
                   1208:         * clock source selection.  However, we'll be conservative here.
                   1209:         * - mycroft
                   1210:         */
                   1211:        if (play->sample_rate != rec->sample_rate &&
                   1212:            usemode == (AUMODE_PLAY | AUMODE_RECORD)) {
                   1213:                if (setmode == AUMODE_PLAY) {
                   1214:                        rec->sample_rate = play->sample_rate;
                   1215:                        setmode |= AUMODE_RECORD;
                   1216:                } else if (setmode == AUMODE_RECORD) {
                   1217:                        play->sample_rate = rec->sample_rate;
                   1218:                        setmode |= AUMODE_PLAY;
                   1219:                } else
                   1220:                        return (EINVAL);
                   1221:        }
                   1222:
                   1223:        for (mode = AUMODE_RECORD; mode != -1;
                   1224:             mode = mode == AUMODE_RECORD ? AUMODE_PLAY : -1) {
                   1225:                if ((setmode & mode) == 0)
                   1226:                        continue;
                   1227:
                   1228:                p = mode == AUMODE_PLAY ? play : rec;
                   1229:
                   1230:                if (p->sample_rate < ESS_MINRATE ||
                   1231:                    p->sample_rate > ESS_MAXRATE ||
                   1232:                    (p->precision != 8 && p->precision != 16) ||
                   1233:                    (p->channels != 1 && p->channels != 2))
                   1234:                        return (EINVAL);
                   1235:
                   1236:                p->factor = 1;
                   1237:                p->sw_code = 0;
                   1238:                switch (p->encoding) {
                   1239:                case AUDIO_ENCODING_SLINEAR_BE:
                   1240:                case AUDIO_ENCODING_ULINEAR_BE:
                   1241:                        if (p->precision == 16)
                   1242:                                p->sw_code = swap_bytes;
                   1243:                        break;
                   1244:                case AUDIO_ENCODING_SLINEAR_LE:
                   1245:                case AUDIO_ENCODING_ULINEAR_LE:
                   1246:                        break;
                   1247:                case AUDIO_ENCODING_ULAW:
                   1248:                        if (mode == AUMODE_PLAY) {
                   1249:                                p->factor = 2;
                   1250:                                p->sw_code = mulaw_to_ulinear16;
                   1251:                        } else
                   1252:                                p->sw_code = ulinear8_to_mulaw;
                   1253:                        break;
                   1254:                case AUDIO_ENCODING_ALAW:
                   1255:                        if (mode == AUMODE_PLAY) {
                   1256:                                p->factor = 2;
                   1257:                                p->sw_code = alaw_to_ulinear16;
                   1258:                        } else
                   1259:                                p->sw_code = ulinear8_to_alaw;
                   1260:                        break;
                   1261:                default:
                   1262:                        return (EINVAL);
                   1263:                }
                   1264:        }
                   1265:
                   1266:        if (usemode == AUMODE_RECORD)
                   1267:                rate = rec->sample_rate;
                   1268:        else
                   1269:                rate = play->sample_rate;
                   1270:
                   1271:        ess_write_x_reg(sc, ESS_XCMD_SAMPLE_RATE, ess_srtotc(rate));
                   1272:        ess_write_x_reg(sc, ESS_XCMD_FILTER_CLOCK, ess_srtofc(rate));
                   1273:
                   1274:        if (!ESS_USE_AUDIO1(sc->sc_model)) {
                   1275:                ess_write_mix_reg(sc, ESS_MREG_SAMPLE_RATE, ess_srtotc(rate));
                   1276:                ess_write_mix_reg(sc, ESS_MREG_FILTER_CLOCK, ess_srtofc(rate));
                   1277:        }
                   1278:
                   1279:        return (0);
                   1280: }
                   1281:
                   1282: int
                   1283: ess_audio1_trigger_output(addr, start, end, blksize, intr, arg, param)
                   1284:        void *addr;
                   1285:        void *start, *end;
                   1286:        int blksize;
                   1287:        void (*intr)(void *);
                   1288:        void *arg;
                   1289:        struct audio_params *param;
                   1290: {
                   1291:        struct ess_softc *sc = addr;
                   1292:        u_int8_t reg;
                   1293:
                   1294:        DPRINTFN(1, ("ess_audio1_trigger_output: sc=%p start=%p end=%p blksize=%d intr=%p(%p)\n",
                   1295:            addr, start, end, blksize, intr, arg));
                   1296:
                   1297:        if (sc->sc_audio1.active)
                   1298:                panic("ess_audio1_trigger_output: already running");
                   1299:
                   1300:        sc->sc_audio1.active = 1;
                   1301:        sc->sc_audio1.intr = intr;
                   1302:        sc->sc_audio1.arg = arg;
                   1303:        if (sc->sc_audio1.polled) {
                   1304:                sc->sc_audio1.dmapos = 0;
                   1305:                sc->sc_audio1.buffersize = (char *)end - (char *)start;
                   1306:                sc->sc_audio1.dmacount = 0;
                   1307:                sc->sc_audio1.blksize = blksize;
                   1308:                timeout_add(&sc->sc_tmo1, hz/30);
                   1309:        }
                   1310:
                   1311:        reg = ess_read_x_reg(sc, ESS_XCMD_AUDIO_CTRL);
                   1312:        if (param->channels == 2) {
                   1313:                reg &= ~ESS_AUDIO_CTRL_MONO;
                   1314:                reg |= ESS_AUDIO_CTRL_STEREO;
                   1315:        } else {
                   1316:                reg |= ESS_AUDIO_CTRL_MONO;
                   1317:                reg &= ~ESS_AUDIO_CTRL_STEREO;
                   1318:        }
                   1319:        ess_write_x_reg(sc, ESS_XCMD_AUDIO_CTRL, reg);
                   1320:
                   1321:        reg = ess_read_x_reg(sc, ESS_XCMD_AUDIO1_CTRL1);
                   1322:        if (param->precision * param->factor == 16)
                   1323:                reg |= ESS_AUDIO1_CTRL1_FIFO_SIZE;
                   1324:        else
                   1325:                reg &= ~ESS_AUDIO1_CTRL1_FIFO_SIZE;
                   1326:        if (param->channels == 2)
                   1327:                reg |= ESS_AUDIO1_CTRL1_FIFO_STEREO;
                   1328:        else
                   1329:                reg &= ~ESS_AUDIO1_CTRL1_FIFO_STEREO;
                   1330:        if (param->encoding == AUDIO_ENCODING_SLINEAR_BE ||
                   1331:            param->encoding == AUDIO_ENCODING_SLINEAR_LE)
                   1332:                reg |= ESS_AUDIO1_CTRL1_FIFO_SIGNED;
                   1333:        else
                   1334:                reg &= ~ESS_AUDIO1_CTRL1_FIFO_SIGNED;
                   1335:        reg |= ESS_AUDIO1_CTRL1_FIFO_CONNECT;
                   1336:        ess_write_x_reg(sc, ESS_XCMD_AUDIO1_CTRL1, reg);
                   1337:
                   1338:        isa_dmastart(sc->sc_isa, sc->sc_audio1.drq, start,
                   1339:                     (char *)end - (char *)start, NULL,
                   1340:            DMAMODE_WRITE | DMAMODE_LOOP, BUS_DMA_NOWAIT);
                   1341:
                   1342:        /* Program transfer count registers with 2's complement of count. */
                   1343:        blksize = -blksize;
                   1344:        ess_write_x_reg(sc, ESS_XCMD_XFER_COUNTLO, blksize);
                   1345:        ess_write_x_reg(sc, ESS_XCMD_XFER_COUNTHI, blksize >> 8);
                   1346:
                   1347:        /* Use 4 bytes per output DMA. */
                   1348:        ess_set_xreg_bits(sc, ESS_XCMD_DEMAND_CTRL, ESS_DEMAND_CTRL_DEMAND_4);
                   1349:
                   1350:        /* Start auto-init DMA */
                   1351:        ess_wdsp(sc, ESS_ACMD_ENABLE_SPKR);
                   1352:        reg = ess_read_x_reg(sc, ESS_XCMD_AUDIO1_CTRL2);
                   1353:        reg &= ~(ESS_AUDIO1_CTRL2_DMA_READ | ESS_AUDIO1_CTRL2_ADC_ENABLE);
                   1354:        reg |= ESS_AUDIO1_CTRL2_FIFO_ENABLE | ESS_AUDIO1_CTRL2_AUTO_INIT;
                   1355:        ess_write_x_reg(sc, ESS_XCMD_AUDIO1_CTRL2, reg);
                   1356:
                   1357:        return (0);
                   1358: }
                   1359:
                   1360: int
                   1361: ess_audio2_trigger_output(addr, start, end, blksize, intr, arg, param)
                   1362:        void *addr;
                   1363:        void *start, *end;
                   1364:        int blksize;
                   1365:        void (*intr)(void *);
                   1366:        void *arg;
                   1367:        struct audio_params *param;
                   1368: {
                   1369:        struct ess_softc *sc = addr;
                   1370:        u_int8_t reg;
                   1371:
                   1372:        DPRINTFN(1, ("ess_audio2_trigger_output: sc=%p start=%p end=%p blksize=%d intr=%p(%p)\n",
                   1373:            addr, start, end, blksize, intr, arg));
                   1374:
                   1375:        if (sc->sc_audio2.active)
                   1376:                panic("ess_audio2_trigger_output: already running");
                   1377:
                   1378:        sc->sc_audio2.active = 1;
                   1379:        sc->sc_audio2.intr = intr;
                   1380:        sc->sc_audio2.arg = arg;
                   1381:        if (sc->sc_audio2.polled) {
                   1382:                sc->sc_audio2.dmapos = 0;
                   1383:                sc->sc_audio2.buffersize = (char *)end - (char *)start;
                   1384:                sc->sc_audio2.dmacount = 0;
                   1385:                sc->sc_audio2.blksize = blksize;
                   1386:                timeout_add(&sc->sc_tmo2, hz/30);
                   1387:        }
                   1388:
                   1389:        reg = ess_read_mix_reg(sc, ESS_MREG_AUDIO2_CTRL2);
                   1390:        if (param->precision * param->factor == 16)
                   1391:                reg |= ESS_AUDIO2_CTRL2_FIFO_SIZE;
                   1392:        else
                   1393:                reg &= ~ESS_AUDIO2_CTRL2_FIFO_SIZE;
                   1394:        if (param->channels == 2)
                   1395:                reg |= ESS_AUDIO2_CTRL2_CHANNELS;
                   1396:        else
                   1397:                reg &= ~ESS_AUDIO2_CTRL2_CHANNELS;
                   1398:        if (param->encoding == AUDIO_ENCODING_SLINEAR_BE ||
                   1399:            param->encoding == AUDIO_ENCODING_SLINEAR_LE)
                   1400:                reg |= ESS_AUDIO2_CTRL2_FIFO_SIGNED;
                   1401:        else
                   1402:                reg &= ~ESS_AUDIO2_CTRL2_FIFO_SIGNED;
                   1403:        ess_write_mix_reg(sc, ESS_MREG_AUDIO2_CTRL2, reg);
                   1404:
                   1405:        isa_dmastart(sc->sc_isa, sc->sc_audio2.drq, start,
                   1406:                     (char *)end - (char *)start, NULL,
                   1407:            DMAMODE_WRITE | DMAMODE_LOOP, BUS_DMA_NOWAIT);
                   1408:
                   1409:        if (IS16BITDRQ(sc->sc_audio2.drq))
                   1410:                blksize >>= 1;  /* use word count for 16 bit DMA */
                   1411:        /* Program transfer count registers with 2's complement of count. */
                   1412:        blksize = -blksize;
                   1413:        ess_write_mix_reg(sc, ESS_MREG_XFER_COUNTLO, blksize);
                   1414:        ess_write_mix_reg(sc, ESS_MREG_XFER_COUNTHI, blksize >> 8);
                   1415:
                   1416:        reg = ess_read_mix_reg(sc, ESS_MREG_AUDIO2_CTRL1);
                   1417:        if (IS16BITDRQ(sc->sc_audio2.drq))
                   1418:                reg |= ESS_AUDIO2_CTRL1_XFER_SIZE;
                   1419:        else
                   1420:                reg &= ~ESS_AUDIO2_CTRL1_XFER_SIZE;
                   1421:        reg |= ESS_AUDIO2_CTRL1_DEMAND_8;
                   1422:        reg |= ESS_AUDIO2_CTRL1_DAC_ENABLE | ESS_AUDIO2_CTRL1_FIFO_ENABLE |
                   1423:               ESS_AUDIO2_CTRL1_AUTO_INIT;
                   1424:        ess_write_mix_reg(sc, ESS_MREG_AUDIO2_CTRL1, reg);
                   1425:
                   1426:        return (0);
                   1427: }
                   1428:
                   1429: int
                   1430: ess_audio1_trigger_input(addr, start, end, blksize, intr, arg, param)
                   1431:        void *addr;
                   1432:        void *start, *end;
                   1433:        int blksize;
                   1434:        void (*intr)(void *);
                   1435:        void *arg;
                   1436:        struct audio_params *param;
                   1437: {
                   1438:        struct ess_softc *sc = addr;
                   1439:        u_int8_t reg;
                   1440:
                   1441:        DPRINTFN(1, ("ess_audio1_trigger_input: sc=%p start=%p end=%p blksize=%d intr=%p(%p)\n",
                   1442:            addr, start, end, blksize, intr, arg));
                   1443:
                   1444:        if (sc->sc_audio1.active)
                   1445:                panic("ess_audio1_trigger_input: already running");
                   1446:
                   1447:        sc->sc_audio1.active = 1;
                   1448:        sc->sc_audio1.intr = intr;
                   1449:        sc->sc_audio1.arg = arg;
                   1450:        if (sc->sc_audio1.polled) {
                   1451:                sc->sc_audio1.dmapos = 0;
                   1452:                sc->sc_audio1.buffersize = (char *)end - (char *)start;
                   1453:                sc->sc_audio1.dmacount = 0;
                   1454:                sc->sc_audio1.blksize = blksize;
                   1455:                timeout_add(&sc->sc_tmo1, hz/30);
                   1456:        }
                   1457:
                   1458:        reg = ess_read_x_reg(sc, ESS_XCMD_AUDIO_CTRL);
                   1459:        if (param->channels == 2) {
                   1460:                reg &= ~ESS_AUDIO_CTRL_MONO;
                   1461:                reg |= ESS_AUDIO_CTRL_STEREO;
                   1462:        } else {
                   1463:                reg |= ESS_AUDIO_CTRL_MONO;
                   1464:                reg &= ~ESS_AUDIO_CTRL_STEREO;
                   1465:        }
                   1466:        ess_write_x_reg(sc, ESS_XCMD_AUDIO_CTRL, reg);
                   1467:
                   1468:        reg = ess_read_x_reg(sc, ESS_XCMD_AUDIO1_CTRL1);
                   1469:        if (param->precision * param->factor == 16)
                   1470:                reg |= ESS_AUDIO1_CTRL1_FIFO_SIZE;
                   1471:        else
                   1472:                reg &= ~ESS_AUDIO1_CTRL1_FIFO_SIZE;
                   1473:        if (param->channels == 2)
                   1474:                reg |= ESS_AUDIO1_CTRL1_FIFO_STEREO;
                   1475:        else
                   1476:                reg &= ~ESS_AUDIO1_CTRL1_FIFO_STEREO;
                   1477:        if (param->encoding == AUDIO_ENCODING_SLINEAR_BE ||
                   1478:            param->encoding == AUDIO_ENCODING_SLINEAR_LE)
                   1479:                reg |= ESS_AUDIO1_CTRL1_FIFO_SIGNED;
                   1480:        else
                   1481:                reg &= ~ESS_AUDIO1_CTRL1_FIFO_SIGNED;
                   1482:        reg |= ESS_AUDIO1_CTRL1_FIFO_CONNECT;
                   1483:        ess_write_x_reg(sc, ESS_XCMD_AUDIO1_CTRL1, reg);
                   1484:
                   1485:        isa_dmastart(sc->sc_isa, sc->sc_audio1.drq, start,
                   1486:                     (char *)end - (char *)start, NULL,
                   1487:            DMAMODE_READ | DMAMODE_LOOP, BUS_DMA_NOWAIT);
                   1488:
                   1489:        /* Program transfer count registers with 2's complement of count. */
                   1490:        blksize = -blksize;
                   1491:        ess_write_x_reg(sc, ESS_XCMD_XFER_COUNTLO, blksize);
                   1492:        ess_write_x_reg(sc, ESS_XCMD_XFER_COUNTHI, blksize >> 8);
                   1493:
                   1494:        /* Use 4 bytes per input DMA. */
                   1495:        ess_set_xreg_bits(sc, ESS_XCMD_DEMAND_CTRL, ESS_DEMAND_CTRL_DEMAND_4);
                   1496:
                   1497:        /* Start auto-init DMA */
                   1498:        ess_wdsp(sc, ESS_ACMD_DISABLE_SPKR);
                   1499:        reg = ess_read_x_reg(sc, ESS_XCMD_AUDIO1_CTRL2);
                   1500:        reg |= ESS_AUDIO1_CTRL2_DMA_READ | ESS_AUDIO1_CTRL2_ADC_ENABLE;
                   1501:        reg |= ESS_AUDIO1_CTRL2_FIFO_ENABLE | ESS_AUDIO1_CTRL2_AUTO_INIT;
                   1502:        ess_write_x_reg(sc, ESS_XCMD_AUDIO1_CTRL2, reg);
                   1503:
                   1504:        return (0);
                   1505: }
                   1506:
                   1507: int
                   1508: ess_audio1_halt(addr)
                   1509:        void *addr;
                   1510: {
                   1511:        struct ess_softc *sc = addr;
                   1512:
                   1513:        DPRINTF(("ess_audio1_halt: sc=%p\n", sc));
                   1514:
                   1515:        if (sc->sc_audio1.active) {
                   1516:                ess_clear_xreg_bits(sc, ESS_XCMD_AUDIO1_CTRL2,
                   1517:                    ESS_AUDIO1_CTRL2_FIFO_ENABLE);
                   1518:                isa_dmaabort(sc->sc_isa, sc->sc_audio1.drq);
                   1519:                if (sc->sc_audio1.polled)
                   1520:                        timeout_del(&sc->sc_tmo1);
                   1521:                sc->sc_audio1.active = 0;
                   1522:        }
                   1523:
                   1524:        return (0);
                   1525: }
                   1526:
                   1527: int
                   1528: ess_audio2_halt(addr)
                   1529:        void *addr;
                   1530: {
                   1531:        struct ess_softc *sc = addr;
                   1532:
                   1533:        DPRINTF(("ess_audio2_halt: sc=%p\n", sc));
                   1534:
                   1535:        if (sc->sc_audio2.active) {
                   1536:                ess_clear_mreg_bits(sc, ESS_MREG_AUDIO2_CTRL1,
                   1537:                    ESS_AUDIO2_CTRL1_DAC_ENABLE |
                   1538:                    ESS_AUDIO2_CTRL1_FIFO_ENABLE);
                   1539:                isa_dmaabort(sc->sc_isa, sc->sc_audio2.drq);
                   1540:                if (sc->sc_audio2.polled)
                   1541:                        timeout_del(&sc->sc_tmo2);
                   1542:                sc->sc_audio2.active = 0;
                   1543:        }
                   1544:
                   1545:        return (0);
                   1546: }
                   1547:
                   1548: int
                   1549: ess_audio1_intr(arg)
                   1550:        void *arg;
                   1551: {
                   1552:        struct ess_softc *sc = arg;
                   1553:        u_int8_t reg;
                   1554:
                   1555:        DPRINTFN(1,("ess_audio1_intr: intr=%p\n", sc->sc_audio1.intr));
                   1556:
                   1557:        /* Check and clear interrupt on Audio1. */
                   1558:        reg = EREAD1(sc->sc_iot, sc->sc_ioh, ESS_DSP_RW_STATUS);
                   1559:        if ((reg & ESS_DSP_READ_OFLOW) == 0)
                   1560:                return (0);
                   1561:        reg = EREAD1(sc->sc_iot, sc->sc_ioh, ESS_CLEAR_INTR);
                   1562:
                   1563:        sc->sc_audio1.nintr++;
                   1564:
                   1565:        if (sc->sc_audio1.active) {
                   1566:                (*sc->sc_audio1.intr)(sc->sc_audio1.arg);
                   1567:                return (1);
                   1568:        } else
                   1569:                return (0);
                   1570: }
                   1571:
                   1572: int
                   1573: ess_audio2_intr(arg)
                   1574:        void *arg;
                   1575: {
                   1576:        struct ess_softc *sc = arg;
                   1577:        u_int8_t reg;
                   1578:
                   1579:        DPRINTFN(1,("ess_audio2_intr: intr=%p\n", sc->sc_audio2.intr));
                   1580:
                   1581:        /* Check and clear interrupt on Audio2. */
                   1582:        reg = ess_read_mix_reg(sc, ESS_MREG_AUDIO2_CTRL2);
                   1583:        if ((reg & ESS_AUDIO2_CTRL2_IRQ_LATCH) == 0)
                   1584:                return (0);
                   1585:        reg &= ~ESS_AUDIO2_CTRL2_IRQ_LATCH;
                   1586:        ess_write_mix_reg(sc, ESS_MREG_AUDIO2_CTRL2, reg);
                   1587:
                   1588:        sc->sc_audio2.nintr++;
                   1589:
                   1590:        if (sc->sc_audio2.active) {
                   1591:                (*sc->sc_audio2.intr)(sc->sc_audio2.arg);
                   1592:                return (1);
                   1593:        } else
                   1594:                return (0);
                   1595: }
                   1596:
                   1597: void
                   1598: ess_audio1_poll(addr)
                   1599:        void *addr;
                   1600: {
                   1601:        struct ess_softc *sc = addr;
                   1602:        int dmapos, dmacount;
                   1603:
                   1604:        if (!sc->sc_audio1.active)
                   1605:                return;
                   1606:
                   1607:        sc->sc_audio1.nintr++;
                   1608:
                   1609:        dmapos = isa_dmacount(sc->sc_isa, sc->sc_audio1.drq);
                   1610:        dmacount = sc->sc_audio1.dmapos - dmapos;
                   1611:        if (dmacount < 0)
                   1612:                dmacount += sc->sc_audio1.buffersize;
                   1613:        sc->sc_audio1.dmapos = dmapos;
                   1614: #if 1
                   1615:        dmacount += sc->sc_audio1.dmacount;
                   1616:        while (dmacount > sc->sc_audio1.blksize) {
                   1617:                dmacount -= sc->sc_audio1.blksize;
                   1618:                (*sc->sc_audio1.intr)(sc->sc_audio1.arg);
                   1619:        }
                   1620:        sc->sc_audio1.dmacount = dmacount;
                   1621: #else
                   1622:        (*sc->sc_audio1.intr)(sc->sc_audio1.arg, dmacount);
                   1623: #endif
                   1624:
                   1625:        timeout_add(&sc->sc_tmo1, hz/30);
                   1626: }
                   1627:
                   1628: void
                   1629: ess_audio2_poll(addr)
                   1630:        void *addr;
                   1631: {
                   1632:        struct ess_softc *sc = addr;
                   1633:        int dmapos, dmacount;
                   1634:
                   1635:        if (!sc->sc_audio2.active)
                   1636:                return;
                   1637:
                   1638:        sc->sc_audio2.nintr++;
                   1639:
                   1640:        dmapos = isa_dmacount(sc->sc_isa, sc->sc_audio2.drq);
                   1641:        dmacount = sc->sc_audio2.dmapos - dmapos;
                   1642:        if (dmacount < 0)
                   1643:                dmacount += sc->sc_audio2.buffersize;
                   1644:        sc->sc_audio2.dmapos = dmapos;
                   1645: #if 1
                   1646:        dmacount += sc->sc_audio2.dmacount;
                   1647:        while (dmacount > sc->sc_audio2.blksize) {
                   1648:                dmacount -= sc->sc_audio2.blksize;
                   1649:                (*sc->sc_audio2.intr)(sc->sc_audio2.arg);
                   1650:        }
                   1651:        sc->sc_audio2.dmacount = dmacount;
                   1652: #else
                   1653:        (*sc->sc_audio2.intr)(sc->sc_audio2.arg, dmacount);
                   1654: #endif
                   1655:
                   1656:        timeout_add(&sc->sc_tmo2, hz/30);
                   1657: }
                   1658:
                   1659: int
                   1660: ess_round_blocksize(addr, blk)
                   1661:        void *addr;
                   1662:        int blk;
                   1663: {
                   1664:        return ((blk + 7) & -8);        /* round for max DMA size */
                   1665: }
                   1666:
                   1667: int
                   1668: ess_set_port(addr, cp)
                   1669:        void *addr;
                   1670:        mixer_ctrl_t *cp;
                   1671: {
                   1672:        struct ess_softc *sc = addr;
                   1673:        int lgain, rgain;
                   1674:
                   1675:        DPRINTFN(5,("ess_set_port: port=%d num_channels=%d\n",
                   1676:                    cp->dev, cp->un.value.num_channels));
                   1677:
                   1678:        switch (cp->dev) {
                   1679:        /*
                   1680:         * The following mixer ports are all stereo. If we get a
                   1681:         * single-channel gain value passed in, then we duplicate it
                   1682:         * to both left and right channels.
                   1683:         */
                   1684:        case ESS_MASTER_VOL:
                   1685:        case ESS_DAC_PLAY_VOL:
                   1686:        case ESS_MIC_PLAY_VOL:
                   1687:        case ESS_LINE_PLAY_VOL:
                   1688:        case ESS_SYNTH_PLAY_VOL:
                   1689:        case ESS_CD_PLAY_VOL:
                   1690:        case ESS_AUXB_PLAY_VOL:
                   1691:        case ESS_RECORD_VOL:
                   1692:                if (cp->type != AUDIO_MIXER_VALUE)
                   1693:                        return EINVAL;
                   1694:
                   1695:                switch (cp->un.value.num_channels) {
                   1696:                case 1:
                   1697:                        lgain = rgain = ESS_4BIT_GAIN(
                   1698:                          cp->un.value.level[AUDIO_MIXER_LEVEL_MONO]);
                   1699:                        break;
                   1700:                case 2:
                   1701:                        lgain = ESS_4BIT_GAIN(
                   1702:                          cp->un.value.level[AUDIO_MIXER_LEVEL_LEFT]);
                   1703:                        rgain = ESS_4BIT_GAIN(
                   1704:                          cp->un.value.level[AUDIO_MIXER_LEVEL_RIGHT]);
                   1705:                        break;
                   1706:                default:
                   1707:                        return EINVAL;
                   1708:                }
                   1709:
                   1710:                sc->gain[cp->dev][ESS_LEFT]  = lgain;
                   1711:                sc->gain[cp->dev][ESS_RIGHT] = rgain;
                   1712:                ess_set_gain(sc, cp->dev, 1);
                   1713:                return (0);
                   1714:
                   1715:        /*
                   1716:         * The PC speaker port is mono. If we get a stereo gain value
                   1717:         * passed in, then we return EINVAL.
                   1718:         */
                   1719:        case ESS_PCSPEAKER_VOL:
                   1720:                if (cp->un.value.num_channels != 1)
                   1721:                        return EINVAL;
                   1722:
                   1723:                sc->gain[cp->dev][ESS_LEFT] = sc->gain[cp->dev][ESS_RIGHT] =
                   1724:                  ESS_3BIT_GAIN(cp->un.value.level[AUDIO_MIXER_LEVEL_MONO]);
                   1725:                ess_set_gain(sc, cp->dev, 1);
                   1726:                return (0);
                   1727:
                   1728:        case ESS_RECORD_SOURCE:
                   1729:                if (ESS_USE_AUDIO1(sc->sc_model)) {
                   1730:                        if (cp->type == AUDIO_MIXER_ENUM)
                   1731:                                return (ess_set_in_port(sc, cp->un.ord));
                   1732:                        else
                   1733:                                return (EINVAL);
                   1734:                } else {
                   1735:                        if (cp->type == AUDIO_MIXER_SET)
                   1736:                                return (ess_set_in_ports(sc, cp->un.mask));
                   1737:                        else
                   1738:                                return (EINVAL);
                   1739:                }
                   1740:                return (0);
                   1741:
                   1742:        case ESS_RECORD_MONITOR:
                   1743:                if (cp->type != AUDIO_MIXER_ENUM)
                   1744:                        return EINVAL;
                   1745:
                   1746:                if (cp->un.ord)
                   1747:                        /* Enable monitor */
                   1748:                        ess_set_xreg_bits(sc, ESS_XCMD_AUDIO_CTRL,
                   1749:                                          ESS_AUDIO_CTRL_MONITOR);
                   1750:                else
                   1751:                        /* Disable monitor */
                   1752:                        ess_clear_xreg_bits(sc, ESS_XCMD_AUDIO_CTRL,
                   1753:                                            ESS_AUDIO_CTRL_MONITOR);
                   1754:                return (0);
                   1755:        }
                   1756:
                   1757:        if (ESS_USE_AUDIO1(sc->sc_model))
                   1758:                return (EINVAL);
                   1759:
                   1760:        switch (cp->dev) {
                   1761:        case ESS_DAC_REC_VOL:
                   1762:        case ESS_MIC_REC_VOL:
                   1763:        case ESS_LINE_REC_VOL:
                   1764:        case ESS_SYNTH_REC_VOL:
                   1765:        case ESS_CD_REC_VOL:
                   1766:        case ESS_AUXB_REC_VOL:
                   1767:                if (cp->type != AUDIO_MIXER_VALUE)
                   1768:                        return EINVAL;
                   1769:
                   1770:                switch (cp->un.value.num_channels) {
                   1771:                case 1:
                   1772:                        lgain = rgain = ESS_4BIT_GAIN(
                   1773:                          cp->un.value.level[AUDIO_MIXER_LEVEL_MONO]);
                   1774:                        break;
                   1775:                case 2:
                   1776:                        lgain = ESS_4BIT_GAIN(
                   1777:                          cp->un.value.level[AUDIO_MIXER_LEVEL_LEFT]);
                   1778:                        rgain = ESS_4BIT_GAIN(
                   1779:                          cp->un.value.level[AUDIO_MIXER_LEVEL_RIGHT]);
                   1780:                        break;
                   1781:                default:
                   1782:                        return EINVAL;
                   1783:                }
                   1784:
                   1785:                sc->gain[cp->dev][ESS_LEFT]  = lgain;
                   1786:                sc->gain[cp->dev][ESS_RIGHT] = rgain;
                   1787:                ess_set_gain(sc, cp->dev, 1);
                   1788:                return (0);
                   1789:
                   1790:        case ESS_MIC_PREAMP:
                   1791:                if (cp->type != AUDIO_MIXER_ENUM)
                   1792:                        return EINVAL;
                   1793:
                   1794:                if (cp->un.ord)
                   1795:                        /* Enable microphone preamp */
                   1796:                        ess_set_xreg_bits(sc, ESS_XCMD_PREAMP_CTRL,
                   1797:                                          ESS_PREAMP_CTRL_ENABLE);
                   1798:                else
                   1799:                        /* Disable microphone preamp */
                   1800:                        ess_clear_xreg_bits(sc, ESS_XCMD_PREAMP_CTRL,
                   1801:                                          ESS_PREAMP_CTRL_ENABLE);
                   1802:                return (0);
                   1803:        }
                   1804:
                   1805:        return (EINVAL);
                   1806: }
                   1807:
                   1808: int
                   1809: ess_get_port(addr, cp)
                   1810:        void *addr;
                   1811:        mixer_ctrl_t *cp;
                   1812: {
                   1813:        struct ess_softc *sc = addr;
                   1814:
                   1815:        DPRINTFN(5,("ess_get_port: port=%d\n", cp->dev));
                   1816:
                   1817:        switch (cp->dev) {
                   1818:        case ESS_MASTER_VOL:
                   1819:        case ESS_DAC_PLAY_VOL:
                   1820:        case ESS_MIC_PLAY_VOL:
                   1821:        case ESS_LINE_PLAY_VOL:
                   1822:        case ESS_SYNTH_PLAY_VOL:
                   1823:        case ESS_CD_PLAY_VOL:
                   1824:        case ESS_AUXB_PLAY_VOL:
                   1825:        case ESS_RECORD_VOL:
                   1826:                switch (cp->un.value.num_channels) {
                   1827:                case 1:
                   1828:                        cp->un.value.level[AUDIO_MIXER_LEVEL_MONO] =
                   1829:                                sc->gain[cp->dev][ESS_LEFT];
                   1830:                        break;
                   1831:                case 2:
                   1832:                        cp->un.value.level[AUDIO_MIXER_LEVEL_LEFT] =
                   1833:                                sc->gain[cp->dev][ESS_LEFT];
                   1834:                        cp->un.value.level[AUDIO_MIXER_LEVEL_RIGHT] =
                   1835:                                sc->gain[cp->dev][ESS_RIGHT];
                   1836:                        break;
                   1837:                default:
                   1838:                        return EINVAL;
                   1839:                }
                   1840:                return (0);
                   1841:
                   1842:        case ESS_PCSPEAKER_VOL:
                   1843:                if (cp->un.value.num_channels != 1)
                   1844:                        return EINVAL;
                   1845:
                   1846:                cp->un.value.level[AUDIO_MIXER_LEVEL_MONO] =
                   1847:                        sc->gain[cp->dev][ESS_LEFT];
                   1848:                return (0);
                   1849:
                   1850:        case ESS_RECORD_SOURCE:
                   1851:                if (ESS_USE_AUDIO1(sc->sc_model))
                   1852:                        cp->un.ord = sc->in_port;
                   1853:                else
                   1854:                        cp->un.mask = sc->in_mask;
                   1855:                return (0);
                   1856:
                   1857:        case ESS_RECORD_MONITOR:
                   1858:                cp->un.ord = (ess_read_x_reg(sc, ESS_XCMD_AUDIO_CTRL) &
                   1859:                              ESS_AUDIO_CTRL_MONITOR) ? 1 : 0;
                   1860:                return (0);
                   1861:        }
                   1862:
                   1863:        if (ESS_USE_AUDIO1(sc->sc_model))
                   1864:                return (EINVAL);
                   1865:
                   1866:        switch (cp->dev) {
                   1867:        case ESS_DAC_REC_VOL:
                   1868:        case ESS_MIC_REC_VOL:
                   1869:        case ESS_LINE_REC_VOL:
                   1870:        case ESS_SYNTH_REC_VOL:
                   1871:        case ESS_CD_REC_VOL:
                   1872:        case ESS_AUXB_REC_VOL:
                   1873:                switch (cp->un.value.num_channels) {
                   1874:                case 1:
                   1875:                        cp->un.value.level[AUDIO_MIXER_LEVEL_MONO] =
                   1876:                                sc->gain[cp->dev][ESS_LEFT];
                   1877:                        break;
                   1878:                case 2:
                   1879:                        cp->un.value.level[AUDIO_MIXER_LEVEL_LEFT] =
                   1880:                                sc->gain[cp->dev][ESS_LEFT];
                   1881:                        cp->un.value.level[AUDIO_MIXER_LEVEL_RIGHT] =
                   1882:                                sc->gain[cp->dev][ESS_RIGHT];
                   1883:                        break;
                   1884:                default:
                   1885:                        return EINVAL;
                   1886:                }
                   1887:                return (0);
                   1888:
                   1889:        case ESS_MIC_PREAMP:
                   1890:                cp->un.ord = (ess_read_x_reg(sc, ESS_XCMD_PREAMP_CTRL) &
                   1891:                              ESS_PREAMP_CTRL_ENABLE) ? 1 : 0;
                   1892:                return (0);
                   1893:        }
                   1894:
                   1895:        return (EINVAL);
                   1896: }
                   1897:
                   1898: int
                   1899: ess_query_devinfo(addr, dip)
                   1900:        void *addr;
                   1901:        mixer_devinfo_t *dip;
                   1902: {
                   1903:        struct ess_softc *sc = addr;
                   1904:
                   1905:        DPRINTFN(5,("ess_query_devinfo: model=%d index=%d\n",
                   1906:                    sc->sc_model, dip->index));
                   1907:
                   1908:        /*
                   1909:         * REVISIT: There are some slight differences between the
                   1910:         *          mixers on the different ESS chips, which can
                   1911:         *          be sorted out using the chip model rather than a
                   1912:         *          separate mixer model.
                   1913:         *          This is currently coded assuming an ES1887; we
                   1914:         *          need to work out which bits are not applicable to
                   1915:         *          the other models (1888 and 888).
                   1916:         */
                   1917:        switch (dip->index) {
                   1918:        case ESS_DAC_PLAY_VOL:
                   1919:                dip->mixer_class = ESS_INPUT_CLASS;
                   1920:                dip->next = dip->prev = AUDIO_MIXER_LAST;
                   1921:                strlcpy(dip->label.name, AudioNdac, sizeof dip->label.name);
                   1922:                dip->type = AUDIO_MIXER_VALUE;
                   1923:                dip->un.v.num_channels = 2;
                   1924:                strlcpy(dip->un.v.units.name, AudioNvolume,
                   1925:                    sizeof dip->un.v.units.name);
                   1926:                return (0);
                   1927:
                   1928:        case ESS_MIC_PLAY_VOL:
                   1929:                dip->mixer_class = ESS_INPUT_CLASS;
                   1930:                dip->prev = AUDIO_MIXER_LAST;
                   1931:                if (ESS_USE_AUDIO1(sc->sc_model))
                   1932:                        dip->next = AUDIO_MIXER_LAST;
                   1933:                else
                   1934:                        dip->next = ESS_MIC_PREAMP;
                   1935:                strlcpy(dip->label.name, AudioNmicrophone,
                   1936:                    sizeof dip->label.name);
                   1937:                dip->type = AUDIO_MIXER_VALUE;
                   1938:                dip->un.v.num_channels = 2;
                   1939:                strlcpy(dip->un.v.units.name, AudioNvolume,
                   1940:                    sizeof dip->un.v.units.name);
                   1941:                return (0);
                   1942:
                   1943:        case ESS_LINE_PLAY_VOL:
                   1944:                dip->mixer_class = ESS_INPUT_CLASS;
                   1945:                dip->next = dip->prev = AUDIO_MIXER_LAST;
                   1946:                strlcpy(dip->label.name, AudioNline, sizeof dip->label.name);
                   1947:                dip->type = AUDIO_MIXER_VALUE;
                   1948:                dip->un.v.num_channels = 2;
                   1949:                strlcpy(dip->un.v.units.name, AudioNvolume,
                   1950:                    sizeof dip->un.v.units.name);
                   1951:                return (0);
                   1952:
                   1953:        case ESS_SYNTH_PLAY_VOL:
                   1954:                dip->mixer_class = ESS_INPUT_CLASS;
                   1955:                dip->next = dip->prev = AUDIO_MIXER_LAST;
                   1956:                strlcpy(dip->label.name, AudioNfmsynth,
                   1957:                    sizeof dip->label.name);
                   1958:                dip->type = AUDIO_MIXER_VALUE;
                   1959:                dip->un.v.num_channels = 2;
                   1960:                strlcpy(dip->un.v.units.name, AudioNvolume,
                   1961:                    sizeof dip->un.v.units.name);
                   1962:                return (0);
                   1963:
                   1964:        case ESS_CD_PLAY_VOL:
                   1965:                dip->mixer_class = ESS_INPUT_CLASS;
                   1966:                dip->next = dip->prev = AUDIO_MIXER_LAST;
                   1967:                strlcpy(dip->label.name, AudioNcd, sizeof dip->label.name);
                   1968:                dip->type = AUDIO_MIXER_VALUE;
                   1969:                dip->un.v.num_channels = 2;
                   1970:                strlcpy(dip->un.v.units.name, AudioNvolume,
                   1971:                    sizeof dip->un.v.units.name);
                   1972:                return (0);
                   1973:
                   1974:        case ESS_AUXB_PLAY_VOL:
                   1975:                dip->mixer_class = ESS_INPUT_CLASS;
                   1976:                dip->next = dip->prev = AUDIO_MIXER_LAST;
                   1977:                strlcpy(dip->label.name, "auxb", sizeof dip->label.name);
                   1978:                dip->type = AUDIO_MIXER_VALUE;
                   1979:                dip->un.v.num_channels = 2;
                   1980:                strlcpy(dip->un.v.units.name, AudioNvolume,
                   1981:                    sizeof dip->un.v.units.name);
                   1982:                return (0);
                   1983:
                   1984:        case ESS_INPUT_CLASS:
                   1985:                dip->mixer_class = ESS_INPUT_CLASS;
                   1986:                dip->next = dip->prev = AUDIO_MIXER_LAST;
                   1987:                strlcpy(dip->label.name, AudioCinputs, sizeof dip->label.name);
                   1988:                dip->type = AUDIO_MIXER_CLASS;
                   1989:                return (0);
                   1990:
                   1991:        case ESS_MASTER_VOL:
                   1992:                dip->mixer_class = ESS_OUTPUT_CLASS;
                   1993:                dip->next = dip->prev = AUDIO_MIXER_LAST;
                   1994:                strlcpy(dip->label.name, AudioNmaster, sizeof dip->label.name);
                   1995:                dip->type = AUDIO_MIXER_VALUE;
                   1996:                dip->un.v.num_channels = 2;
                   1997:                strlcpy(dip->un.v.units.name, AudioNvolume,
                   1998:                    sizeof dip->un.v.units.name);
                   1999:                return (0);
                   2000:
                   2001:        case ESS_PCSPEAKER_VOL:
                   2002:                dip->mixer_class = ESS_OUTPUT_CLASS;
                   2003:                dip->next = dip->prev = AUDIO_MIXER_LAST;
                   2004:                strlcpy(dip->label.name, "pc_speaker", sizeof dip->label.name);
                   2005:                dip->type = AUDIO_MIXER_VALUE;
                   2006:                dip->un.v.num_channels = 1;
                   2007:                strlcpy(dip->un.v.units.name, AudioNvolume,
                   2008:                    sizeof dip->un.v.units.name);
                   2009:                return (0);
                   2010:
                   2011:        case ESS_OUTPUT_CLASS:
                   2012:                dip->mixer_class = ESS_OUTPUT_CLASS;
                   2013:                dip->next = dip->prev = AUDIO_MIXER_LAST;
                   2014:                strlcpy(dip->label.name, AudioCoutputs, sizeof dip->label.name);
                   2015:                dip->type = AUDIO_MIXER_CLASS;
                   2016:                return (0);
                   2017:
                   2018:        case ESS_RECORD_VOL:
                   2019:                dip->mixer_class = ESS_RECORD_CLASS;
                   2020:                dip->next = dip->prev = AUDIO_MIXER_LAST;
                   2021:                strlcpy(dip->label.name, AudioNrecord, sizeof dip->label.name);
                   2022:                dip->type = AUDIO_MIXER_VALUE;
                   2023:                dip->un.v.num_channels = 2;
                   2024:                strlcpy(dip->un.v.units.name, AudioNvolume,
                   2025:                    sizeof dip->un.v.units.name);
                   2026:                return (0);
                   2027:
                   2028:        case ESS_RECORD_SOURCE:
                   2029:                dip->mixer_class = ESS_RECORD_CLASS;
                   2030:                dip->next = dip->prev = AUDIO_MIXER_LAST;
                   2031:                strlcpy(dip->label.name, AudioNsource, sizeof dip->label.name);
                   2032:                if (ESS_USE_AUDIO1(sc->sc_model)) {
                   2033:                        /*
                   2034:                         * The 1788 doesn't use the input mixer control that
                   2035:                         * the 1888 uses, because it's a pain when you only
                   2036:                         * have one mixer.
                   2037:                         * Perhaps it could be emulated by keeping both sets of
                   2038:                         * gain values, and doing a `context switch' of the
                   2039:                         * mixer registers when shifting from playing to
                   2040:                         * recording.
                   2041:                         */
                   2042:                        dip->type = AUDIO_MIXER_ENUM;
                   2043:                        dip->un.e.num_mem = 4;
                   2044:                        strlcpy(dip->un.e.member[0].label.name,
                   2045:                            AudioNmicrophone,
                   2046:                            sizeof dip->un.e.member[0].label.name);
                   2047:                        dip->un.e.member[0].ord = ESS_SOURCE_MIC;
                   2048:                        strlcpy(dip->un.e.member[1].label.name, AudioNline,
                   2049:                            sizeof dip->un.e.member[1].label.name);
                   2050:                        dip->un.e.member[1].ord = ESS_SOURCE_LINE;
                   2051:                        strlcpy(dip->un.e.member[2].label.name, AudioNcd,
                   2052:                            sizeof dip->un.e.member[2].label.name);
                   2053:                        dip->un.e.member[2].ord = ESS_SOURCE_CD;
                   2054:                        strlcpy(dip->un.e.member[3].label.name, AudioNmixerout,
                   2055:                            sizeof dip->un.e.member[3].label.name);
                   2056:                        dip->un.e.member[3].ord = ESS_SOURCE_MIXER;
                   2057:                } else {
                   2058:                        dip->type = AUDIO_MIXER_SET;
                   2059:                        dip->un.s.num_mem = 6;
                   2060:                        strlcpy(dip->un.s.member[0].label.name, AudioNdac,
                   2061:                            sizeof dip->un.e.member[0].label.name);
                   2062:                        dip->un.s.member[0].mask = 1 << ESS_DAC_REC_VOL;
                   2063:                        strlcpy(dip->un.s.member[1].label.name,
                   2064:                            AudioNmicrophone,
                   2065:                            sizeof dip->un.e.member[1].label.name);
                   2066:                        dip->un.s.member[1].mask = 1 << ESS_MIC_REC_VOL;
                   2067:                        strlcpy(dip->un.s.member[2].label.name, AudioNline,
                   2068:                            sizeof dip->un.e.member[2].label.name);
                   2069:                        dip->un.s.member[2].mask = 1 << ESS_LINE_REC_VOL;
                   2070:                        strlcpy(dip->un.s.member[3].label.name, AudioNfmsynth,
                   2071:                            sizeof dip->un.e.member[3].label.name);
                   2072:                        dip->un.s.member[3].mask = 1 << ESS_SYNTH_REC_VOL;
                   2073:                        strlcpy(dip->un.s.member[4].label.name, AudioNcd,
                   2074:                            sizeof dip->un.e.member[4].label.name);
                   2075:                        dip->un.s.member[4].mask = 1 << ESS_CD_REC_VOL;
                   2076:                        strlcpy(dip->un.s.member[5].label.name, "auxb",
                   2077:                            sizeof dip->un.e.member[5].label.name);
                   2078:                        dip->un.s.member[5].mask = 1 << ESS_AUXB_REC_VOL;
                   2079:                }
                   2080:                return (0);
                   2081:
                   2082:        case ESS_RECORD_CLASS:
                   2083:                dip->mixer_class = ESS_RECORD_CLASS;
                   2084:                dip->next = dip->prev = AUDIO_MIXER_LAST;
                   2085:                strlcpy(dip->label.name, AudioCrecord, sizeof dip->label.name);
                   2086:                dip->type = AUDIO_MIXER_CLASS;
                   2087:                return (0);
                   2088:
                   2089:        case ESS_RECORD_MONITOR:
                   2090:                dip->prev = dip->next = AUDIO_MIXER_LAST;
                   2091:                strlcpy(dip->label.name, AudioNmute, sizeof dip->label.name);
                   2092:                dip->type = AUDIO_MIXER_ENUM;
                   2093:                dip->mixer_class = ESS_MONITOR_CLASS;
                   2094:                dip->un.e.num_mem = 2;
                   2095:                strlcpy(dip->un.e.member[0].label.name, AudioNoff,
                   2096:                    sizeof dip->un.e.member[0].label.name);
                   2097:                dip->un.e.member[0].ord = 0;
                   2098:                strlcpy(dip->un.e.member[1].label.name, AudioNon,
                   2099:                    sizeof dip->un.e.member[1].label.name);
                   2100:                dip->un.e.member[1].ord = 1;
                   2101:                return (0);
                   2102:
                   2103:        case ESS_MONITOR_CLASS:
                   2104:                dip->mixer_class = ESS_MONITOR_CLASS;
                   2105:                dip->next = dip->prev = AUDIO_MIXER_LAST;
                   2106:                strlcpy(dip->label.name, AudioCmonitor,
                   2107:                    sizeof dip->label.name);
                   2108:                dip->type = AUDIO_MIXER_CLASS;
                   2109:                return (0);
                   2110:        }
                   2111:
                   2112:        if (ESS_USE_AUDIO1(sc->sc_model))
                   2113:                return (ENXIO);
                   2114:
                   2115:        switch (dip->index) {
                   2116:        case ESS_DAC_REC_VOL:
                   2117:                dip->mixer_class = ESS_RECORD_CLASS;
                   2118:                dip->next = dip->prev = AUDIO_MIXER_LAST;
                   2119:                strlcpy(dip->label.name, AudioNdac, sizeof dip->label.name);
                   2120:                dip->type = AUDIO_MIXER_VALUE;
                   2121:                dip->un.v.num_channels = 2;
                   2122:                strlcpy(dip->un.v.units.name, AudioNvolume,
                   2123:                    sizeof dip->un.v.units.name);
                   2124:                return (0);
                   2125:
                   2126:        case ESS_MIC_REC_VOL:
                   2127:                dip->mixer_class = ESS_RECORD_CLASS;
                   2128:                dip->next = dip->prev = AUDIO_MIXER_LAST;
                   2129:                strlcpy(dip->label.name, AudioNmicrophone,
                   2130:                    sizeof dip->label.name);
                   2131:                dip->type = AUDIO_MIXER_VALUE;
                   2132:                dip->un.v.num_channels = 2;
                   2133:                strlcpy(dip->un.v.units.name, AudioNvolume,
                   2134:                    sizeof dip->un.v.units.name);
                   2135:                return (0);
                   2136:
                   2137:        case ESS_LINE_REC_VOL:
                   2138:                dip->mixer_class = ESS_RECORD_CLASS;
                   2139:                dip->next = dip->prev = AUDIO_MIXER_LAST;
                   2140:                strlcpy(dip->label.name, AudioNline, sizeof dip->label.name);
                   2141:                dip->type = AUDIO_MIXER_VALUE;
                   2142:                dip->un.v.num_channels = 2;
                   2143:                strlcpy(dip->un.v.units.name, AudioNvolume,
                   2144:                    sizeof dip->un.v.units.name);
                   2145:                return (0);
                   2146:
                   2147:        case ESS_SYNTH_REC_VOL:
                   2148:                dip->mixer_class = ESS_RECORD_CLASS;
                   2149:                dip->next = dip->prev = AUDIO_MIXER_LAST;
                   2150:                strlcpy(dip->label.name, AudioNfmsynth,
                   2151:                    sizeof dip->label.name);
                   2152:                dip->type = AUDIO_MIXER_VALUE;
                   2153:                dip->un.v.num_channels = 2;
                   2154:                strlcpy(dip->un.v.units.name, AudioNvolume,
                   2155:                    sizeof dip->un.v.units.name);
                   2156:                return (0);
                   2157:
                   2158:        case ESS_CD_REC_VOL:
                   2159:                dip->mixer_class = ESS_RECORD_CLASS;
                   2160:                dip->next = dip->prev = AUDIO_MIXER_LAST;
                   2161:                strlcpy(dip->label.name, AudioNcd, sizeof dip->label.name);
                   2162:                dip->type = AUDIO_MIXER_VALUE;
                   2163:                dip->un.v.num_channels = 2;
                   2164:                strlcpy(dip->un.v.units.name, AudioNvolume,
                   2165:                    sizeof dip->un.v.units.name);
                   2166:                return (0);
                   2167:
                   2168:        case ESS_AUXB_REC_VOL:
                   2169:                dip->mixer_class = ESS_RECORD_CLASS;
                   2170:                dip->next = dip->prev = AUDIO_MIXER_LAST;
                   2171:                strlcpy(dip->label.name, "auxb", sizeof dip->label.name);
                   2172:                dip->type = AUDIO_MIXER_VALUE;
                   2173:                dip->un.v.num_channels = 2;
                   2174:                strlcpy(dip->un.v.units.name, AudioNvolume,
                   2175:                    sizeof dip->un.v.units.name);
                   2176:                return (0);
                   2177:
                   2178:        case ESS_MIC_PREAMP:
                   2179:                dip->mixer_class = ESS_INPUT_CLASS;
                   2180:                dip->prev = ESS_MIC_PLAY_VOL;
                   2181:                dip->next = AUDIO_MIXER_LAST;
                   2182:                strlcpy(dip->label.name, AudioNpreamp, sizeof dip->label.name);
                   2183:                dip->type = AUDIO_MIXER_ENUM;
                   2184:                dip->un.e.num_mem = 2;
                   2185:                strlcpy(dip->un.e.member[0].label.name, AudioNoff,
                   2186:                    sizeof dip->un.e.member[0].label.name);
                   2187:                dip->un.e.member[0].ord = 0;
                   2188:                strlcpy(dip->un.e.member[1].label.name, AudioNon,
                   2189:                    sizeof dip->un.e.member[1].label.name);
                   2190:                dip->un.e.member[1].ord = 1;
                   2191:                return (0);
                   2192:        }
                   2193:
                   2194:        return (ENXIO);
                   2195: }
                   2196:
                   2197: void *
                   2198: ess_malloc(addr, direction, size, pool, flags)
                   2199:        void *addr;
                   2200:        int direction;
                   2201:        size_t size;
                   2202:        int pool, flags;
                   2203: {
                   2204:        struct ess_softc *sc = addr;
                   2205:        int drq;
                   2206:
                   2207:        if (!ESS_USE_AUDIO1(sc->sc_model))
                   2208:                drq = sc->sc_audio2.drq;
                   2209:        else
                   2210:                drq = sc->sc_audio1.drq;
                   2211:        return (isa_malloc(sc->sc_isa, drq, size, pool, flags));
                   2212: }
                   2213:
                   2214: void
                   2215: ess_free(addr, ptr, pool)
                   2216:        void *addr;
                   2217:        void *ptr;
                   2218:        int pool;
                   2219: {
                   2220:        isa_free(ptr, pool);
                   2221: }
                   2222:
                   2223: size_t
                   2224: ess_round_buffersize(addr, direction, size)
                   2225:        void *addr;
                   2226:        int direction;
                   2227:        size_t size;
                   2228: {
                   2229:        if (size > MAX_ISADMA)
                   2230:                size = MAX_ISADMA;
                   2231:        return (size);
                   2232: }
                   2233:
                   2234: paddr_t
                   2235: ess_mappage(addr, mem, off, prot)
                   2236:        void *addr;
                   2237:        void *mem;
                   2238:        off_t off;
                   2239:        int prot;
                   2240: {
                   2241:        return (isa_mappage(mem, off, prot));
                   2242: }
                   2243:
                   2244: int
                   2245: ess_1788_get_props(addr)
                   2246:        void *addr;
                   2247: {
                   2248:
                   2249:        return (AUDIO_PROP_MMAP | AUDIO_PROP_INDEPENDENT);
                   2250: }
                   2251:
                   2252: int
                   2253: ess_1888_get_props(addr)
                   2254:        void *addr;
                   2255: {
                   2256:
                   2257:        return (AUDIO_PROP_MMAP | AUDIO_PROP_INDEPENDENT | AUDIO_PROP_FULLDUPLEX);
                   2258: }
                   2259:
                   2260: /* ============================================
                   2261:  * Generic functions for ess, not used by audio h/w i/f
                   2262:  * =============================================
                   2263:  */
                   2264:
                   2265: /*
                   2266:  * Reset the chip.
                   2267:  * Return non-zero if the chip isn't detected.
                   2268:  */
                   2269: int
                   2270: ess_reset(sc)
                   2271:        struct ess_softc *sc;
                   2272: {
                   2273:        bus_space_tag_t iot = sc->sc_iot;
                   2274:        bus_space_handle_t ioh = sc->sc_ioh;
                   2275:
                   2276:        sc->sc_audio1.active = 0;
                   2277:        sc->sc_audio2.active = 0;
                   2278:
                   2279:        EWRITE1(iot, ioh, ESS_DSP_RESET, ESS_RESET_EXT);
                   2280:        delay(10000);
                   2281:        EWRITE1(iot, ioh, ESS_DSP_RESET, 0);
                   2282:        if (ess_rdsp(sc) != ESS_MAGIC)
                   2283:                return (1);
                   2284:
                   2285:        /* Enable access to the ESS extension commands. */
                   2286:        ess_wdsp(sc, ESS_ACMD_ENABLE_EXT);
                   2287:
                   2288:        return (0);
                   2289: }
                   2290:
                   2291: void
                   2292: ess_set_gain(sc, port, on)
                   2293:        struct ess_softc *sc;
                   2294:        int port;
                   2295:        int on;
                   2296: {
                   2297:        int gain, left, right;
                   2298:        int mix;
                   2299:        int src;
                   2300:        int stereo;
                   2301:
                   2302:        /*
                   2303:         * Most gain controls are found in the mixer registers and
                   2304:         * are stereo. Any that are not, must set mix and stereo as
                   2305:         * required.
                   2306:         */
                   2307:        mix = 1;
                   2308:        stereo = 1;
                   2309:
                   2310:        switch (port) {
                   2311:        case ESS_MASTER_VOL:
                   2312:                src = ESS_MREG_VOLUME_MASTER;
                   2313:                break;
                   2314:        case ESS_DAC_PLAY_VOL:
                   2315:                if (ESS_USE_AUDIO1(sc->sc_model))
                   2316:                        src = ESS_MREG_VOLUME_VOICE;
                   2317:                else
                   2318:                        src = 0x7C;
                   2319:                break;
                   2320:        case ESS_MIC_PLAY_VOL:
                   2321:                src = ESS_MREG_VOLUME_MIC;
                   2322:                break;
                   2323:        case ESS_LINE_PLAY_VOL:
                   2324:                src = ESS_MREG_VOLUME_LINE;
                   2325:                break;
                   2326:        case ESS_SYNTH_PLAY_VOL:
                   2327:                src = ESS_MREG_VOLUME_SYNTH;
                   2328:                break;
                   2329:        case ESS_CD_PLAY_VOL:
                   2330:                src = ESS_MREG_VOLUME_CD;
                   2331:                break;
                   2332:        case ESS_AUXB_PLAY_VOL:
                   2333:                src = ESS_MREG_VOLUME_AUXB;
                   2334:                break;
                   2335:        case ESS_PCSPEAKER_VOL:
                   2336:                src = ESS_MREG_VOLUME_PCSPKR;
                   2337:                stereo = 0;
                   2338:                break;
                   2339:        case ESS_DAC_REC_VOL:
                   2340:                src = 0x69;
                   2341:                break;
                   2342:        case ESS_MIC_REC_VOL:
                   2343:                src = 0x68;
                   2344:                break;
                   2345:        case ESS_LINE_REC_VOL:
                   2346:                src = 0x6E;
                   2347:                break;
                   2348:        case ESS_SYNTH_REC_VOL:
                   2349:                src = 0x6B;
                   2350:                break;
                   2351:        case ESS_CD_REC_VOL:
                   2352:                src = 0x6A;
                   2353:                break;
                   2354:        case ESS_AUXB_REC_VOL:
                   2355:                src = 0x6C;
                   2356:                break;
                   2357:        case ESS_RECORD_VOL:
                   2358:                src = ESS_XCMD_VOLIN_CTRL;
                   2359:                mix = 0;
                   2360:                break;
                   2361:        default:
                   2362:                return;
                   2363:        }
                   2364:
                   2365:        /* 1788 doesn't have a separate recording mixer */
                   2366:        if (ESS_USE_AUDIO1(sc->sc_model) && mix && src > 0x62)
                   2367:                return;
                   2368:
                   2369:        if (on) {
                   2370:                left = sc->gain[port][ESS_LEFT];
                   2371:                right = sc->gain[port][ESS_RIGHT];
                   2372:        } else {
                   2373:                left = right = 0;
                   2374:        }
                   2375:
                   2376:        if (stereo)
                   2377:                gain = ESS_STEREO_GAIN(left, right);
                   2378:        else
                   2379:                gain = ESS_MONO_GAIN(left);
                   2380:
                   2381:        if (mix)
                   2382:                ess_write_mix_reg(sc, src, gain);
                   2383:        else
                   2384:                ess_write_x_reg(sc, src, gain);
                   2385: }
                   2386:
                   2387: /* Set the input device on devices without an input mixer. */
                   2388: int
                   2389: ess_set_in_port(sc, ord)
                   2390:        struct ess_softc *sc;
                   2391:        int ord;
                   2392: {
                   2393:        mixer_devinfo_t di;
                   2394:        int i;
                   2395:
                   2396:        DPRINTF(("ess_set_in_port: ord=0x%x\n", ord));
                   2397:
                   2398:        /*
                   2399:         * Get the device info for the record source control,
                   2400:         * including the list of available sources.
                   2401:         */
                   2402:        di.index = ESS_RECORD_SOURCE;
                   2403:        if (ess_query_devinfo(sc, &di))
                   2404:                return EINVAL;
                   2405:
                   2406:        /* See if the given ord value was anywhere in the list. */
                   2407:        for (i = 0; i < di.un.e.num_mem; i++) {
                   2408:                if (ord == di.un.e.member[i].ord)
                   2409:                        break;
                   2410:        }
                   2411:        if (i == di.un.e.num_mem)
                   2412:                return EINVAL;
                   2413:
                   2414:        ess_write_mix_reg(sc, ESS_MREG_ADC_SOURCE, ord);
                   2415:
                   2416:        sc->in_port = ord;
                   2417:        return (0);
                   2418: }
                   2419:
                   2420: /* Set the input device levels on input-mixer-enabled devices. */
                   2421: int
                   2422: ess_set_in_ports(sc, mask)
                   2423:        struct ess_softc *sc;
                   2424:        int mask;
                   2425: {
                   2426:        mixer_devinfo_t di;
                   2427:        int i, port;
                   2428:
                   2429:        DPRINTF(("ess_set_in_ports: mask=0x%x\n", mask));
                   2430:
                   2431:        /*
                   2432:         * Get the device info for the record source control,
                   2433:         * including the list of available sources.
                   2434:         */
                   2435:        di.index = ESS_RECORD_SOURCE;
                   2436:        if (ess_query_devinfo(sc, &di))
                   2437:                return EINVAL;
                   2438:
                   2439:        /*
                   2440:         * Set or disable the record volume control for each of the
                   2441:         * possible sources.
                   2442:         */
                   2443:        for (i = 0; i < di.un.s.num_mem; i++) {
                   2444:                /*
                   2445:                 * Calculate the source port number from its mask.
                   2446:                 */
                   2447:                port = ffs(di.un.s.member[i].mask);
                   2448:
                   2449:                /*
                   2450:                 * Set the source gain:
                   2451:                 *      to the current value if source is enabled
                   2452:                 *      to zero if source is disabled
                   2453:                 */
                   2454:                ess_set_gain(sc, port, mask & di.un.s.member[i].mask);
                   2455:        }
                   2456:
                   2457:        sc->in_mask = mask;
                   2458:        return (0);
                   2459: }
                   2460:
                   2461: void
                   2462: ess_speaker_on(sc)
                   2463:        struct ess_softc *sc;
                   2464: {
                   2465:        /* Unmute the DAC. */
                   2466:        ess_set_gain(sc, ESS_DAC_PLAY_VOL, 1);
                   2467: }
                   2468:
                   2469: void
                   2470: ess_speaker_off(sc)
                   2471:        struct ess_softc *sc;
                   2472: {
                   2473:        /* Mute the DAC. */
                   2474:        ess_set_gain(sc, ESS_DAC_PLAY_VOL, 0);
                   2475: }
                   2476:
                   2477: /*
                   2478:  * Calculate the time constant for the requested sampling rate.
                   2479:  */
                   2480: u_int
                   2481: ess_srtotc(rate)
                   2482:        u_int rate;
                   2483: {
                   2484:        u_int tc;
                   2485:
                   2486:        /* The following formulae are from the ESS data sheet. */
                   2487:        if (rate <= 22050)
                   2488:                tc = 128 - 397700L / rate;
                   2489:        else
                   2490:                tc = 256 - 795500L / rate;
                   2491:
                   2492:        return (tc);
                   2493: }
                   2494:
                   2495:
                   2496: /*
                   2497:  * Calculate the filter constant for the reuqested sampling rate.
                   2498:  */
                   2499: u_int
                   2500: ess_srtofc(rate)
                   2501:        u_int rate;
                   2502: {
                   2503:        /*
                   2504:         * The following formula is derived from the information in
                   2505:         * the ES1887 data sheet, based on a roll-off frequency of
                   2506:         * 87%.
                   2507:         */
                   2508:        return (256 - 200279L / rate);
                   2509: }
                   2510:
                   2511:
                   2512: /*
                   2513:  * Return the status of the DSP.
                   2514:  */
                   2515: u_char
                   2516: ess_get_dsp_status(sc)
                   2517:        struct ess_softc *sc;
                   2518: {
                   2519:        return (EREAD1(sc->sc_iot, sc->sc_ioh, ESS_DSP_RW_STATUS));
                   2520: }
                   2521:
                   2522:
                   2523: /*
                   2524:  * Return the read status of the DSP:  1 -> DSP ready for reading
                   2525:  *                                     0 -> DSP not ready for reading
                   2526:  */
                   2527: u_char
                   2528: ess_dsp_read_ready(sc)
                   2529:        struct ess_softc *sc;
                   2530: {
                   2531:        return ((ess_get_dsp_status(sc) & ESS_DSP_READ_READY) ? 1 : 0);
                   2532: }
                   2533:
                   2534:
                   2535: /*
                   2536:  * Return the write status of the DSP: 1 -> DSP ready for writing
                   2537:  *                                     0 -> DSP not ready for writing
                   2538:  */
                   2539: u_char
                   2540: ess_dsp_write_ready(sc)
                   2541:        struct ess_softc *sc;
                   2542: {
                   2543:        return ((ess_get_dsp_status(sc) & ESS_DSP_WRITE_BUSY) ? 0 : 1);
                   2544: }
                   2545:
                   2546:
                   2547: /*
                   2548:  * Read a byte from the DSP.
                   2549:  */
                   2550: int
                   2551: ess_rdsp(sc)
                   2552:        struct ess_softc *sc;
                   2553: {
                   2554:        bus_space_tag_t iot = sc->sc_iot;
                   2555:        bus_space_handle_t ioh = sc->sc_ioh;
                   2556:        int i;
                   2557:
                   2558:        for (i = ESS_READ_TIMEOUT; i > 0; --i) {
                   2559:                if (ess_dsp_read_ready(sc)) {
                   2560:                        i = EREAD1(iot, ioh, ESS_DSP_READ);
                   2561:                        DPRINTFN(8,("ess_rdsp() = 0x%02x\n", i));
                   2562:                        return i;
                   2563:                } else
                   2564:                        delay(10);
                   2565:        }
                   2566:
                   2567:        DPRINTF(("ess_rdsp: timed out\n"));
                   2568:        return (-1);
                   2569: }
                   2570:
                   2571: /*
                   2572:  * Write a byte to the DSP.
                   2573:  */
                   2574: int
                   2575: ess_wdsp(sc, v)
                   2576:        struct ess_softc *sc;
                   2577:        u_char v;
                   2578: {
                   2579:        bus_space_tag_t iot = sc->sc_iot;
                   2580:        bus_space_handle_t ioh = sc->sc_ioh;
                   2581:        int i;
                   2582:
                   2583:        DPRINTFN(8,("ess_wdsp(0x%02x)\n", v));
                   2584:
                   2585:        for (i = ESS_WRITE_TIMEOUT; i > 0; --i) {
                   2586:                if (ess_dsp_write_ready(sc)) {
                   2587:                        EWRITE1(iot, ioh, ESS_DSP_WRITE, v);
                   2588:                        return (0);
                   2589:                } else
                   2590:                        delay(10);
                   2591:        }
                   2592:
                   2593:        DPRINTF(("ess_wdsp(0x%02x): timed out\n", v));
                   2594:        return (-1);
                   2595: }
                   2596:
                   2597: /*
                   2598:  * Write a value to one of the ESS extended registers.
                   2599:  */
                   2600: int
                   2601: ess_write_x_reg(sc, reg, val)
                   2602:        struct ess_softc *sc;
                   2603:        u_char reg;
                   2604:        u_char val;
                   2605: {
                   2606:        int error;
                   2607:
                   2608:        DPRINTFN(2,("ess_write_x_reg: %02x=%02x\n", reg, val));
                   2609:        if ((error = ess_wdsp(sc, reg)) == 0)
                   2610:                error = ess_wdsp(sc, val);
                   2611:
                   2612:        return error;
                   2613: }
                   2614:
                   2615: /*
                   2616:  * Read the value of one of the ESS extended registers.
                   2617:  */
                   2618: u_char
                   2619: ess_read_x_reg(sc, reg)
                   2620:        struct ess_softc *sc;
                   2621:        u_char reg;
                   2622: {
                   2623:        int error;
                   2624:        int val;
                   2625:
                   2626:        if ((error = ess_wdsp(sc, 0xC0)) == 0)
                   2627:                error = ess_wdsp(sc, reg);
                   2628:        if (error)
                   2629:                DPRINTF(("Error reading extended register 0x%02x\n", reg));
                   2630: /* REVISIT: what if an error is returned above? */
                   2631:        val = ess_rdsp(sc);
                   2632:        DPRINTFN(2,("ess_read_x_reg: %02x=%02x\n", reg, val));
                   2633:        return val;
                   2634: }
                   2635:
                   2636: void
                   2637: ess_clear_xreg_bits(sc, reg, mask)
                   2638:        struct ess_softc *sc;
                   2639:        u_char reg;
                   2640:        u_char mask;
                   2641: {
                   2642:        if (ess_write_x_reg(sc, reg, ess_read_x_reg(sc, reg) & ~mask) == -1)
                   2643:                DPRINTF(("Error clearing bits in extended register 0x%02x\n",
                   2644:                         reg));
                   2645: }
                   2646:
                   2647: void
                   2648: ess_set_xreg_bits(sc, reg, mask)
                   2649:        struct ess_softc *sc;
                   2650:        u_char reg;
                   2651:        u_char mask;
                   2652: {
                   2653:        if (ess_write_x_reg(sc, reg, ess_read_x_reg(sc, reg) | mask) == -1)
                   2654:                DPRINTF(("Error setting bits in extended register 0x%02x\n",
                   2655:                         reg));
                   2656: }
                   2657:
                   2658:
                   2659: /*
                   2660:  * Write a value to one of the ESS mixer registers.
                   2661:  */
                   2662: void
                   2663: ess_write_mix_reg(sc, reg, val)
                   2664:        struct ess_softc *sc;
                   2665:        u_char reg;
                   2666:        u_char val;
                   2667: {
                   2668:        bus_space_tag_t iot = sc->sc_iot;
                   2669:        bus_space_handle_t ioh = sc->sc_ioh;
                   2670:        int s;
                   2671:
                   2672:        DPRINTFN(2,("ess_write_mix_reg: %x=%x\n", reg, val));
                   2673:
                   2674:        s = splaudio();
                   2675:        EWRITE1(iot, ioh, ESS_MIX_REG_SELECT, reg);
                   2676:        EWRITE1(iot, ioh, ESS_MIX_REG_DATA, val);
                   2677:        splx(s);
                   2678: }
                   2679:
                   2680: /*
                   2681:  * Read the value of one of the ESS mixer registers.
                   2682:  */
                   2683: u_char
                   2684: ess_read_mix_reg(sc, reg)
                   2685:        struct ess_softc *sc;
                   2686:        u_char reg;
                   2687: {
                   2688:        bus_space_tag_t iot = sc->sc_iot;
                   2689:        bus_space_handle_t ioh = sc->sc_ioh;
                   2690:        int s;
                   2691:        u_char val;
                   2692:
                   2693:        s = splaudio();
                   2694:        EWRITE1(iot, ioh, ESS_MIX_REG_SELECT, reg);
                   2695:        val = EREAD1(iot, ioh, ESS_MIX_REG_DATA);
                   2696:        splx(s);
                   2697:
                   2698:        DPRINTFN(2,("ess_read_mix_reg: %x=%x\n", reg, val));
                   2699:        return val;
                   2700: }
                   2701:
                   2702: void
                   2703: ess_clear_mreg_bits(sc, reg, mask)
                   2704:        struct ess_softc *sc;
                   2705:        u_char reg;
                   2706:        u_char mask;
                   2707: {
                   2708:        ess_write_mix_reg(sc, reg, ess_read_mix_reg(sc, reg) & ~mask);
                   2709: }
                   2710:
                   2711: void
                   2712: ess_set_mreg_bits(sc, reg, mask)
                   2713:        struct ess_softc *sc;
                   2714:        u_char reg;
                   2715:        u_char mask;
                   2716: {
                   2717:        ess_write_mix_reg(sc, reg, ess_read_mix_reg(sc, reg) | mask);
                   2718: }
                   2719:
                   2720: void
                   2721: ess_read_multi_mix_reg(sc, reg, datap, count)
                   2722:        struct ess_softc *sc;
                   2723:        u_char reg;
                   2724:        u_int8_t *datap;
                   2725:        bus_size_t count;
                   2726: {
                   2727:        bus_space_tag_t iot = sc->sc_iot;
                   2728:        bus_space_handle_t ioh = sc->sc_ioh;
                   2729:        int s;
                   2730:
                   2731:        s = splaudio();
                   2732:        EWRITE1(iot, ioh, ESS_MIX_REG_SELECT, reg);
                   2733:        bus_space_read_multi_1(iot, ioh, ESS_MIX_REG_DATA, datap, count);
                   2734:        splx(s);
                   2735: }

CVSweb