1/*-
2 * Copyright (c) 1999 Cameron Grant <cg@freebsd.org>
3 * All rights reserved.
4 *
5 * Derived from the public domain Linux driver
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 *    notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 *    notice, this list of conditions and the following disclaimer in the
14 *    documentation and/or other materials provided with the distribution.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
17 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
20 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHERIN CONTRACT, STRICT
24 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THEPOSSIBILITY OF
26 * SUCH DAMAGE.
27 */
28
29#ifdef HAVE_KERNEL_OPTION_HEADERS
30#include "opt_snd.h"
31#endif
32
33#include <dev/sound/pcm/sound.h>
34#include <dev/sound/pcm/ac97.h>
35#include <dev/sound/pci/neomagic.h>
36#include <dev/sound/pci/neomagic-coeff.h>
37
38#include <dev/pci/pcireg.h>
39#include <dev/pci/pcivar.h>
40
41SND_DECLARE_FILE("$FreeBSD$");
42
43/* -------------------------------------------------------------------- */
44
45#define	NM_BUFFSIZE	16384
46
47#define NM256AV_PCI_ID 	0x800510c8
48#define NM256ZX_PCI_ID 	0x800610c8
49
50struct sc_info;
51
52/* channel registers */
53struct sc_chinfo {
54	int active, spd, dir, fmt;
55	u_int32_t blksize, wmark;
56	struct snd_dbuf *buffer;
57	struct pcm_channel *channel;
58	struct sc_info *parent;
59};
60
61/* device private data */
62struct sc_info {
63	device_t	dev;
64	u_int32_t 	type;
65
66	struct resource *reg, *irq, *buf;
67	int		regid, irqid, bufid;
68	void		*ih;
69
70	u_int32_t 	ac97_base, ac97_status, ac97_busy;
71	u_int32_t	buftop, pbuf, rbuf, cbuf, acbuf;
72	u_int32_t	playint, recint, misc1int, misc2int;
73	u_int32_t	irsz, badintr;
74
75	struct sc_chinfo pch, rch;
76};
77
78/* -------------------------------------------------------------------- */
79
80/*
81 * prototypes
82 */
83
84/* stuff */
85static int 	 nm_loadcoeff(struct sc_info *sc, int dir, int num);
86static int	 nm_setch(struct sc_chinfo *ch);
87static int       nm_init(struct sc_info *);
88static void      nm_intr(void *);
89
90/* talk to the card */
91static u_int32_t nm_rd(struct sc_info *, int, int);
92static void 	 nm_wr(struct sc_info *, int, u_int32_t, int);
93static u_int32_t nm_rdbuf(struct sc_info *, int, int);
94static void 	 nm_wrbuf(struct sc_info *, int, u_int32_t, int);
95
96static u_int32_t badcards[] = {
97	0x0007103c,
98	0x008f1028,
99	0x00dd1014,
100	0x8005110a,
101};
102#define NUM_BADCARDS (sizeof(badcards) / sizeof(u_int32_t))
103
104/* The actual rates supported by the card. */
105static int samplerates[9] = {
106	8000,
107	11025,
108	16000,
109	22050,
110	24000,
111	32000,
112	44100,
113	48000,
114	99999999
115};
116
117/* -------------------------------------------------------------------- */
118
119static u_int32_t nm_fmt[] = {
120	SND_FORMAT(AFMT_U8, 1, 0),
121	SND_FORMAT(AFMT_U8, 2, 0),
122	SND_FORMAT(AFMT_S16_LE, 1, 0),
123	SND_FORMAT(AFMT_S16_LE, 2, 0),
124	0
125};
126static struct pcmchan_caps nm_caps = {4000, 48000, nm_fmt, 0};
127
128/* -------------------------------------------------------------------- */
129
130/* Hardware */
131static u_int32_t
132nm_rd(struct sc_info *sc, int regno, int size)
133{
134	bus_space_tag_t st = rman_get_bustag(sc->reg);
135	bus_space_handle_t sh = rman_get_bushandle(sc->reg);
136
137	switch (size) {
138	case 1:
139		return bus_space_read_1(st, sh, regno);
140	case 2:
141		return bus_space_read_2(st, sh, regno);
142	case 4:
143		return bus_space_read_4(st, sh, regno);
144	default:
145		return 0xffffffff;
146	}
147}
148
149static void
150nm_wr(struct sc_info *sc, int regno, u_int32_t data, int size)
151{
152	bus_space_tag_t st = rman_get_bustag(sc->reg);
153	bus_space_handle_t sh = rman_get_bushandle(sc->reg);
154
155	switch (size) {
156	case 1:
157		bus_space_write_1(st, sh, regno, data);
158		break;
159	case 2:
160		bus_space_write_2(st, sh, regno, data);
161		break;
162	case 4:
163		bus_space_write_4(st, sh, regno, data);
164		break;
165	}
166}
167
168static u_int32_t
169nm_rdbuf(struct sc_info *sc, int regno, int size)
170{
171	bus_space_tag_t st = rman_get_bustag(sc->buf);
172	bus_space_handle_t sh = rman_get_bushandle(sc->buf);
173
174	switch (size) {
175	case 1:
176		return bus_space_read_1(st, sh, regno);
177	case 2:
178		return bus_space_read_2(st, sh, regno);
179	case 4:
180		return bus_space_read_4(st, sh, regno);
181	default:
182		return 0xffffffff;
183	}
184}
185
186static void
187nm_wrbuf(struct sc_info *sc, int regno, u_int32_t data, int size)
188{
189	bus_space_tag_t st = rman_get_bustag(sc->buf);
190	bus_space_handle_t sh = rman_get_bushandle(sc->buf);
191
192	switch (size) {
193	case 1:
194		bus_space_write_1(st, sh, regno, data);
195		break;
196	case 2:
197		bus_space_write_2(st, sh, regno, data);
198		break;
199	case 4:
200		bus_space_write_4(st, sh, regno, data);
201		break;
202	}
203}
204
205/* -------------------------------------------------------------------- */
206/* ac97 codec */
207static int
208nm_waitcd(struct sc_info *sc)
209{
210	int cnt = 10;
211	int fail = 1;
212
213	while (cnt-- > 0) {
214		if (nm_rd(sc, sc->ac97_status, 2) & sc->ac97_busy) {
215			DELAY(100);
216		} else {
217			fail = 0;
218			break;
219		}
220	}
221	return (fail);
222}
223
224static u_int32_t
225nm_initcd(kobj_t obj, void *devinfo)
226{
227	struct sc_info *sc = (struct sc_info *)devinfo;
228
229	nm_wr(sc, 0x6c0, 0x01, 1);
230#if 0
231	/*
232	 * The following code-line may cause a hang for some chipsets, see
233	 * PR 56617.
234	 * In case of a bugreport without this line have a look at the PR and
235	 * conditionize the code-line based upon the specific version of
236	 * the chip.
237	 */
238	nm_wr(sc, 0x6cc, 0x87, 1);
239#endif
240	nm_wr(sc, 0x6cc, 0x80, 1);
241	nm_wr(sc, 0x6cc, 0x00, 1);
242	return 1;
243}
244
245static int
246nm_rdcd(kobj_t obj, void *devinfo, int regno)
247{
248	struct sc_info *sc = (struct sc_info *)devinfo;
249	u_int32_t x;
250
251	if (!nm_waitcd(sc)) {
252		x = nm_rd(sc, sc->ac97_base + regno, 2);
253		DELAY(1000);
254		return x;
255	} else {
256		device_printf(sc->dev, "ac97 codec not ready\n");
257		return -1;
258	}
259}
260
261static int
262nm_wrcd(kobj_t obj, void *devinfo, int regno, u_int32_t data)
263{
264	struct sc_info *sc = (struct sc_info *)devinfo;
265	int cnt = 3;
266
267	if (!nm_waitcd(sc)) {
268		while (cnt-- > 0) {
269			nm_wr(sc, sc->ac97_base + regno, data, 2);
270			if (!nm_waitcd(sc)) {
271				DELAY(1000);
272				return 0;
273			}
274		}
275	}
276	device_printf(sc->dev, "ac97 codec not ready\n");
277	return -1;
278}
279
280static kobj_method_t nm_ac97_methods[] = {
281    	KOBJMETHOD(ac97_init,		nm_initcd),
282    	KOBJMETHOD(ac97_read,		nm_rdcd),
283    	KOBJMETHOD(ac97_write,		nm_wrcd),
284	KOBJMETHOD_END
285};
286AC97_DECLARE(nm_ac97);
287
288/* -------------------------------------------------------------------- */
289
290static void
291nm_ackint(struct sc_info *sc, u_int32_t num)
292{
293	if (sc->type == NM256AV_PCI_ID) {
294		nm_wr(sc, NM_INT_REG, num << 1, 2);
295	} else if (sc->type == NM256ZX_PCI_ID) {
296		nm_wr(sc, NM_INT_REG, num, 4);
297	}
298}
299
300static int
301nm_loadcoeff(struct sc_info *sc, int dir, int num)
302{
303	int ofs, sz, i;
304	u_int32_t addr;
305
306	addr = (dir == PCMDIR_PLAY)? 0x01c : 0x21c;
307	if (dir == PCMDIR_REC)
308		num += 8;
309	sz = coefficientSizes[num];
310	ofs = 0;
311	while (num-- > 0)
312		ofs+= coefficientSizes[num];
313	for (i = 0; i < sz; i++)
314		nm_wrbuf(sc, sc->cbuf + i, coefficients[ofs + i], 1);
315	nm_wr(sc, addr, sc->cbuf, 4);
316	if (dir == PCMDIR_PLAY)
317		sz--;
318	nm_wr(sc, addr + 4, sc->cbuf + sz, 4);
319	return 0;
320}
321
322static int
323nm_setch(struct sc_chinfo *ch)
324{
325	struct sc_info *sc = ch->parent;
326	u_int32_t base;
327	u_int8_t x;
328
329	for (x = 0; x < 8; x++)
330		if (ch->spd < (samplerates[x] + samplerates[x + 1]) / 2)
331			break;
332
333	if (x == 8) return 1;
334
335	ch->spd = samplerates[x];
336	nm_loadcoeff(sc, ch->dir, x);
337
338	x <<= 4;
339	x &= NM_RATE_MASK;
340	if (ch->fmt & AFMT_16BIT) x |= NM_RATE_BITS_16;
341	if (AFMT_CHANNEL(ch->fmt) > 1) x |= NM_RATE_STEREO;
342
343	base = (ch->dir == PCMDIR_PLAY)? NM_PLAYBACK_REG_OFFSET : NM_RECORD_REG_OFFSET;
344	nm_wr(sc, base + NM_RATE_REG_OFFSET, x, 1);
345	return 0;
346}
347
348/* channel interface */
349static void *
350nmchan_init(kobj_t obj, void *devinfo, struct snd_dbuf *b, struct pcm_channel *c, int dir)
351{
352	struct sc_info *sc = devinfo;
353	struct sc_chinfo *ch;
354	u_int32_t chnbuf;
355
356	chnbuf = (dir == PCMDIR_PLAY)? sc->pbuf : sc->rbuf;
357	ch = (dir == PCMDIR_PLAY)? &sc->pch : &sc->rch;
358	ch->active = 0;
359	ch->blksize = 0;
360	ch->wmark = 0;
361	ch->buffer = b;
362	sndbuf_setup(ch->buffer, (u_int8_t *)rman_get_virtual(sc->buf) + chnbuf, NM_BUFFSIZE);
363	if (bootverbose)
364		device_printf(sc->dev, "%s buf %p\n", (dir == PCMDIR_PLAY)?
365			      "play" : "rec", sndbuf_getbuf(ch->buffer));
366	ch->parent = sc;
367	ch->channel = c;
368	ch->dir = dir;
369	return ch;
370}
371
372static int
373nmchan_free(kobj_t obj, void *data)
374{
375	return 0;
376}
377
378static int
379nmchan_setformat(kobj_t obj, void *data, u_int32_t format)
380{
381	struct sc_chinfo *ch = data;
382
383	ch->fmt = format;
384	return nm_setch(ch);
385}
386
387static u_int32_t
388nmchan_setspeed(kobj_t obj, void *data, u_int32_t speed)
389{
390	struct sc_chinfo *ch = data;
391
392	ch->spd = speed;
393	return nm_setch(ch)? 0 : ch->spd;
394}
395
396static u_int32_t
397nmchan_setblocksize(kobj_t obj, void *data, u_int32_t blocksize)
398{
399	struct sc_chinfo *ch = data;
400
401	ch->blksize = blocksize;
402
403	return blocksize;
404}
405
406static int
407nmchan_trigger(kobj_t obj, void *data, int go)
408{
409	struct sc_chinfo *ch = data;
410	struct sc_info *sc = ch->parent;
411	int ssz;
412
413	if (!PCMTRIG_COMMON(go))
414		return 0;
415
416	ssz = (ch->fmt & AFMT_16BIT)? 2 : 1;
417	if (AFMT_CHANNEL(ch->fmt) > 1)
418		ssz <<= 1;
419
420	if (ch->dir == PCMDIR_PLAY) {
421		if (go == PCMTRIG_START) {
422			ch->active = 1;
423			ch->wmark = ch->blksize;
424			nm_wr(sc, NM_PBUFFER_START, sc->pbuf, 4);
425			nm_wr(sc, NM_PBUFFER_END, sc->pbuf + NM_BUFFSIZE - ssz, 4);
426			nm_wr(sc, NM_PBUFFER_CURRP, sc->pbuf, 4);
427			nm_wr(sc, NM_PBUFFER_WMARK, sc->pbuf + ch->wmark, 4);
428			nm_wr(sc, NM_PLAYBACK_ENABLE_REG, NM_PLAYBACK_FREERUN |
429				NM_PLAYBACK_ENABLE_FLAG, 1);
430			nm_wr(sc, NM_AUDIO_MUTE_REG, 0, 2);
431		} else {
432			ch->active = 0;
433			nm_wr(sc, NM_PLAYBACK_ENABLE_REG, 0, 1);
434			nm_wr(sc, NM_AUDIO_MUTE_REG, NM_AUDIO_MUTE_BOTH, 2);
435		}
436	} else {
437		if (go == PCMTRIG_START) {
438			ch->active = 1;
439			ch->wmark = ch->blksize;
440			nm_wr(sc, NM_RECORD_ENABLE_REG, NM_RECORD_FREERUN |
441				NM_RECORD_ENABLE_FLAG, 1);
442			nm_wr(sc, NM_RBUFFER_START, sc->rbuf, 4);
443			nm_wr(sc, NM_RBUFFER_END, sc->rbuf + NM_BUFFSIZE, 4);
444			nm_wr(sc, NM_RBUFFER_CURRP, sc->rbuf, 4);
445			nm_wr(sc, NM_RBUFFER_WMARK, sc->rbuf + ch->wmark, 4);
446		} else {
447			ch->active = 0;
448			nm_wr(sc, NM_RECORD_ENABLE_REG, 0, 1);
449		}
450	}
451	return 0;
452}
453
454static u_int32_t
455nmchan_getptr(kobj_t obj, void *data)
456{
457	struct sc_chinfo *ch = data;
458	struct sc_info *sc = ch->parent;
459
460	if (ch->dir == PCMDIR_PLAY)
461		return nm_rd(sc, NM_PBUFFER_CURRP, 4) - sc->pbuf;
462	else
463		return nm_rd(sc, NM_RBUFFER_CURRP, 4) - sc->rbuf;
464}
465
466static struct pcmchan_caps *
467nmchan_getcaps(kobj_t obj, void *data)
468{
469	return &nm_caps;
470}
471
472static kobj_method_t nmchan_methods[] = {
473    	KOBJMETHOD(channel_init,		nmchan_init),
474    	KOBJMETHOD(channel_free,		nmchan_free),
475    	KOBJMETHOD(channel_setformat,		nmchan_setformat),
476    	KOBJMETHOD(channel_setspeed,		nmchan_setspeed),
477    	KOBJMETHOD(channel_setblocksize,	nmchan_setblocksize),
478    	KOBJMETHOD(channel_trigger,		nmchan_trigger),
479    	KOBJMETHOD(channel_getptr,		nmchan_getptr),
480    	KOBJMETHOD(channel_getcaps,		nmchan_getcaps),
481	KOBJMETHOD_END
482};
483CHANNEL_DECLARE(nmchan);
484
485/* The interrupt handler */
486static void
487nm_intr(void *p)
488{
489	struct sc_info *sc = (struct sc_info *)p;
490	int status, x;
491
492	status = nm_rd(sc, NM_INT_REG, sc->irsz);
493	if (status == 0)
494		return;
495
496	if (status & sc->playint) {
497		status &= ~sc->playint;
498		sc->pch.wmark += sc->pch.blksize;
499		sc->pch.wmark %= NM_BUFFSIZE;
500		nm_wr(sc, NM_PBUFFER_WMARK, sc->pbuf + sc->pch.wmark, 4);
501
502		nm_ackint(sc, sc->playint);
503		chn_intr(sc->pch.channel);
504	}
505	if (status & sc->recint) {
506		status &= ~sc->recint;
507		sc->rch.wmark += sc->rch.blksize;
508		sc->rch.wmark %= NM_BUFFSIZE;
509		nm_wr(sc, NM_RBUFFER_WMARK, sc->rbuf + sc->rch.wmark, 4);
510
511		nm_ackint(sc, sc->recint);
512		chn_intr(sc->rch.channel);
513	}
514	if (status & sc->misc1int) {
515		status &= ~sc->misc1int;
516		nm_ackint(sc, sc->misc1int);
517		x = nm_rd(sc, 0x400, 1);
518		nm_wr(sc, 0x400, x | 2, 1);
519	 	device_printf(sc->dev, "misc int 1\n");
520	}
521	if (status & sc->misc2int) {
522		status &= ~sc->misc2int;
523		nm_ackint(sc, sc->misc2int);
524		x = nm_rd(sc, 0x400, 1);
525		nm_wr(sc, 0x400, x & ~2, 1);
526	 	device_printf(sc->dev, "misc int 2\n");
527	}
528	if (status) {
529		nm_ackint(sc, status);
530	 	device_printf(sc->dev, "unknown int\n");
531	}
532}
533
534/* -------------------------------------------------------------------- */
535
536/*
537 * Probe and attach the card
538 */
539
540static int
541nm_init(struct sc_info *sc)
542{
543	u_int32_t ofs, i;
544
545	if (sc->type == NM256AV_PCI_ID) {
546		sc->ac97_base = NM_MIXER_OFFSET;
547		sc->ac97_status = NM_MIXER_STATUS_OFFSET;
548		sc->ac97_busy = NM_MIXER_READY_MASK;
549
550		sc->buftop = 2560 * 1024;
551
552		sc->irsz = 2;
553		sc->playint = NM_PLAYBACK_INT;
554		sc->recint = NM_RECORD_INT;
555		sc->misc1int = NM_MISC_INT_1;
556		sc->misc2int = NM_MISC_INT_2;
557	} else if (sc->type == NM256ZX_PCI_ID) {
558		sc->ac97_base = NM_MIXER_OFFSET;
559		sc->ac97_status = NM2_MIXER_STATUS_OFFSET;
560		sc->ac97_busy = NM2_MIXER_READY_MASK;
561
562		sc->buftop = (nm_rd(sc, 0xa0b, 2)? 6144 : 4096) * 1024;
563
564		sc->irsz = 4;
565		sc->playint = NM2_PLAYBACK_INT;
566		sc->recint = NM2_RECORD_INT;
567		sc->misc1int = NM2_MISC_INT_1;
568		sc->misc2int = NM2_MISC_INT_2;
569	} else return -1;
570	sc->badintr = 0;
571	ofs = sc->buftop - 0x0400;
572	sc->buftop -= 0x1400;
573
574	if (bootverbose)
575		device_printf(sc->dev, "buftop is 0x%08x\n", sc->buftop);
576 	if ((nm_rdbuf(sc, ofs, 4) & NM_SIG_MASK) == NM_SIGNATURE) {
577		i = nm_rdbuf(sc, ofs + 4, 4);
578		if (i != 0 && i != 0xffffffff) {
579			if (bootverbose)
580				device_printf(sc->dev, "buftop is changed to 0x%08x\n", i);
581			sc->buftop = i;
582		}
583	}
584
585	sc->cbuf = sc->buftop - NM_MAX_COEFFICIENT;
586	sc->rbuf = sc->cbuf - NM_BUFFSIZE;
587	sc->pbuf = sc->rbuf - NM_BUFFSIZE;
588	sc->acbuf = sc->pbuf - (NM_TOTAL_COEFF_COUNT * 4);
589
590	nm_wr(sc, 0, 0x11, 1);
591	nm_wr(sc, NM_RECORD_ENABLE_REG, 0, 1);
592	nm_wr(sc, 0x214, 0, 2);
593
594	return 0;
595}
596
597static int
598nm_pci_probe(device_t dev)
599{
600	struct sc_info *sc = NULL;
601	char *s = NULL;
602	u_int32_t subdev, i;
603
604	subdev = (pci_get_subdevice(dev) << 16) | pci_get_subvendor(dev);
605	switch (pci_get_devid(dev)) {
606	case NM256AV_PCI_ID:
607		i = 0;
608		while ((i < NUM_BADCARDS) && (badcards[i] != subdev))
609			i++;
610
611		/* Try to catch other non-ac97 cards */
612
613		if (i == NUM_BADCARDS) {
614			if (!(sc = malloc(sizeof(*sc), M_DEVBUF, M_NOWAIT | M_ZERO))) {
615				device_printf(dev, "cannot allocate softc\n");
616				return ENXIO;
617			}
618
619			sc->regid = PCIR_BAR(1);
620			sc->reg = bus_alloc_resource_any(dev, SYS_RES_MEMORY,
621							 &sc->regid,
622							 RF_ACTIVE);
623
624			if (!sc->reg) {
625				device_printf(dev, "unable to map register space\n");
626				free(sc, M_DEVBUF);
627				return ENXIO;
628			}
629
630			/*
631			 * My Panasonic CF-M2EV needs resetting device
632			 * before checking mixer is present or not.
633			 * t.ichinoseki@nifty.com.
634			 */
635			nm_wr(sc, 0, 0x11, 1); /* reset device */
636			if ((nm_rd(sc, NM_MIXER_PRESENCE, 2) &
637				NM_PRESENCE_MASK) != NM_PRESENCE_VALUE) {
638				i = 0;	/* non-ac97 card, but not listed */
639				DEB(device_printf(dev, "subdev = 0x%x - badcard?\n",
640				    subdev));
641			}
642			bus_release_resource(dev, SYS_RES_MEMORY, sc->regid,
643					     sc->reg);
644			free(sc, M_DEVBUF);
645		}
646
647		if (i == NUM_BADCARDS)
648			s = "NeoMagic 256AV";
649		DEB(else)
650			DEB(device_printf(dev, "this is a non-ac97 NM256AV, not attaching\n"));
651
652		break;
653
654	case NM256ZX_PCI_ID:
655		s = "NeoMagic 256ZX";
656		break;
657	}
658
659	if (s) device_set_desc(dev, s);
660	return s? 0 : ENXIO;
661}
662
663static int
664nm_pci_attach(device_t dev)
665{
666	struct sc_info *sc;
667	struct ac97_info *codec = NULL;
668	char 		status[SND_STATUSLEN];
669
670	sc = malloc(sizeof(*sc), M_DEVBUF, M_WAITOK | M_ZERO);
671	sc->dev = dev;
672	sc->type = pci_get_devid(dev);
673
674	pci_enable_busmaster(dev);
675
676	sc->bufid = PCIR_BAR(0);
677	sc->buf = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &sc->bufid,
678					 RF_ACTIVE);
679	sc->regid = PCIR_BAR(1);
680	sc->reg = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &sc->regid,
681					 RF_ACTIVE);
682
683	if (!sc->buf || !sc->reg) {
684		device_printf(dev, "unable to map register space\n");
685		goto bad;
686	}
687
688	if (nm_init(sc) == -1) {
689		device_printf(dev, "unable to initialize the card\n");
690		goto bad;
691	}
692
693	codec = AC97_CREATE(dev, sc, nm_ac97);
694	if (codec == NULL) goto bad;
695	if (mixer_init(dev, ac97_getmixerclass(), codec) == -1) goto bad;
696
697	sc->irqid = 0;
698	sc->irq = bus_alloc_resource_any(dev, SYS_RES_IRQ, &sc->irqid,
699					 RF_ACTIVE | RF_SHAREABLE);
700	if (!sc->irq || snd_setup_intr(dev, sc->irq, 0, nm_intr, sc, &sc->ih)) {
701		device_printf(dev, "unable to map interrupt\n");
702		goto bad;
703	}
704
705	snprintf(status, SND_STATUSLEN, "at memory 0x%jx, 0x%jx irq %jd %s",
706		 rman_get_start(sc->buf), rman_get_start(sc->reg),
707		 rman_get_start(sc->irq),PCM_KLDSTRING(snd_neomagic));
708
709	if (pcm_register(dev, sc, 1, 1)) goto bad;
710	pcm_addchan(dev, PCMDIR_REC, &nmchan_class, sc);
711	pcm_addchan(dev, PCMDIR_PLAY, &nmchan_class, sc);
712	pcm_setstatus(dev, status);
713
714	return 0;
715
716bad:
717	if (codec) ac97_destroy(codec);
718	if (sc->buf) bus_release_resource(dev, SYS_RES_MEMORY, sc->bufid, sc->buf);
719	if (sc->reg) bus_release_resource(dev, SYS_RES_MEMORY, sc->regid, sc->reg);
720	if (sc->ih) bus_teardown_intr(dev, sc->irq, sc->ih);
721	if (sc->irq) bus_release_resource(dev, SYS_RES_IRQ, sc->irqid, sc->irq);
722	free(sc, M_DEVBUF);
723	return ENXIO;
724}
725
726static int
727nm_pci_detach(device_t dev)
728{
729	int r;
730	struct sc_info *sc;
731
732	r = pcm_unregister(dev);
733	if (r)
734		return r;
735
736	sc = pcm_getdevinfo(dev);
737	bus_release_resource(dev, SYS_RES_MEMORY, sc->bufid, sc->buf);
738	bus_release_resource(dev, SYS_RES_MEMORY, sc->regid, sc->reg);
739	bus_teardown_intr(dev, sc->irq, sc->ih);
740	bus_release_resource(dev, SYS_RES_IRQ, sc->irqid, sc->irq);
741	free(sc, M_DEVBUF);
742
743	return 0;
744}
745
746static int
747nm_pci_suspend(device_t dev)
748{
749	struct sc_info *sc;
750
751	sc = pcm_getdevinfo(dev);
752
753	/* stop playing */
754	if (sc->pch.active) {
755		nm_wr(sc, NM_PLAYBACK_ENABLE_REG, 0, 1);
756		nm_wr(sc, NM_AUDIO_MUTE_REG, NM_AUDIO_MUTE_BOTH, 2);
757	}
758	/* stop recording */
759	if (sc->rch.active) {
760		nm_wr(sc, NM_RECORD_ENABLE_REG, 0, 1);
761	}
762	return 0;
763}
764
765static int
766nm_pci_resume(device_t dev)
767{
768	struct sc_info *sc;
769
770	sc = pcm_getdevinfo(dev);
771
772	/*
773	 * Reinit audio device.
774	 * Don't call nm_init(). It would change buftop if X ran or
775	 * is running. This makes playing and recording buffer address
776	 * shift but these buffers of channel layer are not changed.
777	 * As a result of this inconsistency, periodic noise will be
778	 * generated while playing.
779	 */
780	nm_wr(sc, 0, 0x11, 1);
781	nm_wr(sc, 0x214, 0, 2);
782
783	/* Reinit mixer */
784    	if (mixer_reinit(dev) == -1) {
785		device_printf(dev, "unable to reinitialize the mixer\n");
786		return ENXIO;
787	}
788	/* restart playing */
789	if (sc->pch.active) {
790		nm_wr(sc, NM_PLAYBACK_ENABLE_REG, NM_PLAYBACK_FREERUN |
791			  NM_PLAYBACK_ENABLE_FLAG, 1);
792		nm_wr(sc, NM_AUDIO_MUTE_REG, 0, 2);
793	}
794	/* restart recording */
795	if (sc->rch.active) {
796		nm_wr(sc, NM_RECORD_ENABLE_REG, NM_RECORD_FREERUN |
797			  NM_RECORD_ENABLE_FLAG, 1);
798	}
799	return 0;
800}
801
802static device_method_t nm_methods[] = {
803	/* Device interface */
804	DEVMETHOD(device_probe,		nm_pci_probe),
805	DEVMETHOD(device_attach,	nm_pci_attach),
806	DEVMETHOD(device_detach,	nm_pci_detach),
807	DEVMETHOD(device_suspend,	nm_pci_suspend),
808	DEVMETHOD(device_resume,	nm_pci_resume),
809	{ 0, 0 }
810};
811
812static driver_t nm_driver = {
813	"pcm",
814	nm_methods,
815	PCM_SOFTC_SIZE,
816};
817
818DRIVER_MODULE(snd_neomagic, pci, nm_driver, pcm_devclass, 0, 0);
819MODULE_DEPEND(snd_neomagic, sound, SOUND_MINVER, SOUND_PREFVER, SOUND_MAXVER);
820MODULE_VERSION(snd_neomagic, 1);
821