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