neomagic.c revision 58384
155639Scg/* 255639Scg * Copyright (c) 1999 Cameron Grant <gandalf@vilnya.demon.co.uk> 355639Scg * All rights reserved. 455639Scg * 555639Scg * Derived from the public domain Linux driver 655639Scg * 755639Scg * Redistribution and use in source and binary forms, with or without 855639Scg * modification, are permitted provided that the following conditions 955639Scg * are met: 1055639Scg * 1. Redistributions of source code must retain the above copyright 1155639Scg * notice, this list of conditions and the following disclaimer. 1255639Scg * 2. Redistributions in binary form must reproduce the above copyright 1355639Scg * notice, this list of conditions and the following disclaimer in the 1455639Scg * documentation and/or other materials provided with the distribution. 1555639Scg * 1655639Scg * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 1755639Scg * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 1855639Scg * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 1955639Scg * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 2055639Scg * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 2155639Scg * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 2255639Scg * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 2355639Scg * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHERIN CONTRACT, STRICT 2455639Scg * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 2555639Scg * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THEPOSSIBILITY OF 2655639Scg * SUCH DAMAGE. 2755639Scg * 2855639Scg * $FreeBSD: head/sys/dev/sound/pci/neomagic.c 58384 2000-03-20 15:30:50Z cg $ 2955639Scg */ 3055639Scg 3155639Scg#include <dev/sound/pcm/sound.h> 3255639Scg#include <dev/sound/pcm/ac97.h> 3355639Scg#include <dev/sound/pci/neomagic.h> 3455639Scg#include <dev/sound/pci/neomagic-coeff.h> 3555639Scg 3655639Scg#include <pci/pcireg.h> 3755639Scg#include <pci/pcivar.h> 3855639Scg 3955639Scg/* -------------------------------------------------------------------- */ 4055639Scg 4155639Scg#define NM_BUFFSIZE 16384 4255639Scg 4355639Scg#define NM256AV_PCI_ID 0x800510c8 4455639Scg#define NM256ZX_PCI_ID 0x800610c8 4555639Scg 4655639Scgstruct sc_info; 4755639Scg 4855639Scg/* channel registers */ 4955639Scgstruct sc_chinfo { 5055639Scg int spd, dir, fmt; 5155639Scg snd_dbuf *buffer; 5255639Scg pcm_channel *channel; 5355639Scg struct sc_info *parent; 5455639Scg}; 5555639Scg 5655639Scg/* device private data */ 5755639Scgstruct sc_info { 5855639Scg device_t dev; 5955639Scg u_int32_t type; 6055639Scg 6155639Scg struct resource *reg, *irq, *buf; 6255639Scg int regid, irqid, bufid; 6355639Scg void *ih; 6455639Scg 6555639Scg u_int32_t ac97_base, ac97_status, ac97_busy; 6655639Scg u_int32_t buftop, pbuf, rbuf, cbuf, acbuf; 6755639Scg u_int32_t playint, recint, misc1int, misc2int; 6855639Scg u_int32_t irsz, badintr; 6955639Scg 7055639Scg struct sc_chinfo pch, rch; 7155639Scg}; 7255639Scg 7355639Scg/* -------------------------------------------------------------------- */ 7455639Scg 7555639Scg/* 7655639Scg * prototypes 7755639Scg */ 7855639Scg 7955639Scg/* channel interface */ 8055639Scgstatic void *nmchan_init(void *devinfo, snd_dbuf *b, pcm_channel *c, int dir); 8155639Scgstatic int nmchan_setdir(void *data, int dir); 8255639Scgstatic int nmchan_setformat(void *data, u_int32_t format); 8355639Scgstatic int nmchan_setspeed(void *data, u_int32_t speed); 8455639Scgstatic int nmchan_setblocksize(void *data, u_int32_t blocksize); 8555639Scgstatic int nmchan_trigger(void *data, int go); 8655639Scgstatic int nmchan_getptr(void *data); 8755639Scgstatic pcmchan_caps *nmchan_getcaps(void *data); 8855639Scg 8955639Scgstatic int nm_waitcd(struct sc_info *sc); 9055639Scg/* talk to the codec - called from ac97.c */ 9155639Scgstatic u_int32_t nm_rdcd(void *, int); 9255639Scgstatic void nm_wrcd(void *, int, u_int32_t); 9355639Scg 9455639Scg/* stuff */ 9555639Scgstatic int nm_loadcoeff(struct sc_info *sc, int dir, int num); 9655639Scgstatic int nm_setch(struct sc_chinfo *ch); 9755639Scgstatic int nm_init(struct sc_info *); 9855639Scgstatic void nm_intr(void *); 9955639Scg 10055639Scg/* talk to the card */ 10155639Scgstatic u_int32_t nm_rd(struct sc_info *, int, int); 10255639Scgstatic void nm_wr(struct sc_info *, int, u_int32_t, int); 10355639Scgstatic u_int32_t nm_rdbuf(struct sc_info *, int, int); 10455639Scgstatic void nm_wrbuf(struct sc_info *, int, u_int32_t, int); 10555639Scg 10655802Scgstatic u_int32_t badcards[] = { 10755802Scg 0x0007103c, 10855802Scg 0x008f1028, 10955802Scg}; 11055802Scg#define NUM_BADCARDS (sizeof(badcards) / sizeof(u_int32_t)) 11155802Scg 11255639Scg/* The actual rates supported by the card. */ 11355639Scgstatic int samplerates[9] = { 11455802Scg 8000, 11555802Scg 11025, 11655802Scg 16000, 11755802Scg 22050, 11855802Scg 24000, 11955802Scg 32000, 12055802Scg 44100, 12155802Scg 48000, 12255802Scg 99999999 12355639Scg}; 12455639Scg 12555639Scg/* -------------------------------------------------------------------- */ 12655639Scg 12755639Scgstatic pcmchan_caps nm_caps = { 12855639Scg 4000, 48000, 12955639Scg AFMT_STEREO | AFMT_U8 | AFMT_S16_LE, 13055639Scg AFMT_STEREO | AFMT_S16_LE 13155639Scg}; 13255639Scg 13355639Scgstatic pcm_channel nm_chantemplate = { 13455639Scg nmchan_init, 13555639Scg nmchan_setdir, 13655639Scg nmchan_setformat, 13755639Scg nmchan_setspeed, 13855639Scg nmchan_setblocksize, 13955639Scg nmchan_trigger, 14055639Scg nmchan_getptr, 14155639Scg nmchan_getcaps, 14255639Scg}; 14355639Scg 14455639Scg/* -------------------------------------------------------------------- */ 14555639Scg 14655639Scg/* Hardware */ 14755639Scgstatic u_int32_t 14855639Scgnm_rd(struct sc_info *sc, int regno, int size) 14955639Scg{ 15055639Scg bus_space_tag_t st = rman_get_bustag(sc->reg); 15155639Scg bus_space_handle_t sh = rman_get_bushandle(sc->reg); 15255639Scg 15355639Scg switch (size) { 15455639Scg case 1: 15555639Scg return bus_space_read_1(st, sh, regno); 15655639Scg case 2: 15755639Scg return bus_space_read_2(st, sh, regno); 15855639Scg case 4: 15955639Scg return bus_space_read_4(st, sh, regno); 16055639Scg default: 16155639Scg return 0xffffffff; 16255639Scg } 16355639Scg} 16455639Scg 16555639Scgstatic void 16655639Scgnm_wr(struct sc_info *sc, int regno, u_int32_t data, int size) 16755639Scg{ 16855639Scg bus_space_tag_t st = rman_get_bustag(sc->reg); 16955639Scg bus_space_handle_t sh = rman_get_bushandle(sc->reg); 17055639Scg 17155639Scg switch (size) { 17255639Scg case 1: 17355639Scg bus_space_write_1(st, sh, regno, data); 17455639Scg break; 17555639Scg case 2: 17655639Scg bus_space_write_2(st, sh, regno, data); 17755639Scg break; 17855639Scg case 4: 17955639Scg bus_space_write_4(st, sh, regno, data); 18055639Scg break; 18155639Scg } 18255639Scg} 18355639Scg 18455639Scgstatic u_int32_t 18555639Scgnm_rdbuf(struct sc_info *sc, int regno, int size) 18655639Scg{ 18755639Scg bus_space_tag_t st = rman_get_bustag(sc->buf); 18855639Scg bus_space_handle_t sh = rman_get_bushandle(sc->buf); 18955639Scg 19055639Scg switch (size) { 19155639Scg case 1: 19255639Scg return bus_space_read_1(st, sh, regno); 19355639Scg case 2: 19455639Scg return bus_space_read_2(st, sh, regno); 19555639Scg case 4: 19655639Scg return bus_space_read_4(st, sh, regno); 19755639Scg default: 19855639Scg return 0xffffffff; 19955639Scg } 20055639Scg} 20155639Scg 20255639Scgstatic void 20355639Scgnm_wrbuf(struct sc_info *sc, int regno, u_int32_t data, int size) 20455639Scg{ 20555639Scg bus_space_tag_t st = rman_get_bustag(sc->buf); 20655639Scg bus_space_handle_t sh = rman_get_bushandle(sc->buf); 20755639Scg 20855639Scg switch (size) { 20955639Scg case 1: 21055639Scg bus_space_write_1(st, sh, regno, data); 21155639Scg break; 21255639Scg case 2: 21355639Scg bus_space_write_2(st, sh, regno, data); 21455639Scg break; 21555639Scg case 4: 21655639Scg bus_space_write_4(st, sh, regno, data); 21755639Scg break; 21855639Scg } 21955639Scg} 22055639Scg 22155639Scg/* ac97 codec */ 22255639Scgstatic int 22355639Scgnm_waitcd(struct sc_info *sc) 22455639Scg{ 22555639Scg int cnt = 10; 22655639Scg 22755639Scg while (cnt-- > 0) { 22855639Scg if (nm_rd(sc, sc->ac97_status, 2) & sc->ac97_busy) 22955639Scg DELAY(100); 23055639Scg else 23155639Scg break; 23255639Scg } 23355639Scg return (nm_rd(sc, sc->ac97_status, 2) & sc->ac97_busy); 23455639Scg} 23555639Scg 23655639Scgstatic u_int32_t 23758384Scgnm_initcd(void *devinfo) 23858384Scg{ 23958384Scg struct sc_info *sc = (struct sc_info *)devinfo; 24058384Scg 24158384Scg nm_wr(sc, 0x6c0, 0x01, 1); 24258384Scg nm_wr(sc, 0x6cc, 0x87, 1); 24358384Scg nm_wr(sc, 0x6cc, 0x80, 1); 24458384Scg nm_wr(sc, 0x6cc, 0x00, 1); 24558384Scg return 0; 24658384Scg} 24758384Scg 24858384Scgstatic u_int32_t 24955639Scgnm_rdcd(void *devinfo, int regno) 25055639Scg{ 25155639Scg struct sc_info *sc = (struct sc_info *)devinfo; 25255639Scg u_int32_t x; 25355639Scg 25455639Scg if (!nm_waitcd(sc)) { 25555639Scg x = nm_rd(sc, sc->ac97_base + regno, 2); 25655639Scg DELAY(1000); 25755639Scg return x; 25855639Scg } else { 25955639Scg device_printf(sc->dev, "ac97 codec not ready\n"); 26055639Scg return 0xffffffff; 26155639Scg } 26255639Scg} 26355639Scg 26455639Scgstatic void 26555639Scgnm_wrcd(void *devinfo, int regno, u_int32_t data) 26655639Scg{ 26755639Scg struct sc_info *sc = (struct sc_info *)devinfo; 26855639Scg int cnt = 3; 26955639Scg 27055639Scg if (!nm_waitcd(sc)) { 27155639Scg while (cnt-- > 0) { 27255639Scg nm_wr(sc, sc->ac97_base + regno, data, 2); 27355639Scg if (!nm_waitcd(sc)) { 27455639Scg DELAY(1000); 27555639Scg return; 27655639Scg } 27755639Scg } 27855639Scg } 27955639Scg device_printf(sc->dev, "ac97 codec not ready\n"); 28055639Scg} 28155639Scg 28255639Scgstatic void 28355639Scgnm_ackint(struct sc_info *sc, u_int32_t num) 28455639Scg{ 28555639Scg if (sc->type == NM256AV_PCI_ID) { 28655639Scg nm_wr(sc, NM_INT_REG, num << 1, 2); 28755639Scg } else if (sc->type == NM256ZX_PCI_ID) { 28855639Scg nm_wr(sc, NM_INT_REG, num, 4); 28955639Scg } 29055639Scg} 29155639Scg 29255639Scgstatic int 29355639Scgnm_loadcoeff(struct sc_info *sc, int dir, int num) 29455639Scg{ 29555639Scg int ofs, sz, i; 29655639Scg u_int32_t addr; 29755639Scg 29855639Scg addr = (dir == PCMDIR_PLAY)? 0x01c : 0x21c; 29955639Scg if (dir == PCMDIR_REC) 30055639Scg num += 8; 30155639Scg sz = coefficientSizes[num]; 30255639Scg ofs = 0; 30355639Scg while (num-- > 0) 30455639Scg ofs+= coefficientSizes[num]; 30555639Scg for (i = 0; i < sz; i++) 30655639Scg nm_wrbuf(sc, sc->cbuf + i, coefficients[ofs + i], 1); 30755639Scg nm_wr(sc, addr, sc->cbuf, 4); 30855639Scg if (dir == PCMDIR_PLAY) 30955639Scg sz--; 31055639Scg nm_wr(sc, addr + 4, sc->cbuf + sz, 4); 31155639Scg return 0; 31255639Scg} 31355639Scg 31455639Scgstatic int 31555639Scgnm_setch(struct sc_chinfo *ch) 31655639Scg{ 31755639Scg struct sc_info *sc = ch->parent; 31855639Scg u_int32_t base; 31955639Scg u_int8_t x; 32055639Scg 32155639Scg for (x = 0; x < 8; x++) 32255639Scg if (ch->spd < (samplerates[x] + samplerates[x + 1]) / 2) 32355639Scg break; 32455639Scg 32555639Scg if (x == 8) return 1; 32655639Scg 32755639Scg ch->spd = samplerates[x]; 32855639Scg nm_loadcoeff(sc, ch->dir, x); 32955639Scg 33055639Scg x <<= 4; 33155639Scg x &= NM_RATE_MASK; 33255639Scg if (ch->fmt & AFMT_16BIT) x |= NM_RATE_BITS_16; 33355639Scg if (ch->fmt & AFMT_STEREO) x |= NM_RATE_STEREO; 33455639Scg 33555639Scg base = (ch->dir == PCMDIR_PLAY)? NM_PLAYBACK_REG_OFFSET : NM_RECORD_REG_OFFSET; 33655639Scg nm_wr(sc, base + NM_RATE_REG_OFFSET, x, 1); 33755639Scg return 0; 33855639Scg} 33955639Scg 34055639Scg/* channel interface */ 34155639Scgstatic void * 34255639Scgnmchan_init(void *devinfo, snd_dbuf *b, pcm_channel *c, int dir) 34355639Scg{ 34455639Scg struct sc_info *sc = devinfo; 34555639Scg struct sc_chinfo *ch; 34655639Scg u_int32_t chnbuf; 34755639Scg 34855639Scg chnbuf = (dir == PCMDIR_PLAY)? sc->pbuf : sc->rbuf; 34955639Scg ch = (dir == PCMDIR_PLAY)? &sc->pch : &sc->rch; 35055639Scg ch->buffer = b; 35155639Scg ch->buffer->bufsize = NM_BUFFSIZE; 35255639Scg ch->buffer->buf = (u_int8_t *)(rman_get_bushandle(sc->buf) + chnbuf); 35355878Scg if (bootverbose) 35455878Scg device_printf(sc->dev, "%s buf %p\n", (dir == PCMDIR_PLAY)? 35555878Scg "play" : "rec", ch->buffer->buf); 35655639Scg ch->parent = sc; 35755639Scg ch->channel = c; 35855639Scg ch->dir = dir; 35955639Scg return ch; 36055639Scg} 36155639Scg 36255639Scgstatic int 36355639Scgnmchan_setdir(void *data, int dir) 36455639Scg{ 36555639Scg return 0; 36655639Scg} 36755639Scg 36855639Scgstatic int 36955639Scgnmchan_setformat(void *data, u_int32_t format) 37055639Scg{ 37155639Scg struct sc_chinfo *ch = data; 37255639Scg 37355639Scg ch->fmt = format; 37455639Scg return nm_setch(ch); 37555639Scg} 37655639Scg 37755639Scgstatic int 37855639Scgnmchan_setspeed(void *data, u_int32_t speed) 37955639Scg{ 38055639Scg struct sc_chinfo *ch = data; 38155639Scg 38255639Scg ch->spd = speed; 38355700Scg return nm_setch(ch)? 0 : ch->spd; 38455639Scg} 38555639Scg 38655639Scgstatic int 38755639Scgnmchan_setblocksize(void *data, u_int32_t blocksize) 38855639Scg{ 38955639Scg return blocksize; 39055639Scg} 39155639Scg 39255639Scgstatic int 39355639Scgnmchan_trigger(void *data, int go) 39455639Scg{ 39555639Scg struct sc_chinfo *ch = data; 39655639Scg struct sc_info *sc = ch->parent; 39755639Scg int ssz; 39855639Scg 39955639Scg if (go == PCMTRIG_EMLDMAWR) return 0; 40055639Scg 40155639Scg ssz = (ch->fmt & AFMT_16BIT)? 2 : 1; 40255639Scg if (ch->fmt & AFMT_STEREO) 40355639Scg ssz <<= 1; 40455639Scg 40555639Scg if (ch->dir == PCMDIR_PLAY) { 40655639Scg if (go == PCMTRIG_START) { 40755639Scg nm_wr(sc, NM_PBUFFER_START, sc->pbuf, 4); 40855639Scg nm_wr(sc, NM_PBUFFER_END, sc->pbuf + NM_BUFFSIZE - ssz, 4); 40955639Scg nm_wr(sc, NM_PBUFFER_CURRP, sc->pbuf, 4); 41055639Scg nm_wr(sc, NM_PBUFFER_WMARK, sc->pbuf + NM_BUFFSIZE / 2, 4); 41155639Scg nm_wr(sc, NM_PLAYBACK_ENABLE_REG, NM_PLAYBACK_FREERUN | 41255639Scg NM_PLAYBACK_ENABLE_FLAG, 1); 41355639Scg nm_wr(sc, NM_AUDIO_MUTE_REG, 0, 2); 41455639Scg } else { 41555639Scg nm_wr(sc, NM_PLAYBACK_ENABLE_REG, 0, 1); 41655639Scg nm_wr(sc, NM_AUDIO_MUTE_REG, NM_AUDIO_MUTE_BOTH, 2); 41755639Scg } 41855639Scg } else { 41955639Scg if (go == PCMTRIG_START) { 42055639Scg nm_wr(sc, NM_RECORD_ENABLE_REG, NM_RECORD_FREERUN | 42155639Scg NM_RECORD_ENABLE_FLAG, 1); 42255639Scg nm_wr(sc, NM_RBUFFER_START, sc->rbuf, 4); 42355639Scg nm_wr(sc, NM_RBUFFER_END, sc->rbuf + NM_BUFFSIZE, 4); 42455639Scg nm_wr(sc, NM_RBUFFER_CURRP, sc->rbuf, 4); 42555639Scg nm_wr(sc, NM_RBUFFER_WMARK, sc->rbuf + NM_BUFFSIZE / 2, 4); 42655639Scg } else { 42755639Scg nm_wr(sc, NM_RECORD_ENABLE_REG, 0, 1); 42855639Scg } 42955639Scg } 43055639Scg return 0; 43155639Scg} 43255639Scg 43355639Scgstatic int 43455639Scgnmchan_getptr(void *data) 43555639Scg{ 43655639Scg struct sc_chinfo *ch = data; 43755639Scg struct sc_info *sc = ch->parent; 43855639Scg 43955639Scg if (ch->dir == PCMDIR_PLAY) 44055639Scg return nm_rd(sc, NM_PBUFFER_CURRP, 4) - sc->pbuf; 44155639Scg else 44255639Scg return nm_rd(sc, NM_RBUFFER_CURRP, 4) - sc->rbuf; 44355639Scg} 44455639Scg 44555639Scgstatic pcmchan_caps * 44655639Scgnmchan_getcaps(void *data) 44755639Scg{ 44855639Scg return &nm_caps; 44955639Scg} 45055639Scg 45155639Scg/* The interrupt handler */ 45255639Scgstatic void 45355639Scgnm_intr(void *p) 45455639Scg{ 45555639Scg struct sc_info *sc = (struct sc_info *)p; 45655713Scg int status, x, active; 45755639Scg 45855713Scg active = (sc->pch.channel->buffer.dl || sc->rch.channel->buffer.dl); 45955639Scg status = nm_rd(sc, NM_INT_REG, sc->irsz); 46055713Scg if (status == 0 && active) { 46155639Scg if (sc->badintr++ > 1000) { 46255639Scg device_printf(sc->dev, "1000 bad intrs\n"); 46355639Scg sc->badintr = 0; 46455639Scg } 46555639Scg return; 46655639Scg } 46755639Scg sc->badintr = 0; 46855639Scg 46955639Scg if (status & sc->playint) { 47055639Scg status &= ~sc->playint; 47155639Scg nm_ackint(sc, sc->playint); 47255639Scg chn_intr(sc->pch.channel); 47355639Scg } 47455639Scg if (status & sc->recint) { 47555639Scg status &= ~sc->recint; 47655639Scg nm_ackint(sc, sc->recint); 47755639Scg chn_intr(sc->rch.channel); 47855639Scg } 47955639Scg if (status & sc->misc1int) { 48055639Scg status &= ~sc->misc1int; 48155639Scg nm_ackint(sc, sc->misc1int); 48255639Scg x = nm_rd(sc, 0x400, 1); 48355639Scg nm_wr(sc, 0x400, x | 2, 1); 48455639Scg device_printf(sc->dev, "misc int 1\n"); 48555639Scg } 48655639Scg if (status & sc->misc2int) { 48755639Scg status &= ~sc->misc2int; 48855639Scg nm_ackint(sc, sc->misc2int); 48955639Scg x = nm_rd(sc, 0x400, 1); 49055639Scg nm_wr(sc, 0x400, x & ~2, 1); 49155639Scg device_printf(sc->dev, "misc int 2\n"); 49255639Scg } 49355639Scg if (status) { 49455639Scg status &= ~sc->misc2int; 49555639Scg nm_ackint(sc, sc->misc2int); 49655639Scg device_printf(sc->dev, "unknown int\n"); 49755639Scg } 49855639Scg} 49955639Scg 50055639Scg/* -------------------------------------------------------------------- */ 50155639Scg 50255639Scg/* 50355639Scg * Probe and attach the card 50455639Scg */ 50555639Scg 50655639Scgstatic int 50755639Scgnm_init(struct sc_info *sc) 50855639Scg{ 50955639Scg u_int32_t ofs, i; 51055639Scg 51155639Scg if (sc->type == NM256AV_PCI_ID) { 51255639Scg sc->ac97_base = NM_MIXER_OFFSET; 51355639Scg sc->ac97_status = NM_MIXER_STATUS_OFFSET; 51455639Scg sc->ac97_busy = NM_MIXER_READY_MASK; 51555639Scg 51655639Scg sc->buftop = 2560 * 1024; 51755639Scg 51855639Scg sc->irsz = 2; 51955639Scg sc->playint = NM_PLAYBACK_INT; 52055639Scg sc->recint = NM_RECORD_INT; 52155639Scg sc->misc1int = NM_MISC_INT_1; 52255639Scg sc->misc2int = NM_MISC_INT_2; 52355639Scg } else if (sc->type == NM256ZX_PCI_ID) { 52455639Scg sc->ac97_base = NM_MIXER_OFFSET; 52555639Scg sc->ac97_status = NM2_MIXER_STATUS_OFFSET; 52655639Scg sc->ac97_busy = NM2_MIXER_READY_MASK; 52755639Scg 52855639Scg sc->buftop = (nm_rd(sc, 0xa0b, 2)? 6144 : 4096) * 1024; 52955639Scg 53055639Scg sc->irsz = 4; 53155639Scg sc->playint = NM2_PLAYBACK_INT; 53255639Scg sc->recint = NM2_RECORD_INT; 53355639Scg sc->misc1int = NM2_MISC_INT_1; 53455639Scg sc->misc2int = NM2_MISC_INT_2; 53555713Scg } else return -1; 53655639Scg sc->badintr = 0; 53755639Scg ofs = sc->buftop - 0x0400; 53855639Scg sc->buftop -= 0x1400; 53955639Scg 54055639Scg if ((nm_rdbuf(sc, ofs, 4) & NM_SIG_MASK) == NM_SIGNATURE) { 54155639Scg i = nm_rdbuf(sc, ofs + 4, 4); 54255639Scg if (i != 0 && i != 0xffffffff) 54355639Scg sc->buftop = i; 54455639Scg } 54555639Scg 54655639Scg sc->cbuf = sc->buftop - NM_MAX_COEFFICIENT; 54755639Scg sc->rbuf = sc->cbuf - NM_BUFFSIZE; 54855639Scg sc->pbuf = sc->rbuf - NM_BUFFSIZE; 54955639Scg sc->acbuf = sc->pbuf - (NM_TOTAL_COEFF_COUNT * 4); 55055639Scg 55155639Scg nm_wr(sc, 0, 0x11, 1); 55255639Scg nm_wr(sc, NM_RECORD_ENABLE_REG, 0, 1); 55355639Scg nm_wr(sc, 0x214, 0, 2); 55455639Scg 55555639Scg return 0; 55655639Scg} 55755639Scg 55855639Scgstatic int 55955639Scgnm_pci_probe(device_t dev) 56055639Scg{ 56155639Scg char *s = NULL; 56255802Scg u_int32_t subdev, i; 56355639Scg 56455802Scg subdev = (pci_get_subdevice(dev) << 16) | pci_get_subvendor(dev); 56555639Scg switch (pci_get_devid(dev)) { 56655639Scg case NM256AV_PCI_ID: 56755802Scg i = 0; 56855802Scg while ((i < NUM_BADCARDS) && (badcards[i] != subdev)) 56955802Scg i++; 57055802Scg if (i == NUM_BADCARDS) 57155802Scg s = "NeoMagic 256AV"; 57255878Scg DEB(else) 57355878Scg DEB(device_printf(dev, "this is a non-ac97 NM256AV, not attaching\n")); 57455639Scg break; 57555639Scg 57655639Scg case NM256ZX_PCI_ID: 57755639Scg s = "NeoMagic 256ZX"; 57855639Scg break; 57955639Scg } 58055639Scg 58155639Scg if (s) device_set_desc(dev, s); 58255639Scg return s? 0 : ENXIO; 58355639Scg} 58455639Scg 58555639Scgstatic int 58655639Scgnm_pci_attach(device_t dev) 58755639Scg{ 58855639Scg snddev_info *d; 58955639Scg u_int32_t data; 59055639Scg struct sc_info *sc; 59155639Scg struct ac97_info *codec; 59255639Scg char status[SND_STATUSLEN]; 59355639Scg 59455639Scg d = device_get_softc(dev); 59555639Scg if ((sc = malloc(sizeof(*sc), M_DEVBUF, M_NOWAIT)) == NULL) { 59655639Scg device_printf(dev, "cannot allocate softc\n"); 59755639Scg return ENXIO; 59855639Scg } 59955639Scg 60055639Scg bzero(sc, sizeof(*sc)); 60155639Scg sc->dev = dev; 60255639Scg sc->type = pci_get_devid(dev); 60355639Scg 60455639Scg data = pci_read_config(dev, PCIR_COMMAND, 2); 60555639Scg data |= (PCIM_CMD_PORTEN|PCIM_CMD_MEMEN|PCIM_CMD_BUSMASTEREN); 60655639Scg pci_write_config(dev, PCIR_COMMAND, data, 2); 60755639Scg data = pci_read_config(dev, PCIR_COMMAND, 2); 60855639Scg 60955639Scg sc->bufid = PCIR_MAPS; 61055639Scg sc->buf = bus_alloc_resource(dev, SYS_RES_MEMORY, &sc->bufid, 61155639Scg 0, ~0, 1, RF_ACTIVE); 61255639Scg sc->regid = PCIR_MAPS + 4; 61355639Scg sc->reg = bus_alloc_resource(dev, SYS_RES_MEMORY, &sc->regid, 61455639Scg 0, ~0, 1, RF_ACTIVE); 61555639Scg 61655639Scg if (!sc->buf || !sc->reg) { 61755639Scg device_printf(dev, "unable to map register space\n"); 61855639Scg goto bad; 61955639Scg } 62055639Scg 62155639Scg if (nm_init(sc) == -1) { 62255639Scg device_printf(dev, "unable to initialize the card\n"); 62355639Scg goto bad; 62455639Scg } 62555639Scg 62658384Scg codec = ac97_create(dev, sc, nm_initcd, nm_rdcd, nm_wrcd); 62755639Scg if (codec == NULL) goto bad; 62855639Scg mixer_init(d, &ac97_mixer, codec); 62955639Scg 63055639Scg sc->irqid = 0; 63155639Scg sc->irq = bus_alloc_resource(dev, SYS_RES_IRQ, &sc->irqid, 63255639Scg 0, ~0, 1, RF_ACTIVE | RF_SHAREABLE); 63355639Scg if (!sc->irq || 63455639Scg bus_setup_intr(dev, sc->irq, INTR_TYPE_TTY, nm_intr, sc, &sc->ih)) { 63555639Scg device_printf(dev, "unable to map interrupt\n"); 63655639Scg goto bad; 63755639Scg } 63855639Scg 63955639Scg snprintf(status, SND_STATUSLEN, "at memory 0x%lx, 0x%lx irq %ld", 64055639Scg rman_get_start(sc->buf), rman_get_start(sc->reg), 64155639Scg rman_get_start(sc->irq)); 64255639Scg 64355639Scg if (pcm_register(dev, sc, 1, 1)) goto bad; 64455639Scg pcm_addchan(dev, PCMDIR_REC, &nm_chantemplate, sc); 64555639Scg pcm_addchan(dev, PCMDIR_PLAY, &nm_chantemplate, sc); 64655639Scg pcm_setstatus(dev, status); 64755639Scg 64855639Scg return 0; 64955639Scg 65055639Scgbad: 65155639Scg if (sc->buf) bus_release_resource(dev, SYS_RES_MEMORY, sc->bufid, sc->buf); 65255639Scg if (sc->reg) bus_release_resource(dev, SYS_RES_MEMORY, sc->regid, sc->reg); 65355639Scg if (sc->ih) bus_teardown_intr(dev, sc->irq, sc->ih); 65455639Scg if (sc->irq) bus_release_resource(dev, SYS_RES_IRQ, sc->irqid, sc->irq); 65555639Scg free(sc, M_DEVBUF); 65655639Scg return ENXIO; 65755639Scg} 65855639Scg 65958384Scgstatic int 66058384Scgnm_pci_resume(device_t dev) 66158384Scg{ 66258384Scg snddev_info *d; 66358384Scg struct sc_info *sc; 66458384Scg 66558384Scg d = device_get_softc(dev); 66658384Scg sc = pcm_getdevinfo(dev); 66758384Scg 66858384Scg /* Reinit audio device */ 66958384Scg if (nm_init(sc) == -1) { 67058384Scg device_printf(dev, "unable to reinitialize the card\n"); 67158384Scg return ENXIO; 67258384Scg } 67358384Scg /* Reinit mixer */ 67458384Scg if (mixer_reinit(d) == -1) { 67558384Scg device_printf(dev, "unable to reinitialize the mixer\n"); 67658384Scg return ENXIO; 67758384Scg } 67858384Scg return 0; 67958384Scg} 68058384Scg 68155639Scgstatic device_method_t nm_methods[] = { 68255639Scg /* Device interface */ 68355639Scg DEVMETHOD(device_probe, nm_pci_probe), 68455639Scg DEVMETHOD(device_attach, nm_pci_attach), 68558384Scg DEVMETHOD(device_resume, nm_pci_resume), 68655639Scg { 0, 0 } 68755639Scg}; 68855639Scg 68955639Scgstatic driver_t nm_driver = { 69055639Scg "pcm", 69155639Scg nm_methods, 69255639Scg sizeof(snddev_info), 69355639Scg}; 69455639Scg 69555639Scgstatic devclass_t pcm_devclass; 69655639Scg 69755639ScgDRIVER_MODULE(nm, pci, nm_driver, pcm_devclass, 0, 0); 698