[BACK]Return to mavb.c CVS log [TXT][DIR] Up to [local] / sys / arch / sgi / dev

Annotation of sys/arch/sgi/dev/mavb.c, Revision 1.1.1.1

1.1       nbrk        1: /*     $OpenBSD: mavb.c,v 1.7 2007/05/20 14:17:05 miod Exp $   */
                      2:
                      3: /*
                      4:  * Copyright (c) 2005 Mark Kettenis
                      5:  *
                      6:  * Permission to use, copy, modify, and distribute this software for any
                      7:  * purpose with or without fee is hereby granted, provided that the above
                      8:  * copyright notice and this permission notice appear in all copies.
                      9:  *
                     10:  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
                     11:  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
                     12:  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
                     13:  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
                     14:  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
                     15:  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
                     16:  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
                     17:  */
                     18:
                     19: #include <sys/param.h>
                     20: #include <sys/systm.h>
                     21: #include <sys/device.h>
                     22: #include <sys/kernel.h>
                     23: #include <sys/timeout.h>
                     24:
                     25: #include <machine/bus.h>
                     26: #include <machine/intr.h>
                     27: #include <machine/autoconf.h>
                     28:
                     29: #include <sys/audioio.h>
                     30: #include <dev/audio_if.h>
                     31:
                     32: #include <mips64/archtype.h>
                     33:
                     34: #include <sgi/localbus/macebus.h>
                     35: #include <sgi/dev/mavbreg.h>
                     36:
                     37: #include <dev/ic/ad1843reg.h>
                     38:
                     39: #undef MAVB_DEBUG
                     40:
                     41: #ifdef MAVB_DEBUG
                     42: #define DPRINTF(l,x)   do { if (mavb_debug & (l)) printf x; } while (0)
                     43: #define MAVB_DEBUG_INTR                0x0100
                     44: int mavb_debug = ~MAVB_DEBUG_INTR;
                     45: #else
                     46: #define DPRINTF(l,x)   /* nothing */
                     47: #endif
                     48:
                     49: /* Repeat delays for volume buttons.  */
                     50: #define MAVB_VOLUME_BUTTON_REPEAT_DEL1 400     /* 400ms to start repeating */
                     51: #define MAVB_VOLUME_BUTTON_REPEAT_DELN  100    /* 100ms between repeats */
                     52:
                     53: /* XXX We need access to some of the MACE ISA registers.  */
                     54: #define MAVB_ISA_NREGS                         0x20
                     55:
                     56: /*
                     57:  * AD1843 Mixer.
                     58:  */
                     59:
                     60: enum {
                     61:        AD1843_RECORD_CLASS,
                     62:        AD1843_ADC_SOURCE,      /* ADC Source Select */
                     63:        AD1843_ADC_GAIN,        /* ADC Input Gain */
                     64:
                     65:        AD1843_INPUT_CLASS,
                     66:        AD1843_DAC1_GAIN,       /* DAC1 Analog/Digital Gain/Attenuation */
                     67:        AD1843_DAC1_MUTE,       /* DAC1 Analog Mute */
                     68:        AD1843_DAC2_GAIN,       /* DAC2 Mix Gain */
                     69:        AD1843_AUX1_GAIN,       /* Auxilliary 1 Mix Gain */
                     70:        AD1843_AUX2_GAIN,       /* Auxilliary 2 Mix Gain */
                     71:        AD1843_AUX3_GAIN,       /* Auxilliary 3 Mix Gain */
                     72:        AD1843_MIC_GAIN,        /* Microphone Mix Gain */
                     73:        AD1843_MONO_GAIN,       /* Mono Mix Gain */
                     74:        AD1843_DAC2_MUTE,       /* DAC2 Mix Mute */
                     75:        AD1843_AUX1_MUTE,       /* Auxilliary 1 Mix Mute */
                     76:        AD1843_AUX2_MUTE,       /* Auxilliary 2 Mix Mute */
                     77:        AD1843_AUX3_MUTE,       /* Auxilliary 3 Mix Mute */
                     78:        AD1843_MIC_MUTE,        /* Microphone Mix Mute */
                     79:        AD1843_MONO_MUTE,       /* Mono Mix Mute */
                     80:        AD1843_SUM_MUTE,        /* Sum Mute */
                     81:
                     82:        AD1843_OUTPUT_CLASS,
                     83:        AD1843_MNO_MUTE,        /* Mono Output Mute */
                     84:        AD1843_HPO_MUTE         /* Headphone Output Mute */
                     85: };
                     86:
                     87: /* ADC Source Select.  The order matches the hardware bits.  */
                     88: const char *ad1843_source[] = {
                     89:        AudioNline,
                     90:        AudioNmicrophone,
                     91:        AudioNaux "1",
                     92:        AudioNaux "2",
                     93:        AudioNaux "3",
                     94:        AudioNmono,
                     95:        AudioNdac "1",
                     96:        AudioNdac "2"
                     97: };
                     98:
                     99: /* Mix Control.  The order matches the hardware register numbering.  */
                    100: const char *ad1843_input[] = {
                    101:        AudioNdac "2",          /* AD1843_DAC2__TO_MIXER */
                    102:        AudioNaux "1",
                    103:        AudioNaux "2",
                    104:        AudioNaux "3",
                    105:        AudioNmicrophone,
                    106:        AudioNmono              /* AD1843_MISC_SETTINGS */
                    107: };
                    108:
                    109: struct mavb_softc {
                    110:        struct device sc_dev;
                    111:        bus_space_tag_t sc_st;
                    112:        bus_space_handle_t sc_sh;
                    113:        bus_dma_tag_t sc_dmat;
                    114:        bus_dmamap_t sc_dmamap;
                    115:
                    116:        /* XXX We need access to some of the MACE ISA registers.  */
                    117:        bus_space_handle_t sc_isash;
                    118:
                    119: #define MAVB_ISA_RING_SIZE             0x1000
                    120:        caddr_t sc_ring;
                    121:
                    122:        caddr_t sc_start, sc_end;
                    123:        int sc_blksize;
                    124:        void (*sc_intr)(void *);
                    125:        void *sc_intrarg;
                    126:
                    127:        caddr_t sc_get;
                    128:        int sc_count;
                    129:
                    130:        u_long sc_play_rate;
                    131:        u_int sc_play_format;
                    132:
                    133:        struct timeout sc_volume_button_to;
                    134: };
                    135:
                    136: typedef u_long ad1843_addr_t;
                    137:
                    138: u_int16_t ad1843_reg_read(struct mavb_softc *, ad1843_addr_t);
                    139: u_int16_t ad1843_reg_write(struct mavb_softc *, ad1843_addr_t, u_int16_t);
                    140: void ad1843_dump_regs(struct mavb_softc *);
                    141:
                    142: int mavb_match(struct device *, void *, void *);
                    143: void mavb_attach(struct device *, struct device *, void *);
                    144:
                    145: struct cfattach mavb_ca = {
                    146:        sizeof(struct mavb_softc), mavb_match, mavb_attach
                    147: };
                    148:
                    149: struct cfdriver mavb_cd = {
                    150:        NULL, "mavb", DV_DULL
                    151: };
                    152:
                    153: int mavb_open(void *, int);
                    154: void mavb_close(void *);
                    155: int mavb_query_encoding(void *, struct audio_encoding *);
                    156: int mavb_set_params(void *, int, int, struct audio_params *,
                    157:                    struct audio_params *);
                    158: int mavb_round_blocksize(void *hdl, int bs);
                    159: int mavb_halt_output(void *);
                    160: int mavb_halt_input(void *);
                    161: int mavb_getdev(void *, struct audio_device *);
                    162: int mavb_set_port(void *, struct mixer_ctrl *);
                    163: int mavb_get_port(void *, struct mixer_ctrl *);
                    164: int mavb_query_devinfo(void *, struct mixer_devinfo *);
                    165: int mavb_get_props(void *);
                    166: int mavb_trigger_output(void *, void *, void *, int, void (*)(void *),
                    167:                        void *, struct audio_params *);
                    168: int mavb_trigger_input(void *, void *, void *, int, void (*)(void *),
                    169:                       void *, struct audio_params *);
                    170:
                    171: struct audio_hw_if mavb_sa_hw_if = {
                    172:        mavb_open,
                    173:        mavb_close,
                    174:        0,
                    175:        mavb_query_encoding,
                    176:        mavb_set_params,
                    177:        mavb_round_blocksize,
                    178:        0,
                    179:        0,
                    180:        0,
                    181:        0,
                    182:        0,
                    183:        mavb_halt_output,
                    184:        mavb_halt_input,
                    185:        0,
                    186:        mavb_getdev,
                    187:        0,
                    188:        mavb_set_port,
                    189:        mavb_get_port,
                    190:        mavb_query_devinfo,
                    191:        0,
                    192:        0,
                    193:        0,
                    194:        0,
                    195:        mavb_get_props,
                    196:        mavb_trigger_output,
                    197:        mavb_trigger_input
                    198: };
                    199:
                    200: struct audio_device mavb_device = {
                    201:        "A3",
                    202:        "",
                    203:        "mavb"
                    204: };
                    205:
                    206: int
                    207: mavb_open(void *hdl, int flags)
                    208: {
                    209:        return (0);
                    210: }
                    211:
                    212: void
                    213: mavb_close(void *hdl)
                    214: {
                    215: }
                    216:
                    217: int
                    218: mavb_query_encoding(void *hdl, struct audio_encoding *ae)
                    219: {
                    220:        switch (ae->index) {
                    221:        case 0:
                    222:                /* 8-bit Unsigned Linear PCM.  */
                    223:                strlcpy(ae->name, AudioEulinear, sizeof ae->name);
                    224:                ae->encoding = AUDIO_ENCODING_ULINEAR;
                    225:                ae->precision = 8;
                    226:                ae->flags = 0;
                    227:                break;
                    228:        case 1:
                    229:                /* 16-bit Signed Linear PCM.  */
                    230:                strlcpy(ae->name, AudioEslinear_be, sizeof ae->name);
                    231:                ae->encoding = AUDIO_ENCODING_SLINEAR_BE;
                    232:                ae->precision = 16;
                    233:                ae->flags = 0;
                    234:                break;
                    235:        case 2:
                    236:                /* 8-bit mu-Law Companded.  */
                    237:                strlcpy(ae->name, AudioEmulaw, sizeof ae->name);
                    238:                ae->encoding = AUDIO_ENCODING_ULAW;
                    239:                ae->precision = 8;
                    240:                ae->flags = 0;
                    241:                break;
                    242:        case 3:
                    243:                /* 8-bit A-Law Companded.  */
                    244:                strlcpy(ae->name, AudioEalaw, sizeof ae->name);
                    245:                ae->encoding = AUDIO_ENCODING_ALAW;
                    246:                ae->precision = 8;
                    247:                ae->flags = 0;
                    248:                break;
                    249:        default:
                    250:                return (EINVAL);
                    251:        }
                    252:
                    253:        return (0);
                    254: }
                    255:
                    256: /*
                    257:  * For some reason SGI has decided to standardize their sound hardware
                    258:  * interfaces on 24-bit PCM even though the AD1843 codec used in the
                    259:  * Moosehead A/V Board only supports 16-bit and 8-bit formats.
                    260:  * Therefore we must convert everything to 24-bit samples only to have
                    261:  * the MACE hardware convert them back into 16-bit samples again.  To
                    262:  * complicate matters further, the 24-bit samples are embedded 32-bit
                    263:  * integers.  The 8-bit and 16-bit samples are first converted into
                    264:  * 24-bit samples by padding them to the right with zeroes.  Then they
                    265:  * are sign-extended into 32-bit integers.  This conversion is
                    266:  * conveniently done through the software encoding layer of the high
                    267:  * level audio driver by using the functions below.  Conversion of
                    268:  * mu-law and A-law formats is done by the hardware.
                    269:  */
                    270:
                    271: static void
                    272: linear16_to_linear24_be(void *hdl, u_char *p, int cc)
                    273: {
                    274:        u_char *q = p;
                    275:
                    276:        p += cc;
                    277:        q += cc * 2;
                    278:        while ((cc -= 2) >= 0) {
                    279:                q -= 4;
                    280:                q[3] = 0;
                    281:                q[2] = *--p;
                    282:                q[1] = *--p;
                    283:                q[0] = (*p & 0x80) ? 0xff : 0;
                    284:        }
                    285: }
                    286:
                    287: static void
                    288: linear24_to_linear16_be(void *hdl, u_char *p, int cc)
                    289: {
                    290:        u_char *q = p;
                    291:
                    292:        while ((cc -= 4) >= 0) {
                    293:                *q++ = p[1];
                    294:                *q++ = p[2];
                    295:                p += 4;
                    296:        }
                    297: }
                    298:
                    299: static void
                    300: ulinear8_to_ulinear24_be(void *hdl, u_char *p, int cc)
                    301: {
                    302:        u_char *q = p;
                    303:
                    304:        p += cc;
                    305:        q += cc * 4;
                    306:        while (--cc >= 0) {
                    307:                q -= 4;
                    308:                q[3] = 0;
                    309:                q[2] = 0;
                    310:                q[1] = *--p;
                    311:                q[0] = (*p & 0x80) ? 0xff : 0;
                    312:        }
                    313: }
                    314:
                    315: static void
                    316: ulinear24_to_ulinear8_be(void *hdl, u_char *p, int cc)
                    317: {
                    318:        u_char *q = p;
                    319:
                    320:        while ((cc -= 4) >= 0) {
                    321:                *q++ = p[1];
                    322:                p += 4;
                    323:        }
                    324: }
                    325:
                    326: static void
                    327: linear16_to_linear24_be_mts(void *hdl, u_char *p, int cc)
                    328: {
                    329:        u_char *q = p;
                    330:
                    331:        p += cc;
                    332:        q += cc * 4;
                    333:        while ((cc -= 2) >= 0) {
                    334:                q -= 8;
                    335:                q[3] = q[7] = 0;
                    336:                q[2] = q[6] = *--p;
                    337:                q[1] = q[5] = *--p;
                    338:                q[0] = q[4] = (*p & 0x80) ? 0xff : 0;
                    339:        }
                    340: }
                    341:
                    342: static void
                    343: ulinear8_to_ulinear24_be_mts(void *hdl, u_char *p, int cc)
                    344: {
                    345:        u_char *q = p;
                    346:
                    347:        p += cc;
                    348:        q += cc * 8;
                    349:        while (--cc >= 0) {
                    350:                q -= 8;
                    351:                q[3] = q[7] = 0;
                    352:                q[2] = q[6] = 0;
                    353:                q[1] = q[5] = *--p;
                    354:                q[0] = q[4] = (*p & 0x80) ? 0xff : 0;
                    355:        }
                    356: }
                    357:
                    358: static int
                    359: mavb_set_play_rate(struct mavb_softc *sc, u_long sample_rate)
                    360: {
                    361:        if (sample_rate < 4000 || sample_rate > 48000)
                    362:                return (EINVAL);
                    363:
                    364:        if (sc->sc_play_rate != sample_rate) {
                    365:                ad1843_reg_write(sc, AD1843_CLOCK2_SAMPLE_RATE, sample_rate);
                    366:                sc->sc_play_rate = sample_rate;
                    367:        }
                    368:        return (0);
                    369: }
                    370:
                    371: static int
                    372: mavb_set_play_format(struct mavb_softc *sc, u_int encoding)
                    373: {
                    374:        u_int16_t value;
                    375:        u_int format;
                    376:
                    377:        switch(encoding) {
                    378:        case AUDIO_ENCODING_ULINEAR_BE:
                    379:                format = AD1843_PCM8;
                    380:                break;
                    381:        case AUDIO_ENCODING_SLINEAR_BE:
                    382:                format = AD1843_PCM16;
                    383:                break;
                    384:        case AUDIO_ENCODING_ULAW:
                    385:                format = AD1843_ULAW;
                    386:                break;
                    387:        case AUDIO_ENCODING_ALAW:
                    388:                format = AD1843_ALAW;
                    389:                break;
                    390:        default:
                    391:                return (EINVAL);
                    392:        }
                    393:
                    394:        if (sc->sc_play_format != format) {
                    395:                value = ad1843_reg_read(sc, AD1843_SERIAL_INTERFACE);
                    396:                value &= ~AD1843_DA1F_MASK;
                    397:                value |= (format << AD1843_DA1F_SHIFT);
                    398:                ad1843_reg_write(sc, AD1843_SERIAL_INTERFACE, value);
                    399:                sc->sc_play_format = format;
                    400:        }
                    401:        return (0);
                    402: }
                    403:
                    404: int
                    405: mavb_set_params(void *hdl, int setmode, int usemode,
                    406:     struct audio_params *play, struct audio_params *rec)
                    407: {
                    408:        struct mavb_softc *sc = (struct mavb_softc *)hdl;
                    409:        int error;
                    410:
                    411:        DPRINTF(1, ("%s: mavb_set_params: sample=%ld precision=%d "
                    412:            "channels=%d\n", sc->sc_dev.dv_xname, play->sample_rate,
                    413:            play->precision, play->channels));
                    414:
                    415:        if (setmode & AUMODE_PLAY) {
                    416:                switch (play->encoding) {
                    417:                case AUDIO_ENCODING_ULAW:
                    418:                case AUDIO_ENCODING_ALAW:
                    419:                case AUDIO_ENCODING_ULINEAR_BE:
                    420:                        if (play->precision != 8)
                    421:                                return (EINVAL);
                    422:                        switch (play->channels) {
                    423:                        case 1:
                    424:                                play->factor = 8;
                    425:                                play->sw_code = ulinear8_to_ulinear24_be_mts;
                    426:                                break;
                    427:                        case 2:
                    428:                                play->factor = 4;
                    429:                                play->sw_code = ulinear8_to_ulinear24_be;
                    430:                                break;
                    431:                        default:
                    432:                                return (EINVAL);
                    433:                        }
                    434:                        break;
                    435:                case AUDIO_ENCODING_SLINEAR_BE:
                    436:                        if (play->precision == 16) {
                    437:                                switch (play->channels) {
                    438:                                case 1:
                    439:                                        play->factor = 4;
                    440:                                        play->sw_code =
                    441:                                                linear16_to_linear24_be_mts;
                    442:                                        break;
                    443:                                case 2:
                    444:                                        play->factor = 2;
                    445:                                        play->sw_code =
                    446:                                                linear16_to_linear24_be;
                    447:                                        break;
                    448:                                default:
                    449:                                        return (EINVAL);
                    450:                                }
                    451:                        } else {
                    452:                                return (EINVAL);
                    453:                        }
                    454:                        break;
                    455:                default:
                    456:                        return (EINVAL);
                    457:                }
                    458:
                    459:                error = mavb_set_play_rate(sc, play->sample_rate);
                    460:                if (error)
                    461:                        return (error);
                    462:
                    463:                error = mavb_set_play_format(sc, play->encoding);
                    464:                if (error)
                    465:                        return (error);
                    466:        }
                    467:
                    468:        if (setmode & AUMODE_RECORD) {
                    469:                switch (rec->encoding) {
                    470:                case AUDIO_ENCODING_ULAW:
                    471:                case AUDIO_ENCODING_ALAW:
                    472:                case AUDIO_ENCODING_ULINEAR_BE:
                    473:                        if (rec->precision != 8)
                    474:                                return (EINVAL);
                    475:                        rec->factor = 4;
                    476:                        rec->sw_code = ulinear24_to_ulinear8_be;
                    477:                        break;
                    478:                case AUDIO_ENCODING_SLINEAR_BE:
                    479:                        if (rec->precision == 16) {
                    480:                                rec->factor = 2;
                    481:                                rec->sw_code = linear24_to_linear16_be;
                    482:                        } else {
                    483:                                return (EINVAL);
                    484:                        }
                    485:                        break;
                    486:                default:
                    487:                        return (EINVAL);
                    488:                }
                    489:        }
                    490:
                    491:        return (0);
                    492: }
                    493:
                    494: int
                    495: mavb_round_blocksize(void *hdl, int bs)
                    496: {
                    497:        /* Block size should be a multiple of 32.  */
                    498:        return (bs + 0x1f) & ~0x1f;
                    499: }
                    500:
                    501: int
                    502: mavb_halt_output(void *hdl)
                    503: {
                    504:        struct mavb_softc *sc = (struct mavb_softc *)hdl;
                    505:
                    506:        DPRINTF(1, ("%s: mavb_halt_output called\n", sc->sc_dev.dv_xname));
                    507:
                    508:        bus_space_write_8(sc->sc_st, sc->sc_sh, MAVB_CHANNEL2_CONTROL, 0);
                    509:        return (0);
                    510: }
                    511:
                    512: int
                    513: mavb_halt_input(void *hdl)
                    514: {
                    515:        return (0);
                    516: }
                    517:
                    518: int
                    519: mavb_getdev(void *hdl, struct audio_device *ret)
                    520: {
                    521:        *ret = mavb_device;
                    522:        return (0);
                    523: }
                    524:
                    525: int
                    526: mavb_set_port(void *hdl, struct mixer_ctrl *mc)
                    527: {
                    528:        struct mavb_softc *sc = (struct mavb_softc *)hdl;
                    529:        u_char left, right;
                    530:        ad1843_addr_t reg;
                    531:        u_int16_t value;
                    532:
                    533:        DPRINTF(1, ("%s: mavb_set_port: dev=%d\n", sc->sc_dev.dv_xname,
                    534:            mc->dev));
                    535:
                    536:        switch (mc->dev) {
                    537:        case AD1843_ADC_SOURCE:
                    538:                value = ad1843_reg_read(sc, AD1843_ADC_SOURCE_GAIN);
                    539:                value &= ~(AD1843_LSS_MASK | AD1843_RSS_MASK);
                    540:                value |= ((mc->un.ord << AD1843_LSS_SHIFT) & AD1843_LSS_MASK);
                    541:                value |= ((mc->un.ord << AD1843_RSS_SHIFT) & AD1843_RSS_MASK);
                    542:                ad1843_reg_write(sc, AD1843_ADC_SOURCE_GAIN, value);
                    543:                break;
                    544:        case AD1843_ADC_GAIN:
                    545:                left = mc->un.value.level[AUDIO_MIXER_LEVEL_LEFT];
                    546:                right = mc->un.value.level[AUDIO_MIXER_LEVEL_RIGHT];
                    547:                value = ad1843_reg_read(sc, AD1843_ADC_SOURCE_GAIN);
                    548:                value &= ~(AD1843_LIG_MASK | AD1843_RIG_MASK);
                    549:                value |= ((left >> 4) << AD1843_LIG_SHIFT);
                    550:                value |= ((right >> 4) << AD1843_RIG_SHIFT);
                    551:                ad1843_reg_write(sc, AD1843_ADC_SOURCE_GAIN, value);
                    552:                break;
                    553:
                    554:        case AD1843_DAC1_GAIN:
                    555:                left = AUDIO_MAX_GAIN -
                    556:                    mc->un.value.level[AUDIO_MIXER_LEVEL_LEFT];
                    557:                right = AUDIO_MAX_GAIN -
                    558:                     mc->un.value.level[AUDIO_MIXER_LEVEL_RIGHT];
                    559:                value = ad1843_reg_read(sc, AD1843_DAC1_ANALOG_GAIN);
                    560:                value &= ~(AD1843_LDA1G_MASK | AD1843_RDA1G_MASK);
                    561:                value |= ((left >> 2) << AD1843_LDA1G_SHIFT);
                    562:                value |= ((right >> 2) << AD1843_RDA1G_SHIFT);
                    563:                ad1843_reg_write(sc, AD1843_DAC1_ANALOG_GAIN, value);
                    564:                break;
                    565:        case AD1843_DAC1_MUTE:
                    566:                value = ad1843_reg_read(sc, AD1843_DAC1_ANALOG_GAIN);
                    567:                if (mc->un.ord == 0)
                    568:                        value &= ~(AD1843_LDA1GM | AD1843_RDA1GM);
                    569:                else
                    570:                        value |= (AD1843_LDA1GM | AD1843_RDA1GM);
                    571:                ad1843_reg_write(sc, AD1843_DAC1_ANALOG_GAIN, value);
                    572:                break;
                    573:
                    574:        case AD1843_DAC2_GAIN:
                    575:        case AD1843_AUX1_GAIN:
                    576:        case AD1843_AUX2_GAIN:
                    577:        case AD1843_AUX3_GAIN:
                    578:        case AD1843_MIC_GAIN:
                    579:                left = AUDIO_MAX_GAIN -
                    580:                    mc->un.value.level[AUDIO_MIXER_LEVEL_LEFT];
                    581:                right = AUDIO_MAX_GAIN -
                    582:                     mc->un.value.level[AUDIO_MIXER_LEVEL_RIGHT];
                    583:                reg = AD1843_DAC2_TO_MIXER + mc->dev - AD1843_DAC2_GAIN;
                    584:                value = ad1843_reg_read(sc, reg);
                    585:                value &= ~(AD1843_LD2M_MASK | AD1843_RD2M_MASK);
                    586:                value |= ((left >> 3) << AD1843_LD2M_SHIFT);
                    587:                value |= ((right >> 3) << AD1843_RD2M_SHIFT);
                    588:                ad1843_reg_write(sc, reg, value);
                    589:                break;
                    590:        case AD1843_MONO_GAIN:
                    591:                left = AUDIO_MAX_GAIN -
                    592:                    mc->un.value.level[AUDIO_MIXER_LEVEL_MONO];
                    593:                value = ad1843_reg_read(sc, AD1843_MISC_SETTINGS);
                    594:                value &= ~AD1843_MNM_MASK;
                    595:                value |= ((left >> 3) << AD1843_MNM_SHIFT);
                    596:                ad1843_reg_write(sc, AD1843_MISC_SETTINGS, value);
                    597:                break;
                    598:        case AD1843_DAC2_MUTE:
                    599:        case AD1843_AUX1_MUTE:
                    600:        case AD1843_AUX2_MUTE:
                    601:        case AD1843_AUX3_MUTE:
                    602:        case AD1843_MIC_MUTE:
                    603:        case AD1843_MONO_MUTE:  /* matches left channel */
                    604:                reg = AD1843_DAC2_TO_MIXER + mc->dev - AD1843_DAC2_MUTE;
                    605:                value = ad1843_reg_read(sc, reg);
                    606:                if (mc->un.ord == 0)
                    607:                        value &= ~(AD1843_LD2MM | AD1843_RD2MM);
                    608:                else
                    609:                        value |= (AD1843_LD2MM | AD1843_RD2MM);
                    610:                ad1843_reg_write(sc, reg, value);
                    611:                break;
                    612:
                    613:        case AD1843_SUM_MUTE:
                    614:                value = ad1843_reg_read(sc, AD1843_MISC_SETTINGS);
                    615:                if (mc->un.ord == 0)
                    616:                        value &= ~AD1843_SUMM;
                    617:                else
                    618:                        value |= AD1843_SUMM;
                    619:                ad1843_reg_write(sc, AD1843_MISC_SETTINGS, value);
                    620:                break;
                    621:
                    622:        case AD1843_MNO_MUTE:
                    623:                value = ad1843_reg_read(sc, AD1843_MISC_SETTINGS);
                    624:                if (mc->un.ord == 0)
                    625:                        value &= ~AD1843_MNOM;
                    626:                else
                    627:                        value |= AD1843_MNOM;
                    628:                ad1843_reg_write(sc, AD1843_MISC_SETTINGS, value);
                    629:                break;
                    630:
                    631:        case AD1843_HPO_MUTE:
                    632:                value = ad1843_reg_read(sc, AD1843_MISC_SETTINGS);
                    633:                if (mc->un.ord == 0)
                    634:                        value &= ~AD1843_HPOM;
                    635:                else
                    636:                        value |= AD1843_HPOM;
                    637:                ad1843_reg_write(sc, AD1843_MISC_SETTINGS, value);
                    638:                value = ad1843_reg_read(sc, AD1843_MISC_SETTINGS);
                    639:                break;
                    640:
                    641:        default:
                    642:                return (EINVAL);
                    643:        }
                    644:
                    645:        return (0);
                    646: }
                    647:
                    648: int
                    649: mavb_get_port(void *hdl, struct mixer_ctrl *mc)
                    650: {
                    651:        struct mavb_softc *sc = (struct mavb_softc *)hdl;
                    652:        u_char left, right;
                    653:        ad1843_addr_t reg;
                    654:        u_int16_t value;
                    655:
                    656:        DPRINTF(1, ("%s: mavb_get_port: dev=%d\n", sc->sc_dev.dv_xname,
                    657:            mc->dev));
                    658:
                    659:        switch (mc->dev) {
                    660:        case AD1843_ADC_SOURCE:
                    661:                value = ad1843_reg_read(sc, AD1843_ADC_SOURCE_GAIN);
                    662:                mc->un.ord = (value & AD1843_LSS_MASK) >> AD1843_LSS_SHIFT;
                    663:                break;
                    664:        case AD1843_ADC_GAIN:
                    665:                value = ad1843_reg_read(sc, AD1843_ADC_SOURCE_GAIN);
                    666:                left = (value & AD1843_LIG_MASK) >> AD1843_LIG_SHIFT;
                    667:                right = (value & AD1843_RIG_MASK) >> AD1843_RIG_SHIFT;
                    668:                mc->un.value.level[AUDIO_MIXER_LEVEL_LEFT] =
                    669:                    (left << 4) | left;
                    670:                mc->un.value.level[AUDIO_MIXER_LEVEL_RIGHT] =
                    671:                    (right << 2) | right;
                    672:                break;
                    673:
                    674:        case AD1843_DAC1_GAIN:
                    675:                value = ad1843_reg_read(sc, AD1843_DAC1_ANALOG_GAIN);
                    676:                left = (value & AD1843_LDA1G_MASK) >> AD1843_LDA1G_SHIFT;
                    677:                right = (value & AD1843_RDA1G_MASK) >> AD1843_RDA1G_SHIFT;
                    678:                mc->un.value.level[AUDIO_MIXER_LEVEL_LEFT] =
                    679:                    AUDIO_MAX_GAIN - (left << 2);
                    680:                mc->un.value.level[AUDIO_MIXER_LEVEL_RIGHT] =
                    681:                    AUDIO_MAX_GAIN - (right << 2);
                    682:                break;
                    683:        case AD1843_DAC1_MUTE:
                    684:                value = ad1843_reg_read(sc, AD1843_DAC1_ANALOG_GAIN);
                    685:                mc->un.ord = (value & AD1843_LDA1GM) ? 1 : 0;
                    686:                break;
                    687:
                    688:        case AD1843_DAC2_GAIN:
                    689:        case AD1843_AUX1_GAIN:
                    690:        case AD1843_AUX2_GAIN:
                    691:        case AD1843_AUX3_GAIN:
                    692:        case AD1843_MIC_GAIN:
                    693:                reg = AD1843_DAC2_TO_MIXER + mc->dev - AD1843_DAC2_GAIN;
                    694:                value = ad1843_reg_read(sc, reg);
                    695:                left = (value & AD1843_LD2M_MASK) >> AD1843_LD2M_SHIFT;
                    696:                right = (value & AD1843_RD2M_MASK) >> AD1843_RD2M_SHIFT;
                    697:                mc->un.value.level[AUDIO_MIXER_LEVEL_LEFT] =
                    698:                    AUDIO_MAX_GAIN - (left << 3);
                    699:                mc->un.value.level[AUDIO_MIXER_LEVEL_RIGHT] =
                    700:                    AUDIO_MAX_GAIN - (right << 3);
                    701:                break;
                    702:        case AD1843_MONO_GAIN:
                    703:                if (mc->un.value.num_channels != 1)
                    704:                        return (EINVAL);
                    705:
                    706:                value = ad1843_reg_read(sc, AD1843_MISC_SETTINGS);
                    707:                left = (value & AD1843_MNM_MASK) >> AD1843_MNM_SHIFT;
                    708:                mc->un.value.level[AUDIO_MIXER_LEVEL_MONO] =
                    709:                    AUDIO_MAX_GAIN - (left << 3);
                    710:                break;
                    711:        case AD1843_DAC2_MUTE:
                    712:        case AD1843_AUX1_MUTE:
                    713:        case AD1843_AUX2_MUTE:
                    714:        case AD1843_AUX3_MUTE:
                    715:        case AD1843_MIC_MUTE:
                    716:        case AD1843_MONO_MUTE:  /* matches left channel */
                    717:                reg = AD1843_DAC2_TO_MIXER + mc->dev - AD1843_DAC2_MUTE;
                    718:                value = ad1843_reg_read(sc, reg);
                    719:                mc->un.ord = (value & AD1843_LD2MM) ? 1 : 0;
                    720:                break;
                    721:
                    722:        case AD1843_SUM_MUTE:
                    723:                value = ad1843_reg_read(sc, AD1843_MISC_SETTINGS);
                    724:                mc->un.ord = (value & AD1843_SUMM) ? 1 : 0;
                    725:                break;
                    726:
                    727:        case AD1843_MNO_MUTE:
                    728:                value = ad1843_reg_read(sc, AD1843_MISC_SETTINGS);
                    729:                mc->un.ord = (value & AD1843_MNOM) ? 1 : 0;
                    730:                break;
                    731:
                    732:        case AD1843_HPO_MUTE:
                    733:                value = ad1843_reg_read(sc, AD1843_MISC_SETTINGS);
                    734:                mc->un.ord = (value & AD1843_HPOM) ? 1 : 0;
                    735:                break;
                    736:
                    737:        default:
                    738:                return (EINVAL);
                    739:        }
                    740:
                    741:        return (0);
                    742: }
                    743:
                    744: int
                    745: mavb_query_devinfo(void *hdl, struct mixer_devinfo *di)
                    746: {
                    747:        int i;
                    748:
                    749:        di->prev = di->next = AUDIO_MIXER_LAST;
                    750:
                    751:        switch (di->index) {
                    752:        case AD1843_RECORD_CLASS:
                    753:                di->type = AUDIO_MIXER_CLASS;
                    754:                di->mixer_class = AD1843_RECORD_CLASS;
                    755:                strlcpy(di->label.name, AudioCrecord, sizeof di->label.name);
                    756:                break;
                    757:
                    758:        case AD1843_ADC_SOURCE:
                    759:                di->type = AUDIO_MIXER_ENUM;
                    760:                di->mixer_class = AD1843_RECORD_CLASS;
                    761:                di->next = AD1843_ADC_GAIN;
                    762:                strlcpy(di->label.name, AudioNsource, sizeof di->label.name);
                    763:                di->un.e.num_mem =
                    764:                        sizeof ad1843_source / sizeof ad1843_source[1];
                    765:                for (i = 0; i < di->un.e.num_mem; i++) {
                    766:                        strlcpy(di->un.e.member[i].label.name,
                    767:                             ad1843_source[i],
                    768:                            sizeof di->un.e.member[0].label.name);
                    769:                        di->un.e.member[i].ord = i;
                    770:                }
                    771:                break;
                    772:        case AD1843_ADC_GAIN:
                    773:                di->type = AUDIO_MIXER_VALUE;
                    774:                di->mixer_class = AD1843_RECORD_CLASS;
                    775:                di->prev = AD1843_ADC_SOURCE;
                    776:                strlcpy(di->label.name, AudioNvolume, sizeof di->label.name);
                    777:                di->un.v.num_channels = 2;
                    778:                strlcpy(di->un.v.units.name, AudioNvolume,
                    779:                    sizeof di->un.v.units.name);
                    780:                break;
                    781:
                    782:        case AD1843_INPUT_CLASS:
                    783:                di->type = AUDIO_MIXER_CLASS;
                    784:                di->mixer_class = AD1843_INPUT_CLASS;
                    785:                strlcpy(di->label.name, AudioCinputs, sizeof di->label.name);
                    786:                break;
                    787:
                    788:        case AD1843_DAC1_GAIN:
                    789:                di->type = AUDIO_MIXER_VALUE;
                    790:                di->mixer_class = AD1843_INPUT_CLASS;
                    791:                di->next = AD1843_DAC1_MUTE;
                    792:                strlcpy(di->label.name, AudioNdac "1", sizeof di->label.name);
                    793:                di->un.v.num_channels = 2;
                    794:                strlcpy(di->un.v.units.name, AudioNvolume,
                    795:                    sizeof di->un.v.units.name);
                    796:                break;
                    797:        case AD1843_DAC1_MUTE:
                    798:                di->type = AUDIO_MIXER_ENUM;
                    799:                di->mixer_class = AD1843_INPUT_CLASS;
                    800:                di->prev = AD1843_DAC1_GAIN;
                    801:                strlcpy(di->label.name, AudioNmute, sizeof di->label.name);
                    802:                di->un.e.num_mem = 2;
                    803:                strlcpy(di->un.e.member[0].label.name, AudioNoff,
                    804:                    sizeof di->un.e.member[0].label.name);
                    805:                di->un.e.member[0].ord = 0;
                    806:                strlcpy(di->un.e.member[1].label.name, AudioNon,
                    807:                    sizeof di->un.e.member[1].label.name);
                    808:                di->un.e.member[1].ord = 1;
                    809:                break;
                    810:
                    811:        case AD1843_DAC2_GAIN:
                    812:        case AD1843_AUX1_GAIN:
                    813:        case AD1843_AUX2_GAIN:
                    814:        case AD1843_AUX3_GAIN:
                    815:        case AD1843_MIC_GAIN:
                    816:        case AD1843_MONO_GAIN:
                    817:                di->type = AUDIO_MIXER_VALUE;
                    818:                di->mixer_class = AD1843_INPUT_CLASS;
                    819:                di->next = di->index + AD1843_DAC2_MUTE - AD1843_DAC2_GAIN;
                    820:                strlcpy(di->label.name,
                    821:                     ad1843_input[di->index - AD1843_DAC2_GAIN],
                    822:                    sizeof di->label.name);
                    823:                if (di->index == AD1843_MONO_GAIN)
                    824:                        di->un.v.num_channels = 1;
                    825:                else
                    826:                        di->un.v.num_channels = 2;
                    827:                strlcpy(di->un.v.units.name, AudioNvolume,
                    828:                    sizeof di->un.v.units.name);
                    829:                break;
                    830:        case AD1843_DAC2_MUTE:
                    831:        case AD1843_AUX1_MUTE:
                    832:        case AD1843_AUX2_MUTE:
                    833:        case AD1843_AUX3_MUTE:
                    834:        case AD1843_MIC_MUTE:
                    835:        case AD1843_MONO_MUTE:
                    836:                di->type = AUDIO_MIXER_ENUM;
                    837:                di->mixer_class = AD1843_INPUT_CLASS;
                    838:                di->prev = di->index + AD1843_DAC2_GAIN - AD1843_DAC2_MUTE;
                    839:                strlcpy(di->label.name, AudioNmute, sizeof di->label.name);
                    840:                di->un.e.num_mem = 2;
                    841:                strlcpy(di->un.e.member[0].label.name, AudioNoff,
                    842:                    sizeof di->un.e.member[0].label.name);
                    843:                di->un.e.member[0].ord = 0;
                    844:                strlcpy(di->un.e.member[1].label.name, AudioNon,
                    845:                    sizeof di->un.e.member[1].label.name);
                    846:                di->un.e.member[1].ord = 1;
                    847:                break;
                    848:
                    849:        case AD1843_SUM_MUTE:
                    850:                di->type = AUDIO_MIXER_ENUM;
                    851:                di->mixer_class = AD1843_INPUT_CLASS;
                    852:                strlcpy(di->label.name, "sum." AudioNmute,
                    853:                    sizeof di->label.name);
                    854:                di->un.e.num_mem = 2;
                    855:                strlcpy(di->un.e.member[0].label.name, AudioNoff,
                    856:                    sizeof di->un.e.member[0].label.name);
                    857:                di->un.e.member[0].ord = 0;
                    858:                strlcpy(di->un.e.member[1].label.name, AudioNon,
                    859:                    sizeof di->un.e.member[1].label.name);
                    860:                di->un.e.member[1].ord = 1;
                    861:                break;
                    862:
                    863:        case AD1843_OUTPUT_CLASS:
                    864:                di->type = AUDIO_MIXER_CLASS;
                    865:                di->mixer_class = AD1843_OUTPUT_CLASS;
                    866:                strlcpy(di->label.name, AudioCoutputs, sizeof di->label.name);
                    867:                break;
                    868:
                    869:        case AD1843_MNO_MUTE:
                    870:                di->type = AUDIO_MIXER_ENUM;
                    871:                di->mixer_class = AD1843_OUTPUT_CLASS;
                    872:                strlcpy(di->label.name, AudioNmono "." AudioNmute,
                    873:                    sizeof di->label.name);
                    874:                di->un.e.num_mem = 2;
                    875:                strlcpy(di->un.e.member[0].label.name, AudioNoff,
                    876:                    sizeof di->un.e.member[0].label.name);
                    877:                di->un.e.member[0].ord = 0;
                    878:                strlcpy(di->un.e.member[1].label.name, AudioNon,
                    879:                    sizeof di->un.e.member[1].label.name);
                    880:                di->un.e.member[1].ord = 1;
                    881:                break;
                    882:
                    883:        case AD1843_HPO_MUTE:
                    884:                di->type = AUDIO_MIXER_ENUM;
                    885:                di->mixer_class = AD1843_OUTPUT_CLASS;
                    886:                strlcpy(di->label.name, AudioNheadphone "." AudioNmute,
                    887:                    sizeof di->label.name);
                    888:                di->un.e.num_mem = 2;
                    889:                strlcpy(di->un.e.member[0].label.name, AudioNoff,
                    890:                    sizeof di->un.e.member[0].label.name);
                    891:                di->un.e.member[0].ord = 0;
                    892:                strlcpy(di->un.e.member[1].label.name, AudioNon,
                    893:                    sizeof di->un.e.member[1].label.name);
                    894:                di->un.e.member[1].ord = 1;
                    895:                break;
                    896:
                    897:        default:
                    898:                return (EINVAL);
                    899:        }
                    900:
                    901:        return (0);
                    902: }
                    903:
                    904: int
                    905: mavb_get_props(void *hdl)
                    906: {
                    907:        return (AUDIO_PROP_FULLDUPLEX | AUDIO_PROP_INDEPENDENT);
                    908: }
                    909:
                    910: static void
                    911: mavb_dma_output(struct mavb_softc *sc)
                    912: {
                    913:        bus_space_tag_t st = sc->sc_st;
                    914:        bus_space_handle_t sh = sc->sc_sh;
                    915:        u_int64_t write_ptr;
                    916:        u_int64_t depth;
                    917:        caddr_t src, dst;
                    918:        int count;
                    919:
                    920:        write_ptr = bus_space_read_8(st, sh, MAVB_CHANNEL2_WRITE_PTR);
                    921:        depth = bus_space_read_8(st, sh, MAVB_CHANNEL2_DEPTH);
                    922:
                    923:        dst = sc->sc_ring + write_ptr;
                    924:        src = sc->sc_get;
                    925:
                    926:        count = (MAVB_ISA_RING_SIZE - depth - 32);
                    927:        while (--count >= 0) {
                    928:                *dst++ = *src++;
                    929:                if (dst >= sc->sc_ring + MAVB_ISA_RING_SIZE)
                    930:                        dst = sc->sc_ring;
                    931:                if (src >= sc->sc_end)
                    932:                        src = sc->sc_start;
                    933:                if (++sc->sc_count >= sc->sc_blksize) {
                    934:                        if (sc->sc_intr)
                    935:                                sc->sc_intr(sc->sc_intrarg);
                    936:                        sc->sc_count = 0;
                    937:                }
                    938:        }
                    939:
                    940:        write_ptr = dst - sc->sc_ring;
                    941:        bus_space_write_8(st, sh, MAVB_CHANNEL2_WRITE_PTR, write_ptr);
                    942:        sc->sc_get = src;
                    943: }
                    944:
                    945: int
                    946: mavb_trigger_output(void *hdl, void *start, void *end, int blksize,
                    947:                    void (*intr)(void *), void *intrarg,
                    948:                    struct audio_params *param)
                    949: {
                    950:        struct mavb_softc *sc = (struct mavb_softc *)hdl;
                    951:
                    952:        DPRINTF(1, ("%s: mavb_trigger_output: start=%p end=%p "
                    953:            "blksize=%d intr=%p(%p)\n", sc->sc_dev.dv_xname,
                    954:            start, end, blksize, intr, intrarg));
                    955:
                    956:        sc->sc_blksize = blksize;
                    957:        sc->sc_intr = intr;
                    958:        sc->sc_intrarg = intrarg;
                    959:
                    960:        sc->sc_start = sc->sc_get = start;
                    961:        sc->sc_end = end;
                    962:
                    963:        sc->sc_count = 0;
                    964:
                    965:        bus_space_write_8(sc->sc_st, sc->sc_sh, MAVB_CHANNEL2_CONTROL,
                    966:            MAVB_CHANNEL_RESET);
                    967:        delay(1000);
                    968:        bus_space_write_8(sc->sc_st, sc->sc_sh, MAVB_CHANNEL2_CONTROL, 0);
                    969:
                    970:        mavb_dma_output(sc);
                    971:
                    972:        bus_space_write_8(sc->sc_st, sc->sc_sh, MAVB_CHANNEL2_CONTROL,
                    973:            MAVB_CHANNEL_DMA_ENABLE | MAVB_CHANNEL_INT_50);
                    974:        return (0);
                    975: }
                    976:
                    977: int
                    978: mavb_trigger_input(void *hdl, void *start, void *end, int blksize,
                    979:                   void (*intr)(void *), void *intrarg,
                    980:                   struct audio_params *param)
                    981: {
                    982:        return (0);
                    983: }
                    984:
                    985: static void
                    986: mavb_button_repeat(void *hdl)
                    987: {
                    988:        struct mavb_softc *sc = (struct mavb_softc *)hdl;
                    989:        u_int64_t intmask, control;
                    990:        u_int16_t value, left, right;
                    991:
                    992:        DPRINTF(1, ("%s: mavb_repeat called\n", sc->sc_dev.dv_xname));
                    993:
                    994: #define  MAVB_CONTROL_VOLUME_BUTTONS \
                    995:     (MAVB_CONTROL_VOLUME_BUTTON_UP | MAVB_CONTROL_VOLUME_BUTTON_DOWN)
                    996:
                    997:        control = bus_space_read_8(sc->sc_st, sc->sc_sh, MAVB_CONTROL);
                    998:        if (control & MAVB_CONTROL_VOLUME_BUTTONS) {
                    999:                value = ad1843_reg_read(sc, AD1843_DAC1_ANALOG_GAIN);
                   1000:                left = (value & AD1843_LDA1G_MASK) >> AD1843_LDA1G_SHIFT;
                   1001:                right = (value & AD1843_RDA1G_MASK) >> AD1843_RDA1G_SHIFT;
                   1002:                if (control & MAVB_CONTROL_VOLUME_BUTTON_UP) {
                   1003:                        control &= ~MAVB_CONTROL_VOLUME_BUTTON_UP;
                   1004:                        if (left > 0)
                   1005:                                left--;         /* attenuation! */
                   1006:                        if (right > 0)
                   1007:                                right--;
                   1008:                }
                   1009:                if (control & MAVB_CONTROL_VOLUME_BUTTON_DOWN) {
                   1010:                        control &= ~MAVB_CONTROL_VOLUME_BUTTON_DOWN;
                   1011:                        if (left < 63)
                   1012:                                left++;
                   1013:                        if (right < 63)
                   1014:                                right++;
                   1015:                }
                   1016:                bus_space_write_8(sc->sc_st, sc->sc_sh, MAVB_CONTROL, control);
                   1017:
                   1018:                value &= ~(AD1843_LDA1G_MASK | AD1843_RDA1G_MASK);
                   1019:                value |= (left << AD1843_LDA1G_SHIFT);
                   1020:                value |= (right << AD1843_RDA1G_SHIFT);
                   1021:                ad1843_reg_write(sc, AD1843_DAC1_ANALOG_GAIN, value);
                   1022:
                   1023:                timeout_add(&sc->sc_volume_button_to,
                   1024:                    (hz * MAVB_VOLUME_BUTTON_REPEAT_DELN) / 1000);
                   1025:        } else {
                   1026:                /* Enable volume button interrupts again.  */
                   1027:                intmask = bus_space_read_8(sc->sc_st, sc->sc_isash,
                   1028:                     MACE_ISA_INT_MASK);
                   1029:                bus_space_write_8(sc->sc_st, sc->sc_isash, MACE_ISA_INT_MASK,
                   1030:                     intmask | MACE_ISA_INT_AUDIO_SC);
                   1031:        }
                   1032: }
                   1033:
                   1034: static int
                   1035: mavb_intr(void *arg)
                   1036: {
                   1037:        struct mavb_softc *sc = arg;
                   1038:        u_int64_t intstat, intmask;
                   1039:
                   1040:        intstat = bus_space_read_8(sc->sc_st, sc->sc_isash, MACE_ISA_INT_STAT);
                   1041:        DPRINTF(MAVB_DEBUG_INTR, ("%s: mavb_intr: intstat = 0x%lx\n",
                   1042:             sc->sc_dev.dv_xname, intstat));
                   1043:
                   1044:        if (intstat & MACE_ISA_INT_AUDIO_SC) {
                   1045:                /* Disable volume button interrupts.  */
                   1046:                intmask = bus_space_read_8(sc->sc_st, sc->sc_isash,
                   1047:                     MACE_ISA_INT_MASK);
                   1048:                bus_space_write_8(sc->sc_st, sc->sc_isash, MACE_ISA_INT_MASK,
                   1049:                     intmask & ~MACE_ISA_INT_AUDIO_SC);
                   1050:
                   1051:                timeout_add(&sc->sc_volume_button_to,
                   1052:                    (hz * MAVB_VOLUME_BUTTON_REPEAT_DEL1) / 1000);
                   1053:        }
                   1054:
                   1055:        if (intstat & MACE_ISA_INT_AUDIO_DMA2)
                   1056:                mavb_dma_output(sc);
                   1057:
                   1058:        return 1;
                   1059: }
                   1060:
                   1061: int
                   1062: mavb_match(struct device *parent, void *match, void *aux)
                   1063: {
                   1064:        struct confargs *ca = aux;
                   1065:        bus_space_handle_t ioh;
                   1066:        u_int64_t control;
                   1067:
                   1068:        if (ca->ca_sys != SGI_O2 || strcmp(ca->ca_name, mavb_cd.cd_name))
                   1069:                return (0);
                   1070:
                   1071:        if (bus_space_map(ca->ca_iot, ca->ca_baseaddr, MAVB_NREGS, 0,
                   1072:            &ioh) != 0)
                   1073:                return (0);
                   1074:        control = bus_space_read_8(ca->ca_iot, ioh, MAVB_CONTROL);
                   1075:        bus_space_unmap(ca->ca_iot, ioh, MAVB_NREGS);
                   1076:
                   1077:        return ((control & MAVB_CONTROL_CODEC_PRESENT) != 0);
                   1078: }
                   1079:
                   1080: void
                   1081: mavb_attach(struct device *parent, struct device *self, void *aux)
                   1082: {
                   1083:        struct mavb_softc *sc = (void *)self;
                   1084:        struct confargs *ca = aux;
                   1085:        bus_dma_segment_t seg;
                   1086:        u_int16_t value;
                   1087:        int rseg;
                   1088:
                   1089:        sc->sc_st = ca->ca_iot;
                   1090:        if (bus_space_map(sc->sc_st, ca->ca_baseaddr, MAVB_NREGS, 0,
                   1091:            &sc->sc_sh) != 0) {
                   1092:                printf(": can't map i/o space\n");
                   1093:                return;
                   1094:        }
                   1095:
                   1096:        /* XXX We need access to some of the MACE ISA registers.  */
                   1097:        extern bus_space_handle_t mace_h;
                   1098:        bus_space_subregion(sc->sc_st, mace_h, 0, MAVB_ISA_NREGS,
                   1099:            &sc->sc_isash);
                   1100:
                   1101:        /* Set up DMA structures.  */
                   1102:        sc->sc_dmat = ca->ca_dmat;
                   1103:        if (bus_dmamap_create(sc->sc_dmat, 4 * MAVB_ISA_RING_SIZE, 1,
                   1104:            4 * MAVB_ISA_RING_SIZE, 0, 0, &sc->sc_dmamap)) {
                   1105:                printf(": can't create MACE ISA DMA map\n");
                   1106:                return;
                   1107:        }
                   1108:
                   1109:        if (bus_dmamem_alloc(sc->sc_dmat, 4 * MAVB_ISA_RING_SIZE,
                   1110:            MACE_ISA_RING_ALIGN, 0, &seg, 1, &rseg, BUS_DMA_NOWAIT)) {
                   1111:                printf(": can't allocate ring buffer\n");
                   1112:                return;
                   1113:        }
                   1114:
                   1115:        if (bus_dmamem_map(sc->sc_dmat, &seg, rseg, 4 * MAVB_ISA_RING_SIZE,
                   1116:            &sc->sc_ring, BUS_DMA_COHERENT)) {
                   1117:                printf(": can't map ring buffer\n");
                   1118:                return;
                   1119:        }
                   1120:
                   1121:        if (bus_dmamap_load(sc->sc_dmat, sc->sc_dmamap, sc->sc_ring,
                   1122:            4 * MAVB_ISA_RING_SIZE, NULL, BUS_DMA_NOWAIT)) {
                   1123:                printf(": can't load MACE ISA DMA map\n");
                   1124:                return;
                   1125:        }
                   1126:
                   1127:        sc->sc_ring += MAVB_ISA_RING_SIZE; /* XXX */
                   1128:
                   1129:        bus_space_write_8(sc->sc_st, sc->sc_isash, MACE_ISA_RING_BASE,
                   1130:            sc->sc_dmamap->dm_segs[0].ds_addr);
                   1131:
                   1132:        /* Establish interrupt.  */
                   1133:        BUS_INTR_ESTABLISH(ca, NULL, ca->ca_intr, IST_EDGE, IPL_AUDIO,
                   1134:            mavb_intr, sc, sc->sc_dev.dv_xname);
                   1135:
                   1136:        /* 2. Assert the RESET signal.  */
                   1137:        bus_space_write_8(sc->sc_st, sc->sc_sh, MAVB_CONTROL,
                   1138:            MAVB_CONTROL_RESET);
                   1139:        delay(1);               /* at least 100 ns */
                   1140:
                   1141:        /* 3. Deassert the RESET signal and enter a wait period to
                   1142:               allow the AD1843 internal clocks and the external
                   1143:               crystal oscillator to stabilize.  */
                   1144:        bus_space_write_8(sc->sc_st, sc->sc_sh, MAVB_CONTROL, 0);
                   1145:        delay(800);             /* typically 400 us to 800 us */
                   1146:        if (ad1843_reg_read(sc, AD1843_CODEC_STATUS) & AD1843_INIT) {
                   1147:                printf(": codec not ready\n");
                   1148:                return;
                   1149:        }
                   1150:
                   1151:        /* 4. Put the conversion sources into standby.  */
                   1152:        value = ad1843_reg_read(sc, AD1843_FUNDAMENTAL_SETTINGS);
                   1153:        ad1843_reg_write(sc, AD1843_FUNDAMENTAL_SETTINGS,
                   1154:            value & ~AD1843_PDNI);
                   1155:        delay (500000);         /* approximately 474 ms */
                   1156:        if (ad1843_reg_read(sc, AD1843_CODEC_STATUS) & AD1843_PDNO) {
                   1157:                printf(": can't power up conversion resources\n");
                   1158:                return;
                   1159:        }
                   1160:
                   1161:        /* 5. Power up the clock generators and enable clock output pins.  */
                   1162:        value = ad1843_reg_read(sc, AD1843_FUNDAMENTAL_SETTINGS);
                   1163:        ad1843_reg_write(sc, AD1843_FUNDAMENTAL_SETTINGS, value | AD1843_C2EN);
                   1164:
                   1165:        /* 6. Configure conversion resources while they are in standby.  */
                   1166:        value = ad1843_reg_read(sc, AD1843_CHANNEL_SAMPLE_RATE);
                   1167:        ad1843_reg_write(sc, AD1843_CHANNEL_SAMPLE_RATE,
                   1168:             value | (2 << AD1843_DA1C_SHIFT));
                   1169:
                   1170:        /* 7. Enable conversion resources.  */
                   1171:        value = ad1843_reg_read(sc, AD1843_CHANNEL_POWER_DOWN);
                   1172:        ad1843_reg_write(sc, AD1843_CHANNEL_POWER_DOWN,
                   1173:             value | (AD1843_DA1EN | AD1843_AAMEN));
                   1174:
                   1175:        /* 8. Configure conversion resources while they are enabled.  */
                   1176:        value = ad1843_reg_read(sc, AD1843_DAC1_ANALOG_GAIN);
                   1177:        ad1843_reg_write(sc, AD1843_DAC1_ANALOG_GAIN,
                   1178:             value & ~(AD1843_LDA1GM | AD1843_RDA1GM));
                   1179:        value = ad1843_reg_read(sc, AD1843_DAC1_DIGITAL_GAIN);
                   1180:        ad1843_reg_write(sc, AD1843_DAC1_DIGITAL_GAIN,
                   1181:             value & ~(AD1843_LDA1AM | AD1843_RDA1AM));
                   1182:        value = ad1843_reg_read(sc, AD1843_MISC_SETTINGS);
                   1183:        ad1843_reg_write(sc, AD1843_MISC_SETTINGS,
                   1184:             value & ~(AD1843_HPOM | AD1843_MNOM));
                   1185:
                   1186:        value = ad1843_reg_read(sc, AD1843_CODEC_STATUS);
                   1187:        printf(": AD1843 rev %d\n", (u_int)value & AD1843_REVISION_MASK);
                   1188:
                   1189:        sc->sc_play_rate = 48000;
                   1190:        sc->sc_play_format = AD1843_PCM8;
                   1191:
                   1192:        timeout_set(&sc->sc_volume_button_to, mavb_button_repeat, sc);
                   1193:
                   1194:        audio_attach_mi(&mavb_sa_hw_if, sc, &sc->sc_dev);
                   1195:
                   1196:        return;
                   1197: }
                   1198:
                   1199: u_int16_t
                   1200: ad1843_reg_read(struct mavb_softc *sc, ad1843_addr_t addr)
                   1201: {
                   1202:        bus_space_write_8(sc->sc_st, sc->sc_sh, MAVB_CODEC_CONTROL,
                   1203:             (addr & MAVB_CODEC_ADDRESS_MASK) << MAVB_CODEC_ADDRESS_SHIFT |
                   1204:            MAVB_CODEC_READ);
                   1205:        delay(200);
                   1206:        return bus_space_read_8(sc->sc_st, sc->sc_sh, MAVB_CODEC_STATUS);
                   1207: }
                   1208:
                   1209: u_int16_t
                   1210: ad1843_reg_write(struct mavb_softc *sc, ad1843_addr_t addr, u_int16_t value)
                   1211: {
                   1212:        bus_space_write_8(sc->sc_st, sc->sc_sh, MAVB_CODEC_CONTROL,
                   1213:            (addr & MAVB_CODEC_ADDRESS_MASK) << MAVB_CODEC_ADDRESS_SHIFT |
                   1214:            (value & MAVB_CODEC_WORD_MASK) << MAVB_CODEC_WORD_SHIFT);
                   1215:        delay(200);
                   1216:        return bus_space_read_8(sc->sc_st, sc->sc_sh, MAVB_CODEC_STATUS);
                   1217: }
                   1218:
                   1219: void
                   1220: ad1843_dump_regs(struct mavb_softc *sc)
                   1221: {
                   1222:        u_int16_t addr;
                   1223:
                   1224:        for (addr = 0; addr < AD1843_NREGS; addr++)
                   1225:                printf("%d: 0x%04x\n", addr, ad1843_reg_read(sc, addr));
                   1226: }

CVSweb