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

Annotation of sys/dev/pci/neo.c, Revision 1.1.1.1

1.1       nbrk        1: /*      $OpenBSD: neo.c,v 1.19 2005/08/09 04:10:13 mickey Exp $       */
                      2:
                      3: /*
                      4:  * Copyright (c) 1999 Cameron Grant <gandalf@vilnya.demon.co.uk>
                      5:  * All rights reserved.
                      6:  *
                      7:  * Derived from the public domain Linux driver
                      8:  *
                      9:  * Redistribution and use in source and binary forms, with or without
                     10:  * modification, are permitted provided that the following conditions
                     11:  * are met:
                     12:  * 1. Redistributions of source code must retain the above copyright
                     13:  *    notice, this list of conditions and the following disclaimer.
                     14:  * 2. Redistributions in binary form must reproduce the above copyright
                     15:  *    notice, this list of conditions and the following disclaimer in the
                     16:  *    documentation and/or other materials provided with the distribution.
                     17:  *
                     18:  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
                     19:  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
                     20:  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
                     21:  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
                     22:  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
                     23:  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
                     24:  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
                     25:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
                     26:  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
                     27:  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
                     28:  * SUCH DAMAGE.
                     29:  *
                     30:  * $FreeBSD: src/sys/dev/sound/pci/neomagic.c,v 1.8 2000/03/20 15:30:50 cg Exp $
                     31:  */
                     32:
                     33:
                     34:
                     35: #include <sys/param.h>
                     36: #include <sys/systm.h>
                     37: #include <sys/kernel.h>
                     38: #include <sys/malloc.h>
                     39: #include <sys/device.h>
                     40:
                     41: #include <dev/pci/pcidevs.h>
                     42: #include <dev/pci/pcivar.h>
                     43:
                     44: #include <sys/audioio.h>
                     45: #include <dev/audio_if.h>
                     46: #include <dev/mulaw.h>
                     47: #include <dev/auconv.h>
                     48: #include <dev/ic/ac97.h>
                     49:
                     50: #include <dev/pci/neoreg.h>
                     51:
                     52: /* -------------------------------------------------------------------- */
                     53: /*
                     54:  * As of 04/13/00, public documentation on the Neomagic 256 is not available.
                     55:  * These comments were gleaned by looking at the driver carefully.
                     56:  *
                     57:  * The Neomagic 256 AV/ZX chips provide both video and audio capabilities
                     58:  * on one chip. About 2-6 megabytes of memory are associated with
                     59:  * the chip. Most of this goes to video frame buffers, but some is used for
                     60:  * audio buffering.
                     61:  *
                     62:  * Unlike most PCI audio chips, the Neomagic chip does not rely on DMA.
                     63:  * Instead, the chip allows you to carve two ring buffers out of its
                     64:  * memory. How you carve this and how much you can carve seems to be
                     65:  * voodoo. The algorithm is in nm_init.
                     66:  *
                     67:  * Most Neomagic audio chips use the AC-97 codec interface. However, there
                     68:  * seem to be a select few chips 256AV chips that do not support AC-97.
                     69:  * This driver does not support them but there are rumors that it
                     70:  * might work with wss isa drivers. This might require some playing around
                     71:  * with your BIOS.
                     72:  *
                     73:  * The Neomagic 256 AV/ZX have 2 PCI I/O region descriptors. Both of
                     74:  * them describe a memory region. The frame buffer is the first region
                     75:  * and the register set is the second region.
                     76:  *
                     77:  * The register manipulation logic is taken from the Linux driver,
                     78:  * which is in the public domain.
                     79:  *
                     80:  * The Neomagic is even nice enough to map the AC-97 codec registers into
                     81:  * the register space to allow direct manipulation. Watch out, accessing
                     82:  * AC-97 registers on the Neomagic requires great delicateness, otherwise
                     83:  * the thing will hang the PCI bus, rendering your system frozen.
                     84:  *
                     85:  * For one, it seems the Neomagic status register that reports AC-97
                     86:  * readiness should NOT be polled more often than once each 1ms.
                     87:  *
                     88:  * Also, writes to the AC-97 register space may take over 40us to
                     89:  * complete.
                     90:  *
                     91:  * Unlike many sound engines, the Neomagic does not support (as fas as
                     92:  * we know :) ) the notion of interrupting every n bytes transferred,
                     93:  * unlike many DMA engines.  Instead, it allows you to specify one
                     94:  * location in each ring buffer (called the watermark). When the chip
                     95:  * passes that location while playing, it signals an interrupt.
                     96:  *
                     97:  * The ring buffer size is currently 16k. That is about 100ms of audio
                     98:  * at 44.1khz/stero/16 bit. However, to keep the buffer full, interrupts
                     99:  * are generated more often than that, so 20-40 interrupts per second
                    100:  * should not be unexpected. Increasing BUFFSIZE should help minimize
                    101:  * the glitches due to drivers that spend too much time looping at high
                    102:  * privelege levels as well as the impact of badly written audio
                    103:  * interface clients.
                    104:  *
                    105:  * TO-DO list:
                    106:  *    neo_malloc/neo_free are still seriously broken.
                    107:  *
                    108:  *    Figure out interaction with video stuff (look at Xfree86 driver?)
                    109:  *
                    110:  *    Power management (neoactivate)
                    111:  *
                    112:  *    Fix detection of Neo devices that don't work this driver (see neo_attach)
                    113:  *
                    114:  *    Figure out how to shrink that huge table neo-coeff.h
                    115:  */
                    116:
                    117: #define        NM_BUFFSIZE     16384
                    118:
                    119: #define NM256AV_PCI_ID  0x800510c8
                    120: #define NM256ZX_PCI_ID  0x800610c8
                    121:
                    122: /* device private data */
                    123: struct neo_softc {
                    124:        struct          device dev;
                    125:
                    126:        bus_space_tag_t bufiot;
                    127:        bus_space_handle_t  bufioh;
                    128:
                    129:        bus_space_tag_t regiot;
                    130:        bus_space_handle_t  regioh;
                    131:
                    132:        u_int32_t       type;
                    133:        void            *ih;
                    134:
                    135:        void    (*pintr)(void *);       /* dma completion intr handler */
                    136:        void    *parg;          /* arg for intr() */
                    137:
                    138:        void    (*rintr)(void *);       /* dma completion intr handler */
                    139:        void    *rarg;          /* arg for intr() */
                    140:
                    141:        u_int32_t       ac97_base, ac97_status, ac97_busy;
                    142:        u_int32_t       buftop, pbuf, rbuf, cbuf, acbuf;
                    143:        u_int32_t       playint, recint, misc1int, misc2int;
                    144:        u_int32_t       irsz, badintr;
                    145:
                    146:         u_int32_t       pbufsize;
                    147:         u_int32_t       rbufsize;
                    148:
                    149:        u_int32_t       pblksize;
                    150:        u_int32_t       rblksize;
                    151:
                    152:         u_int32_t       pwmark;
                    153:         u_int32_t       rwmark;
                    154:
                    155:        struct ac97_codec_if *codec_if;
                    156:        struct ac97_host_if host_if;
                    157:
                    158:        void *powerhook;
                    159: };
                    160:
                    161: static struct neo_firmware *nf;
                    162:
                    163: /* -------------------------------------------------------------------- */
                    164:
                    165: /*
                    166:  * prototypes
                    167:  */
                    168:
                    169: static int      nm_waitcd(struct neo_softc *sc);
                    170: static int      nm_loadcoeff(struct neo_softc *sc, int dir, int num);
                    171: static int       nm_init(struct neo_softc *);
                    172:
                    173: int    nmchan_getptr(struct neo_softc *, int);
                    174: /* talk to the card */
                    175: static u_int32_t nm_rd(struct neo_softc *, int, int);
                    176: static void     nm_wr(struct neo_softc *, int, u_int32_t, int);
                    177: static u_int32_t nm_rdbuf(struct neo_softc *, int, int);
                    178: static void     nm_wrbuf(struct neo_softc *, int, u_int32_t, int);
                    179:
                    180: int    neo_match(struct device *, void *, void *);
                    181: void   neo_attach(struct device *, struct device *, void *);
                    182: int    neo_intr(void *);
                    183:
                    184: int    neo_open(void *, int);
                    185: void   neo_close(void *);
                    186: int    neo_query_encoding(void *, struct audio_encoding *);
                    187: int    neo_set_params(void *, int, int, struct audio_params *, struct audio_params *);
                    188: int    neo_round_blocksize(void *, int);
                    189: int    neo_trigger_output(void *, void *, void *, int, void (*)(void *),
                    190:            void *, struct audio_params *);
                    191: int    neo_trigger_input(void *, void *, void *, int, void (*)(void *),
                    192:            void *, struct audio_params *);
                    193: int    neo_halt_output(void *);
                    194: int    neo_halt_input(void *);
                    195: int    neo_getdev(void *, struct audio_device *);
                    196: int    neo_mixer_set_port(void *, mixer_ctrl_t *);
                    197: int    neo_mixer_get_port(void *, mixer_ctrl_t *);
                    198: int     neo_attach_codec(void *sc, struct ac97_codec_if *);
                    199: int    neo_read_codec(void *sc, u_int8_t a, u_int16_t *d);
                    200: int    neo_write_codec(void *sc, u_int8_t a, u_int16_t d);
                    201: void    neo_reset_codec(void *sc);
                    202: enum ac97_host_flags neo_flags_codec(void *sc);
                    203: int    neo_query_devinfo(void *, mixer_devinfo_t *);
                    204: void   *neo_malloc(void *, int, size_t, int, int);
                    205: void   neo_free(void *, void *, int);
                    206: size_t neo_round_buffersize(void *, int, size_t);
                    207: int    neo_get_props(void *);
                    208: void   neo_set_mixer(struct neo_softc *sc, int a, int d);
                    209: void    neo_power(int why, void *arg);
                    210:
                    211:
                    212: struct cfdriver neo_cd = {
                    213:        NULL, "neo", DV_DULL
                    214: };
                    215:
                    216:
                    217: struct cfattach neo_ca = {
                    218:        sizeof(struct neo_softc), neo_match, neo_attach
                    219: };
                    220:
                    221:
                    222: struct audio_device neo_device = {
                    223:        "NeoMagic 256",
                    224:        "",
                    225:        "neo"
                    226: };
                    227:
                    228: #if 0
                    229: static u_int32_t badcards[] = {
                    230:        0x0007103c,
                    231:        0x008f1028,
                    232: };
                    233: #endif
                    234:
                    235: #define NUM_BADCARDS (sizeof(badcards) / sizeof(u_int32_t))
                    236:
                    237: /* The actual rates supported by the card. */
                    238: static int samplerates[9] = {
                    239:        8000,
                    240:        11025,
                    241:        16000,
                    242:        22050,
                    243:        24000,
                    244:        32000,
                    245:        44100,
                    246:        48000,
                    247:        99999999
                    248: };
                    249:
                    250: /* -------------------------------------------------------------------- */
                    251:
                    252: struct audio_hw_if neo_hw_if = {
                    253:        neo_open,
                    254:        neo_close,
                    255:        NULL,
                    256:        neo_query_encoding,
                    257:        neo_set_params,
                    258: #if 1
                    259:        neo_round_blocksize,
                    260: #else
                    261:        NULL,
                    262: #endif
                    263:        NULL,
                    264:        NULL,
                    265:        NULL,
                    266:        NULL,
                    267:        NULL,
                    268:        neo_halt_output,
                    269:        neo_halt_input,
                    270:        NULL,
                    271:        neo_getdev,
                    272:        NULL,
                    273:        neo_mixer_set_port,
                    274:        neo_mixer_get_port,
                    275:        neo_query_devinfo,
                    276:        neo_malloc,
                    277:        neo_free,
                    278:        neo_round_buffersize,
                    279:        0,                              /* neo_mappage, */
                    280:        neo_get_props,
                    281:        neo_trigger_output,
                    282:        neo_trigger_input,
                    283:
                    284: };
                    285:
                    286: /* -------------------------------------------------------------------- */
                    287:
                    288: /* Hardware */
                    289: static u_int32_t
                    290: nm_rd(struct neo_softc *sc, int regno, int size)
                    291: {
                    292:        bus_space_tag_t st = sc->regiot;
                    293:        bus_space_handle_t sh = sc->regioh;
                    294:
                    295:        switch (size) {
                    296:        case 1:
                    297:                return bus_space_read_1(st, sh, regno);
                    298:        case 2:
                    299:                return bus_space_read_2(st, sh, regno);
                    300:        case 4:
                    301:                return bus_space_read_4(st, sh, regno);
                    302:        default:
                    303:                return (0xffffffff);
                    304:        }
                    305: }
                    306:
                    307: static void
                    308: nm_wr(struct neo_softc *sc, int regno, u_int32_t data, int size)
                    309: {
                    310:        bus_space_tag_t st = sc->regiot;
                    311:        bus_space_handle_t sh = sc->regioh;
                    312:
                    313:        switch (size) {
                    314:        case 1:
                    315:                bus_space_write_1(st, sh, regno, data);
                    316:                break;
                    317:        case 2:
                    318:                bus_space_write_2(st, sh, regno, data);
                    319:                break;
                    320:        case 4:
                    321:                bus_space_write_4(st, sh, regno, data);
                    322:                break;
                    323:        }
                    324: }
                    325:
                    326: static u_int32_t
                    327: nm_rdbuf(struct neo_softc *sc, int regno, int size)
                    328: {
                    329:        bus_space_tag_t st = sc->bufiot;
                    330:        bus_space_handle_t sh = sc->bufioh;
                    331:
                    332:        switch (size) {
                    333:        case 1:
                    334:                return bus_space_read_1(st, sh, regno);
                    335:        case 2:
                    336:                return bus_space_read_2(st, sh, regno);
                    337:        case 4:
                    338:                return bus_space_read_4(st, sh, regno);
                    339:        default:
                    340:                return (0xffffffff);
                    341:        }
                    342: }
                    343:
                    344: static void
                    345: nm_wrbuf(struct neo_softc *sc, int regno, u_int32_t data, int size)
                    346: {
                    347:        bus_space_tag_t st = sc->bufiot;
                    348:        bus_space_handle_t sh = sc->bufioh;
                    349:
                    350:        switch (size) {
                    351:        case 1:
                    352:                bus_space_write_1(st, sh, regno, data);
                    353:                break;
                    354:        case 2:
                    355:                bus_space_write_2(st, sh, regno, data);
                    356:                break;
                    357:        case 4:
                    358:                bus_space_write_4(st, sh, regno, data);
                    359:                break;
                    360:        }
                    361: }
                    362:
                    363: /* ac97 codec */
                    364: static int
                    365: nm_waitcd(struct neo_softc *sc)
                    366: {
                    367:        int cnt = 10;
                    368:        int fail = 1;
                    369:
                    370:        while (cnt-- > 0) {
                    371:                if (nm_rd(sc, sc->ac97_status, 2) & sc->ac97_busy)
                    372:                        DELAY(100);
                    373:                else {
                    374:                        fail = 0;
                    375:                        break;
                    376:                }
                    377:        }
                    378:        return (fail);
                    379: }
                    380:
                    381:
                    382: static void
                    383: nm_ackint(struct neo_softc *sc, u_int32_t num)
                    384: {
                    385:        if (sc->type == NM256AV_PCI_ID)
                    386:                nm_wr(sc, NM_INT_REG, num << 1, 2);
                    387:        else if (sc->type == NM256ZX_PCI_ID)
                    388:                nm_wr(sc, NM_INT_REG, num, 4);
                    389: }
                    390:
                    391: static int
                    392: nm_loadcoeff(struct neo_softc *sc, int dir, int num)
                    393: {
                    394:        int ofs, sz, i;
                    395:        u_int32_t addr;
                    396:
                    397:        if (nf == NULL) {
                    398:                size_t buflen;
                    399:                u_char *buf;
                    400:                int error;
                    401:
                    402:                error = loadfirmware("neo-coefficients", &buf, &buflen);
                    403:                if (error)
                    404:                        return (error);
                    405:                nf = (struct neo_firmware *)buf;
                    406:        }
                    407:
                    408:        addr = (dir == AUMODE_PLAY)? 0x01c : 0x21c;
                    409:        if (dir == AUMODE_RECORD)
                    410:                num += 8;
                    411:        sz = nf->coefficientSizes[num];
                    412:        ofs = 0;
                    413:        while (num-- > 0)
                    414:                ofs+= nf->coefficientSizes[num];
                    415:        for (i = 0; i < sz; i++)
                    416:                nm_wrbuf(sc, sc->cbuf + i, nf->coefficients[ofs + i], 1);
                    417:        nm_wr(sc, addr, sc->cbuf, 4);
                    418:        if (dir == AUMODE_PLAY)
                    419:                sz--;
                    420:        nm_wr(sc, addr + 4, sc->cbuf + sz, 4);
                    421:        return (0);
                    422: }
                    423:
                    424: int
                    425: nmchan_getptr(sc, mode)
                    426:         struct neo_softc *sc;
                    427:        int mode;
                    428: {
                    429:        if (mode == AUMODE_PLAY)
                    430:                return (nm_rd(sc, NM_PBUFFER_CURRP, 4) - sc->pbuf);
                    431:        else
                    432:                return (nm_rd(sc, NM_RBUFFER_CURRP, 4) - sc->rbuf);
                    433: }
                    434:
                    435:
                    436: /* The interrupt handler */
                    437: int
                    438: neo_intr(void *p)
                    439: {
                    440:        struct neo_softc *sc = (struct neo_softc *)p;
                    441:        int status, x;
                    442:        int rv = 0;
                    443:
                    444:        status = nm_rd(sc, NM_INT_REG, sc->irsz);
                    445:
                    446:        if (status & sc->playint) {
                    447:                status &= ~sc->playint;
                    448:
                    449:                sc->pwmark += sc->pblksize;
                    450:                sc->pwmark %= sc->pbufsize;
                    451:
                    452:                nm_wr(sc, NM_PBUFFER_WMARK, sc->pbuf + sc->pwmark, 4);
                    453:
                    454:                nm_ackint(sc, sc->playint);
                    455:
                    456:                if (sc->pintr)
                    457:                        (*sc->pintr)(sc->parg);
                    458:
                    459:                rv = 1;
                    460:        }
                    461:        if (status & sc->recint) {
                    462:                status &= ~sc->recint;
                    463:
                    464:                sc->rwmark += sc->rblksize;
                    465:                sc->rwmark %= sc->rbufsize;
                    466:
                    467:                nm_ackint(sc, sc->recint);
                    468:                if (sc->rintr)
                    469:                        (*sc->rintr)(sc->rarg);
                    470:
                    471:                rv = 1;
                    472:        }
                    473:        if (status & sc->misc1int) {
                    474:                status &= ~sc->misc1int;
                    475:                nm_ackint(sc, sc->misc1int);
                    476:                x = nm_rd(sc, 0x400, 1);
                    477:                nm_wr(sc, 0x400, x | 2, 1);
                    478:                printf("%s: misc int 1\n", sc->dev.dv_xname);
                    479:                rv = 1;
                    480:        }
                    481:        if (status & sc->misc2int) {
                    482:                status &= ~sc->misc2int;
                    483:                nm_ackint(sc, sc->misc2int);
                    484:                x = nm_rd(sc, 0x400, 1);
                    485:                nm_wr(sc, 0x400, x & ~2, 1);
                    486:                printf("%s: misc int 2\n", sc->dev.dv_xname);
                    487:                rv = 1;
                    488:        }
                    489:        if (status) {
                    490:                status &= ~sc->misc2int;
                    491:                nm_ackint(sc, sc->misc2int);
                    492:                printf("%s: unknown int\n", sc->dev.dv_xname);
                    493:                rv = 1;
                    494:        }
                    495:
                    496:        return (rv);
                    497: }
                    498:
                    499: /* -------------------------------------------------------------------- */
                    500:
                    501: /*
                    502:  * Probe and attach the card
                    503:  */
                    504:
                    505: static int
                    506: nm_init(struct neo_softc *sc)
                    507: {
                    508:        u_int32_t ofs, i;
                    509:
                    510:        if (sc->type == NM256AV_PCI_ID) {
                    511:                sc->ac97_base = NM_MIXER_OFFSET;
                    512:                sc->ac97_status = NM_MIXER_STATUS_OFFSET;
                    513:                sc->ac97_busy = NM_MIXER_READY_MASK;
                    514:
                    515:                sc->buftop = 2560 * 1024;
                    516:
                    517:                sc->irsz = 2;
                    518:                sc->playint = NM_PLAYBACK_INT;
                    519:                sc->recint = NM_RECORD_INT;
                    520:                sc->misc1int = NM_MISC_INT_1;
                    521:                sc->misc2int = NM_MISC_INT_2;
                    522:        } else if (sc->type == NM256ZX_PCI_ID) {
                    523:                sc->ac97_base = NM_MIXER_OFFSET;
                    524:                sc->ac97_status = NM2_MIXER_STATUS_OFFSET;
                    525:                sc->ac97_busy = NM2_MIXER_READY_MASK;
                    526:
                    527:                sc->buftop = (nm_rd(sc, 0xa0b, 2)? 6144 : 4096) * 1024;
                    528:
                    529:                sc->irsz = 4;
                    530:                sc->playint = NM2_PLAYBACK_INT;
                    531:                sc->recint = NM2_RECORD_INT;
                    532:                sc->misc1int = NM2_MISC_INT_1;
                    533:                sc->misc2int = NM2_MISC_INT_2;
                    534:        } else return -1;
                    535:        sc->badintr = 0;
                    536:        ofs = sc->buftop - 0x0400;
                    537:        sc->buftop -= 0x1400;
                    538:
                    539:        if ((nm_rdbuf(sc, ofs, 4) & NM_SIG_MASK) == NM_SIGNATURE) {
                    540:                i = nm_rdbuf(sc, ofs + 4, 4);
                    541:                if (i != 0 && i != 0xffffffff)
                    542:                        sc->buftop = i;
                    543:        }
                    544:
                    545:        sc->cbuf = sc->buftop - NM_MAX_COEFFICIENT;
                    546:        sc->rbuf = sc->cbuf - NM_BUFFSIZE;
                    547:        sc->pbuf = sc->rbuf - NM_BUFFSIZE;
                    548:        sc->acbuf = sc->pbuf - (NM_TOTAL_COEFF_COUNT * 4);
                    549:
                    550:        nm_wr(sc, 0, 0x11, 1);
                    551:        nm_wr(sc, NM_RECORD_ENABLE_REG, 0, 1);
                    552:        nm_wr(sc, 0x214, 0, 2);
                    553:
                    554:        return 0;
                    555: }
                    556:
                    557:
                    558: void
                    559: neo_attach(parent, self, aux)
                    560:        struct device *parent;
                    561:        struct device *self;
                    562:        void *aux;
                    563: {
                    564:        struct neo_softc *sc = (struct neo_softc *)self;
                    565:        struct pci_attach_args *pa = (struct pci_attach_args *)aux;
                    566:        pci_chipset_tag_t pc = pa->pa_pc;
                    567:        char const *intrstr;
                    568:        pci_intr_handle_t ih;
                    569:        int error;
                    570:
                    571:        sc->type = pa->pa_id;
                    572:
                    573:        /* Map I/O register */
                    574:        if (pci_mapreg_map(pa, PCI_MAPS, PCI_MAPREG_TYPE_MEM, 0,
                    575:                           &sc->bufiot, &sc->bufioh, NULL, NULL, 0)) {
                    576:                printf("\n%s: can't map i/o space\n", sc->dev.dv_xname);
                    577:                return;
                    578:        }
                    579:
                    580:
                    581:        if (pci_mapreg_map(pa, PCI_MAPS + 4, PCI_MAPREG_TYPE_MEM, 0,
                    582:                           &sc->regiot, &sc->regioh, NULL, NULL, 0)) {
                    583:                printf("\n%s: can't map i/o space\n", sc->dev.dv_xname);
                    584:                return;
                    585:        }
                    586:
                    587:        /* Map and establish the interrupt. */
                    588:        if (pci_intr_map(pa, &ih)) {
                    589:                printf("\n%s: couldn't map interrupt\n", sc->dev.dv_xname);
                    590:                return;
                    591:        }
                    592:        intrstr = pci_intr_string(pc, ih);
                    593:        sc->ih = pci_intr_establish(pc, ih, IPL_AUDIO, neo_intr, sc,
                    594:                                       sc->dev.dv_xname);
                    595:
                    596:        if (sc->ih == NULL) {
                    597:                printf("\n%s: couldn't establish interrupt",
                    598:                       sc->dev.dv_xname);
                    599:                if (intrstr != NULL)
                    600:                        printf(" at %s", intrstr);
                    601:                printf("\n");
                    602:                return;
                    603:        }
                    604:        printf(": %s\n", intrstr);
                    605:
                    606:        if ((error = nm_init(sc)) != 0)
                    607:                return;
                    608:
                    609:        sc->host_if.arg = sc;
                    610:
                    611:        sc->host_if.attach = neo_attach_codec;
                    612:        sc->host_if.read   = neo_read_codec;
                    613:        sc->host_if.write  = neo_write_codec;
                    614:        sc->host_if.reset  = neo_reset_codec;
                    615:        sc->host_if.flags  = neo_flags_codec;
                    616:
                    617:        if ((error = ac97_attach(&sc->host_if)) != 0)
                    618:                return;
                    619:
                    620:        sc->powerhook = powerhook_establish(neo_power, sc);
                    621:
                    622:        audio_attach_mi(&neo_hw_if, sc, &sc->dev);
                    623:
                    624:        return;
                    625: }
                    626:
                    627: void
                    628: neo_power(int why, void *addr)
                    629: {
                    630:        struct neo_softc *sc = (struct neo_softc *)addr;
                    631:
                    632:        if (why == PWR_RESUME) {
                    633:                nm_init(sc);
                    634:                (sc->codec_if->vtbl->restore_ports)(sc->codec_if);
                    635:        }
                    636: }
                    637:
                    638:
                    639:
                    640: int
                    641: neo_match(parent, match, aux)
                    642:        struct device *parent;
                    643:        void *match;
                    644:        void *aux;
                    645: {
                    646:        struct pci_attach_args *pa = (struct pci_attach_args *) aux;
                    647: #if 0
                    648:        u_int32_t subdev, badcard;
                    649: #endif
                    650:
                    651:        if (PCI_VENDOR(pa->pa_id) != PCI_VENDOR_NEOMAGIC)
                    652:                return (0);
                    653:
                    654: #if 0
                    655:        subdev = (pci_get_subdevice(dev) << 16) | pci_get_subvendor(dev);
                    656: #endif
                    657:        switch (PCI_PRODUCT(pa->pa_id)) {
                    658:        case PCI_PRODUCT_NEOMAGIC_NM256AV:
                    659: #if 0
                    660:                i = 0;
                    661:                while ((i < NUM_BADCARDS) && (badcards[i] != subdev))
                    662:                        i++;
                    663:                if (i == NUM_BADCARDS)
                    664:                        s = "NeoMagic 256AV";
                    665:                DEB(else)
                    666:                        DEB(device_printf(dev, "this is a non-ac97 NM256AV, not attaching\n"));
                    667:                return (1);
                    668: #endif
                    669:        case PCI_PRODUCT_NEOMAGIC_NM256ZX:
                    670:                return (1);
                    671:        }
                    672:
                    673:        return (0);
                    674: }
                    675:
                    676: int
                    677: neo_read_codec(sc_, a, d)
                    678:         void *sc_;
                    679:        u_int8_t a;
                    680:        u_int16_t *d;
                    681: {
                    682:        struct neo_softc *sc = sc_;
                    683:
                    684:        if (!nm_waitcd(sc)) {
                    685:                *d = nm_rd(sc, sc->ac97_base + a, 2);
                    686:                DELAY(1000);
                    687:                return 0;
                    688:        }
                    689:
                    690:        return (ENXIO);
                    691: }
                    692:
                    693:
                    694: int
                    695: neo_write_codec(sc_, a, d)
                    696:         void *sc_;
                    697:        u_int8_t a;
                    698:        u_int16_t d;
                    699: {
                    700:        struct neo_softc *sc = sc_;
                    701:        int cnt = 3;
                    702:
                    703:        if (!nm_waitcd(sc)) {
                    704:                while (cnt-- > 0) {
                    705:                        nm_wr(sc, sc->ac97_base + a, d, 2);
                    706:                        if (!nm_waitcd(sc)) {
                    707:                                DELAY(1000);
                    708:                                return (0);
                    709:                        }
                    710:                }
                    711:        }
                    712:
                    713:         return (ENXIO);
                    714: }
                    715:
                    716:
                    717: int
                    718: neo_attach_codec(sc_, codec_if)
                    719:        void *sc_;
                    720:        struct ac97_codec_if  *codec_if;
                    721: {
                    722:        struct neo_softc *sc = sc_;
                    723:
                    724:        sc->codec_if = codec_if;
                    725:        return (0);
                    726: }
                    727:
                    728: void
                    729: neo_reset_codec(sc)
                    730:        void *sc;
                    731: {
                    732:        nm_wr(sc, 0x6c0, 0x01, 1);
                    733:        nm_wr(sc, 0x6cc, 0x87, 1);
                    734:        nm_wr(sc, 0x6cc, 0x80, 1);
                    735:        nm_wr(sc, 0x6cc, 0x00, 1);
                    736:
                    737:        return;
                    738: }
                    739:
                    740:
                    741: enum ac97_host_flags
                    742: neo_flags_codec(sc)
                    743:        void *sc;
                    744: {
                    745:        return (AC97_HOST_DONT_READANY);
                    746: }
                    747:
                    748: int
                    749: neo_open(addr, flags)
                    750:        void *addr;
                    751:        int flags;
                    752: {
                    753:        return (0);
                    754: }
                    755:
                    756: /*
                    757:  * Close function is called at splaudio().
                    758:  */
                    759: void
                    760: neo_close(addr)
                    761:        void *addr;
                    762: {
                    763:        struct neo_softc *sc = addr;
                    764:
                    765:        neo_halt_output(sc);
                    766:        neo_halt_input(sc);
                    767:
                    768:        sc->pintr = 0;
                    769:        sc->rintr = 0;
                    770: }
                    771:
                    772: int
                    773: neo_query_encoding(addr, fp)
                    774:        void *addr;
                    775:        struct audio_encoding *fp;
                    776: {
                    777:        switch (fp->index) {
                    778:        case 0:
                    779:                strlcpy(fp->name, AudioEulinear, sizeof fp->name);
                    780:                fp->encoding = AUDIO_ENCODING_ULINEAR;
                    781:                fp->precision = 8;
                    782:                fp->flags = 0;
                    783:                return (0);
                    784:        case 1:
                    785:                strlcpy(fp->name, AudioEmulaw, sizeof fp->name);
                    786:                fp->encoding = AUDIO_ENCODING_ULAW;
                    787:                fp->precision = 8;
                    788:                fp->flags = AUDIO_ENCODINGFLAG_EMULATED;
                    789:                return (0);
                    790:        case 2:
                    791:                strlcpy(fp->name, AudioEalaw, sizeof fp->name);
                    792:                fp->encoding = AUDIO_ENCODING_ALAW;
                    793:                fp->precision = 8;
                    794:                fp->flags = AUDIO_ENCODINGFLAG_EMULATED;
                    795:                return (0);
                    796:        case 3:
                    797:                strlcpy(fp->name, AudioEslinear, sizeof fp->name);
                    798:                fp->encoding = AUDIO_ENCODING_SLINEAR;
                    799:                fp->precision = 8;
                    800:                fp->flags = AUDIO_ENCODINGFLAG_EMULATED;
                    801:                return (0);
                    802:        case 4:
                    803:                strlcpy(fp->name, AudioEslinear_le, sizeof fp->name);
                    804:                fp->encoding = AUDIO_ENCODING_SLINEAR_LE;
                    805:                fp->precision = 16;
                    806:                fp->flags = 0;
                    807:                return (0);
                    808:        case 5:
                    809:                strlcpy(fp->name, AudioEulinear_le, sizeof fp->name);
                    810:                fp->encoding = AUDIO_ENCODING_ULINEAR_LE;
                    811:                fp->precision = 16;
                    812:                fp->flags = AUDIO_ENCODINGFLAG_EMULATED;
                    813:                return (0);
                    814:        case 6:
                    815:                strlcpy(fp->name, AudioEslinear_be, sizeof fp->name);
                    816:                fp->encoding = AUDIO_ENCODING_SLINEAR_BE;
                    817:                fp->precision = 16;
                    818:                fp->flags = AUDIO_ENCODINGFLAG_EMULATED;
                    819:                return (0);
                    820:        case 7:
                    821:                strlcpy(fp->name, AudioEulinear_be, sizeof fp->name);
                    822:                fp->encoding = AUDIO_ENCODING_ULINEAR_BE;
                    823:                fp->precision = 16;
                    824:                fp->flags = AUDIO_ENCODINGFLAG_EMULATED;
                    825:                return (0);
                    826:        default:
                    827:                return (EINVAL);
                    828:        }
                    829: }
                    830:
                    831: /* Todo: don't commit settings to card until we've verified all parameters */
                    832: int
                    833: neo_set_params(addr, setmode, usemode, play, rec)
                    834:        void *addr;
                    835:        int setmode, usemode;
                    836:        struct audio_params *play, *rec;
                    837: {
                    838:        struct neo_softc *sc = addr;
                    839:        u_int32_t base;
                    840:        u_int8_t x;
                    841:        int mode;
                    842:        struct audio_params *p;
                    843:
                    844:        for (mode = AUMODE_RECORD; mode != -1;
                    845:             mode = mode == AUMODE_RECORD ? AUMODE_PLAY : -1) {
                    846:                if ((setmode & mode) == 0)
                    847:                        continue;
                    848:
                    849:                p = mode == AUMODE_PLAY ? play : rec;
                    850:
                    851:                if (p == NULL) continue;
                    852:
                    853:                for (x = 0; x < 8; x++)
                    854:                        if (p->sample_rate < (samplerates[x] + samplerates[x + 1]) / 2)
                    855:                                break;
                    856:
                    857:                if (x == 8) return (EINVAL);
                    858:
                    859:                p->sample_rate = samplerates[x];
                    860:                nm_loadcoeff(sc, mode, x);
                    861:
                    862:                x <<= 4;
                    863:                x &= NM_RATE_MASK;
                    864:                if (p->precision == 16) x |= NM_RATE_BITS_16;
                    865:                if (p->channels == 2) x |= NM_RATE_STEREO;
                    866:
                    867:                base = (mode == AUMODE_PLAY) ?
                    868:                    NM_PLAYBACK_REG_OFFSET : NM_RECORD_REG_OFFSET;
                    869:                nm_wr(sc, base + NM_RATE_REG_OFFSET, x, 1);
                    870:
                    871:                p->factor = 1;
                    872:                p->sw_code = 0;
                    873:                switch (p->encoding) {
                    874:                case AUDIO_ENCODING_SLINEAR_BE:
                    875:                        if (p->precision == 16)
                    876:                                p->sw_code = swap_bytes;
                    877:                        else
                    878:                                p->sw_code = change_sign8;
                    879:                        break;
                    880:                case AUDIO_ENCODING_SLINEAR_LE:
                    881:                        if (p->precision != 16)
                    882:                                p->sw_code = change_sign8;
                    883:                        break;
                    884:                case AUDIO_ENCODING_ULINEAR_BE:
                    885:                        if (p->precision == 16) {
                    886:                                if (mode == AUMODE_PLAY)
                    887:                                        p->sw_code = swap_bytes_change_sign16;
                    888:                                else
                    889:                                        p->sw_code = change_sign16_swap_bytes;
                    890:                        }
                    891:                        break;
                    892:                case AUDIO_ENCODING_ULINEAR_LE:
                    893:                        if (p->precision == 16)
                    894:                                p->sw_code = change_sign16;
                    895:                        break;
                    896:                case AUDIO_ENCODING_ULAW:
                    897:                        if (mode == AUMODE_PLAY) {
                    898:                                p->factor = 2;
                    899:                                p->sw_code = mulaw_to_slinear16;
                    900:                        } else
                    901:                                p->sw_code = ulinear8_to_mulaw;
                    902:                        break;
                    903:                case AUDIO_ENCODING_ALAW:
                    904:                        if (mode == AUMODE_PLAY) {
                    905:                                p->factor = 2;
                    906:                                p->sw_code = alaw_to_slinear16;
                    907:                        } else
                    908:                                p->sw_code = ulinear8_to_alaw;
                    909:                        break;
                    910:                default:
                    911:                        return (EINVAL);
                    912:                }
                    913:        }
                    914:
                    915:
                    916:        return (0);
                    917: }
                    918:
                    919: int
                    920: neo_round_blocksize(addr, blk)
                    921:        void *addr;
                    922:        int blk;
                    923: {
                    924:        return (NM_BUFFSIZE / 2);
                    925: }
                    926:
                    927: int
                    928: neo_trigger_output(addr, start, end, blksize, intr, arg, param)
                    929:        void *addr;
                    930:        void *start, *end;
                    931:        int blksize;
                    932:        void (*intr)(void *);
                    933:        void *arg;
                    934:        struct audio_params *param;
                    935: {
                    936:        struct neo_softc *sc = addr;
                    937:        int ssz;
                    938:
                    939:        sc->pintr = intr;
                    940:        sc->parg = arg;
                    941:
                    942:        ssz = (param->precision * param->factor == 16)? 2 : 1;
                    943:        if (param->channels == 2)
                    944:                ssz <<= 1;
                    945:
                    946:        sc->pbufsize = ((char *)end - (char *)start);
                    947:        sc->pblksize = blksize;
                    948:        sc->pwmark = blksize;
                    949:
                    950:        nm_wr(sc, NM_PBUFFER_START, sc->pbuf, 4);
                    951:        nm_wr(sc, NM_PBUFFER_END, sc->pbuf + sc->pbufsize - ssz, 4);
                    952:        nm_wr(sc, NM_PBUFFER_CURRP, sc->pbuf, 4);
                    953:        nm_wr(sc, NM_PBUFFER_WMARK, sc->pbuf + sc->pwmark, 4);
                    954:        nm_wr(sc, NM_PLAYBACK_ENABLE_REG, NM_PLAYBACK_FREERUN |
                    955:            NM_PLAYBACK_ENABLE_FLAG, 1);
                    956:        nm_wr(sc, NM_AUDIO_MUTE_REG, 0, 2);
                    957:
                    958:        return (0);
                    959: }
                    960:
                    961:
                    962:
                    963: int
                    964: neo_trigger_input(addr, start, end, blksize, intr, arg, param)
                    965:        void *addr;
                    966:        void *start, *end;
                    967:        int blksize;
                    968:        void (*intr)(void *);
                    969:        void *arg;
                    970:        struct audio_params *param;
                    971: {
                    972:        struct neo_softc *sc = addr;
                    973:        int ssz;
                    974:
                    975:        sc->rintr = intr;
                    976:        sc->rarg = arg;
                    977:
                    978:        ssz = (param->precision * param->factor == 16)? 2 : 1;
                    979:        if (param->channels == 2)
                    980:                ssz <<= 1;
                    981:
                    982:        sc->rbufsize = ((char *)end - (char *)start);
                    983:        sc->rblksize = blksize;
                    984:        sc->rwmark = blksize;
                    985:
                    986:        nm_wr(sc, NM_RBUFFER_START, sc->rbuf, 4);
                    987:        nm_wr(sc, NM_RBUFFER_END, sc->rbuf + sc->rbufsize, 4);
                    988:        nm_wr(sc, NM_RBUFFER_CURRP, sc->rbuf, 4);
                    989:        nm_wr(sc, NM_RBUFFER_WMARK, sc->rbuf + sc->rwmark, 4);
                    990:        nm_wr(sc, NM_RECORD_ENABLE_REG, NM_RECORD_FREERUN |
                    991:            NM_RECORD_ENABLE_FLAG, 1);
                    992:
                    993:        return (0);
                    994: }
                    995:
                    996: int
                    997: neo_halt_output(addr)
                    998:        void *addr;
                    999: {
                   1000:        struct neo_softc *sc = (struct neo_softc *)addr;
                   1001:
                   1002:        nm_wr(sc, NM_PLAYBACK_ENABLE_REG, 0, 1);
                   1003:        nm_wr(sc, NM_AUDIO_MUTE_REG, NM_AUDIO_MUTE_BOTH, 2);
                   1004:
                   1005:        sc->pintr = 0;
                   1006:
                   1007:        return (0);
                   1008: }
                   1009:
                   1010: int
                   1011: neo_halt_input(addr)
                   1012:        void *addr;
                   1013: {
                   1014:        struct neo_softc *sc = (struct neo_softc *)addr;
                   1015:
                   1016:        nm_wr(sc, NM_RECORD_ENABLE_REG, 0, 1);
                   1017:
                   1018:        sc->rintr = 0;
                   1019:
                   1020:        return (0);
                   1021: }
                   1022:
                   1023: int
                   1024: neo_getdev(addr, retp)
                   1025:        void *addr;
                   1026:        struct audio_device *retp;
                   1027: {
                   1028:        *retp = neo_device;
                   1029:        return (0);
                   1030: }
                   1031:
                   1032: int
                   1033: neo_mixer_set_port(addr, cp)
                   1034:        void *addr;
                   1035:        mixer_ctrl_t *cp;
                   1036: {
                   1037:        struct neo_softc *sc = addr;
                   1038:
                   1039:        return ((sc->codec_if->vtbl->mixer_set_port)(sc->codec_if, cp));
                   1040: }
                   1041:
                   1042: int
                   1043: neo_mixer_get_port(addr, cp)
                   1044:        void *addr;
                   1045:        mixer_ctrl_t *cp;
                   1046: {
                   1047:        struct neo_softc *sc = addr;
                   1048:
                   1049:        return ((sc->codec_if->vtbl->mixer_get_port)(sc->codec_if, cp));
                   1050: }
                   1051:
                   1052: int
                   1053: neo_query_devinfo(addr, dip)
                   1054:        void *addr;
                   1055:        mixer_devinfo_t *dip;
                   1056: {
                   1057:        struct neo_softc *sc = addr;
                   1058:
                   1059:        return ((sc->codec_if->vtbl->query_devinfo)(sc->codec_if, dip));
                   1060: }
                   1061:
                   1062: void *
                   1063: neo_malloc(addr, direction, size, pool, flags)
                   1064:        void *addr;
                   1065:        int  direction;
                   1066:        size_t size;
                   1067:        int pool, flags;
                   1068: {
                   1069:        struct neo_softc *sc = addr;
                   1070:        void *rv = 0;
                   1071:
                   1072:        switch (direction) {
                   1073:        case AUMODE_PLAY:
                   1074:                rv = (char *)sc->bufioh + sc->pbuf;
                   1075:                break;
                   1076:        case AUMODE_RECORD:
                   1077:                rv = (char *)sc->bufioh + sc->rbuf;
                   1078:                break;
                   1079:        default:
                   1080:                break;
                   1081:        }
                   1082:
                   1083:        return (rv);
                   1084: }
                   1085:
                   1086: void
                   1087: neo_free(addr, ptr, pool)
                   1088:        void *addr;
                   1089:        void *ptr;
                   1090:        int pool;
                   1091: {
                   1092:        return;
                   1093: }
                   1094:
                   1095: size_t
                   1096: neo_round_buffersize(addr, direction, size)
                   1097:        void *addr;
                   1098:        int direction;
                   1099:        size_t size;
                   1100: {
                   1101:        return (NM_BUFFSIZE);
                   1102: }
                   1103:
                   1104:
                   1105: int
                   1106: neo_get_props(addr)
                   1107:        void *addr;
                   1108: {
                   1109:
                   1110:        return (AUDIO_PROP_INDEPENDENT | AUDIO_PROP_FULLDUPLEX);
                   1111: }

CVSweb