Rename sprintf -> ksprintf
[dfdiff.git] / sys / dev / sound / pci / neomagic.c
bloba4a21a59fd28f0d327731d569b6419133f0f0e1d
1 /*
2 * Copyright (c) 1999 Cameron Grant <gandalf@vilnya.demon.co.uk>
3 * All rights reserved.
5 * Derived from the public domain Linux driver
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.
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.
28 * $FreeBSD: src/sys/dev/sound/pci/neomagic.c,v 1.7.2.11 2002/04/22 15:49:32 cg Exp $
29 * $DragonFly: src/sys/dev/sound/pci/neomagic.c,v 1.6 2006/12/20 18:14:40 dillon Exp $
32 #include <dev/sound/pcm/sound.h>
33 #include <dev/sound/pcm/ac97.h>
34 #include <dev/sound/pci/neomagic.h>
35 #include <dev/sound/pci/neomagic-coeff.h>
37 #include <bus/pci/pcireg.h>
38 #include <bus/pci/pcivar.h>
40 SND_DECLARE_FILE("$DragonFly: src/sys/dev/sound/pci/neomagic.c,v 1.6 2006/12/20 18:14:40 dillon Exp $");
42 /* -------------------------------------------------------------------- */
44 #define NM_BUFFSIZE 16384
46 #define NM256AV_PCI_ID 0x800510c8
47 #define NM256ZX_PCI_ID 0x800610c8
49 struct sc_info;
51 /* channel registers */
52 struct sc_chinfo {
53 int active, spd, dir, fmt;
54 u_int32_t blksize, wmark;
55 struct snd_dbuf *buffer;
56 struct pcm_channel *channel;
57 struct sc_info *parent;
60 /* device private data */
61 struct sc_info {
62 device_t dev;
63 u_int32_t type;
65 struct resource *reg, *irq, *buf;
66 int regid, irqid, bufid;
67 void *ih;
69 u_int32_t ac97_base, ac97_status, ac97_busy;
70 u_int32_t buftop, pbuf, rbuf, cbuf, acbuf;
71 u_int32_t playint, recint, misc1int, misc2int;
72 u_int32_t irsz, badintr;
74 struct sc_chinfo pch, rch;
77 /* -------------------------------------------------------------------- */
80 * prototypes
83 /* stuff */
84 static int nm_loadcoeff(struct sc_info *sc, int dir, int num);
85 static int nm_setch(struct sc_chinfo *ch);
86 static int nm_init(struct sc_info *);
87 static void nm_intr(void *);
89 /* talk to the card */
90 static u_int32_t nm_rd(struct sc_info *, int, int);
91 static void nm_wr(struct sc_info *, int, u_int32_t, int);
92 static u_int32_t nm_rdbuf(struct sc_info *, int, int);
93 static void nm_wrbuf(struct sc_info *, int, u_int32_t, int);
95 static u_int32_t badcards[] = {
96 0x0007103c,
97 0x008f1028,
98 0x00dd1014,
99 0x8005110a,
101 #define NUM_BADCARDS (sizeof(badcards) / sizeof(u_int32_t))
103 /* The actual rates supported by the card. */
104 static int samplerates[9] = {
105 8000,
106 11025,
107 16000,
108 22050,
109 24000,
110 32000,
111 44100,
112 48000,
113 99999999
116 /* -------------------------------------------------------------------- */
118 static u_int32_t nm_fmt[] = {
119 AFMT_U8,
120 AFMT_STEREO | AFMT_U8,
121 AFMT_S16_LE,
122 AFMT_STEREO | AFMT_S16_LE,
125 static struct pcmchan_caps nm_caps = {4000, 48000, nm_fmt, 0};
127 /* -------------------------------------------------------------------- */
129 /* Hardware */
130 static u_int32_t
131 nm_rd(struct sc_info *sc, int regno, int size)
133 bus_space_tag_t st = rman_get_bustag(sc->reg);
134 bus_space_handle_t sh = rman_get_bushandle(sc->reg);
136 switch (size) {
137 case 1:
138 return bus_space_read_1(st, sh, regno);
139 case 2:
140 return bus_space_read_2(st, sh, regno);
141 case 4:
142 return bus_space_read_4(st, sh, regno);
143 default:
144 return 0xffffffff;
148 static void
149 nm_wr(struct sc_info *sc, int regno, u_int32_t data, int size)
151 bus_space_tag_t st = rman_get_bustag(sc->reg);
152 bus_space_handle_t sh = rman_get_bushandle(sc->reg);
154 switch (size) {
155 case 1:
156 bus_space_write_1(st, sh, regno, data);
157 break;
158 case 2:
159 bus_space_write_2(st, sh, regno, data);
160 break;
161 case 4:
162 bus_space_write_4(st, sh, regno, data);
163 break;
167 static u_int32_t
168 nm_rdbuf(struct sc_info *sc, int regno, int size)
170 bus_space_tag_t st = rman_get_bustag(sc->buf);
171 bus_space_handle_t sh = rman_get_bushandle(sc->buf);
173 switch (size) {
174 case 1:
175 return bus_space_read_1(st, sh, regno);
176 case 2:
177 return bus_space_read_2(st, sh, regno);
178 case 4:
179 return bus_space_read_4(st, sh, regno);
180 default:
181 return 0xffffffff;
185 static void
186 nm_wrbuf(struct sc_info *sc, int regno, u_int32_t data, int size)
188 bus_space_tag_t st = rman_get_bustag(sc->buf);
189 bus_space_handle_t sh = rman_get_bushandle(sc->buf);
191 switch (size) {
192 case 1:
193 bus_space_write_1(st, sh, regno, data);
194 break;
195 case 2:
196 bus_space_write_2(st, sh, regno, data);
197 break;
198 case 4:
199 bus_space_write_4(st, sh, regno, data);
200 break;
204 /* -------------------------------------------------------------------- */
205 /* ac97 codec */
206 static int
207 nm_waitcd(struct sc_info *sc)
209 int cnt = 10;
210 int fail = 1;
212 while (cnt-- > 0) {
213 if (nm_rd(sc, sc->ac97_status, 2) & sc->ac97_busy) {
214 DELAY(100);
215 } else {
216 fail = 0;
217 break;
220 return (fail);
223 static u_int32_t
224 nm_initcd(kobj_t obj, void *devinfo)
226 struct sc_info *sc = (struct sc_info *)devinfo;
228 nm_wr(sc, 0x6c0, 0x01, 1);
229 nm_wr(sc, 0x6cc, 0x87, 1);
230 nm_wr(sc, 0x6cc, 0x80, 1);
231 nm_wr(sc, 0x6cc, 0x00, 1);
232 return 1;
235 static int
236 nm_rdcd(kobj_t obj, void *devinfo, int regno)
238 struct sc_info *sc = (struct sc_info *)devinfo;
239 u_int32_t x;
241 if (!nm_waitcd(sc)) {
242 x = nm_rd(sc, sc->ac97_base + regno, 2);
243 DELAY(1000);
244 return x;
245 } else {
246 device_printf(sc->dev, "ac97 codec not ready\n");
247 return -1;
251 static int
252 nm_wrcd(kobj_t obj, void *devinfo, int regno, u_int32_t data)
254 struct sc_info *sc = (struct sc_info *)devinfo;
255 int cnt = 3;
257 if (!nm_waitcd(sc)) {
258 while (cnt-- > 0) {
259 nm_wr(sc, sc->ac97_base + regno, data, 2);
260 if (!nm_waitcd(sc)) {
261 DELAY(1000);
262 return 0;
266 device_printf(sc->dev, "ac97 codec not ready\n");
267 return -1;
270 static kobj_method_t nm_ac97_methods[] = {
271 KOBJMETHOD(ac97_init, nm_initcd),
272 KOBJMETHOD(ac97_read, nm_rdcd),
273 KOBJMETHOD(ac97_write, nm_wrcd),
274 { 0, 0 }
276 AC97_DECLARE(nm_ac97);
278 /* -------------------------------------------------------------------- */
280 static void
281 nm_ackint(struct sc_info *sc, u_int32_t num)
283 if (sc->type == NM256AV_PCI_ID) {
284 nm_wr(sc, NM_INT_REG, num << 1, 2);
285 } else if (sc->type == NM256ZX_PCI_ID) {
286 nm_wr(sc, NM_INT_REG, num, 4);
290 static int
291 nm_loadcoeff(struct sc_info *sc, int dir, int num)
293 int ofs, sz, i;
294 u_int32_t addr;
296 addr = (dir == PCMDIR_PLAY)? 0x01c : 0x21c;
297 if (dir == PCMDIR_REC)
298 num += 8;
299 sz = coefficientSizes[num];
300 ofs = 0;
301 while (num-- > 0)
302 ofs+= coefficientSizes[num];
303 for (i = 0; i < sz; i++)
304 nm_wrbuf(sc, sc->cbuf + i, coefficients[ofs + i], 1);
305 nm_wr(sc, addr, sc->cbuf, 4);
306 if (dir == PCMDIR_PLAY)
307 sz--;
308 nm_wr(sc, addr + 4, sc->cbuf + sz, 4);
309 return 0;
312 static int
313 nm_setch(struct sc_chinfo *ch)
315 struct sc_info *sc = ch->parent;
316 u_int32_t base;
317 u_int8_t x;
319 for (x = 0; x < 8; x++)
320 if (ch->spd < (samplerates[x] + samplerates[x + 1]) / 2)
321 break;
323 if (x == 8) return 1;
325 ch->spd = samplerates[x];
326 nm_loadcoeff(sc, ch->dir, x);
328 x <<= 4;
329 x &= NM_RATE_MASK;
330 if (ch->fmt & AFMT_16BIT) x |= NM_RATE_BITS_16;
331 if (ch->fmt & AFMT_STEREO) x |= NM_RATE_STEREO;
333 base = (ch->dir == PCMDIR_PLAY)? NM_PLAYBACK_REG_OFFSET : NM_RECORD_REG_OFFSET;
334 nm_wr(sc, base + NM_RATE_REG_OFFSET, x, 1);
335 return 0;
338 /* channel interface */
339 static void *
340 nmchan_init(kobj_t obj, void *devinfo, struct snd_dbuf *b, struct pcm_channel *c, int dir)
342 struct sc_info *sc = devinfo;
343 struct sc_chinfo *ch;
344 u_int32_t chnbuf;
346 chnbuf = (dir == PCMDIR_PLAY)? sc->pbuf : sc->rbuf;
347 ch = (dir == PCMDIR_PLAY)? &sc->pch : &sc->rch;
348 ch->active = 0;
349 ch->blksize = 0;
350 ch->wmark = 0;
351 ch->buffer = b;
352 sndbuf_setup(ch->buffer, (u_int8_t *)rman_get_virtual(sc->buf) + chnbuf, NM_BUFFSIZE);
353 if (bootverbose)
354 device_printf(sc->dev, "%s buf %p\n", (dir == PCMDIR_PLAY)?
355 "play" : "rec", sndbuf_getbuf(ch->buffer));
356 ch->parent = sc;
357 ch->channel = c;
358 ch->dir = dir;
359 return ch;
362 static int
363 nmchan_free(kobj_t obj, void *data)
365 return 0;
368 static int
369 nmchan_setformat(kobj_t obj, void *data, u_int32_t format)
371 struct sc_chinfo *ch = data;
373 ch->fmt = format;
374 return nm_setch(ch);
377 static int
378 nmchan_setspeed(kobj_t obj, void *data, u_int32_t speed)
380 struct sc_chinfo *ch = data;
382 ch->spd = speed;
383 return nm_setch(ch)? 0 : ch->spd;
386 static int
387 nmchan_setblocksize(kobj_t obj, void *data, u_int32_t blocksize)
389 struct sc_chinfo *ch = data;
391 ch->blksize = blocksize;
393 return blocksize;
396 static int
397 nmchan_trigger(kobj_t obj, void *data, int go)
399 struct sc_chinfo *ch = data;
400 struct sc_info *sc = ch->parent;
401 int ssz;
403 if (go == PCMTRIG_EMLDMAWR || go == PCMTRIG_EMLDMARD)
404 return 0;
406 ssz = (ch->fmt & AFMT_16BIT)? 2 : 1;
407 if (ch->fmt & AFMT_STEREO)
408 ssz <<= 1;
410 if (ch->dir == PCMDIR_PLAY) {
411 if (go == PCMTRIG_START) {
412 ch->active = 1;
413 ch->wmark = ch->blksize;
414 nm_wr(sc, NM_PBUFFER_START, sc->pbuf, 4);
415 nm_wr(sc, NM_PBUFFER_END, sc->pbuf + NM_BUFFSIZE - ssz, 4);
416 nm_wr(sc, NM_PBUFFER_CURRP, sc->pbuf, 4);
417 nm_wr(sc, NM_PBUFFER_WMARK, sc->pbuf + ch->wmark, 4);
418 nm_wr(sc, NM_PLAYBACK_ENABLE_REG, NM_PLAYBACK_FREERUN |
419 NM_PLAYBACK_ENABLE_FLAG, 1);
420 nm_wr(sc, NM_AUDIO_MUTE_REG, 0, 2);
421 } else {
422 ch->active = 0;
423 nm_wr(sc, NM_PLAYBACK_ENABLE_REG, 0, 1);
424 nm_wr(sc, NM_AUDIO_MUTE_REG, NM_AUDIO_MUTE_BOTH, 2);
426 } else {
427 if (go == PCMTRIG_START) {
428 ch->active = 1;
429 ch->wmark = ch->blksize;
430 nm_wr(sc, NM_RECORD_ENABLE_REG, NM_RECORD_FREERUN |
431 NM_RECORD_ENABLE_FLAG, 1);
432 nm_wr(sc, NM_RBUFFER_START, sc->rbuf, 4);
433 nm_wr(sc, NM_RBUFFER_END, sc->rbuf + NM_BUFFSIZE, 4);
434 nm_wr(sc, NM_RBUFFER_CURRP, sc->rbuf, 4);
435 nm_wr(sc, NM_RBUFFER_WMARK, sc->rbuf + ch->wmark, 4);
436 } else {
437 ch->active = 0;
438 nm_wr(sc, NM_RECORD_ENABLE_REG, 0, 1);
441 return 0;
444 static int
445 nmchan_getptr(kobj_t obj, void *data)
447 struct sc_chinfo *ch = data;
448 struct sc_info *sc = ch->parent;
450 if (ch->dir == PCMDIR_PLAY)
451 return nm_rd(sc, NM_PBUFFER_CURRP, 4) - sc->pbuf;
452 else
453 return nm_rd(sc, NM_RBUFFER_CURRP, 4) - sc->rbuf;
456 static struct pcmchan_caps *
457 nmchan_getcaps(kobj_t obj, void *data)
459 return &nm_caps;
462 static kobj_method_t nmchan_methods[] = {
463 KOBJMETHOD(channel_init, nmchan_init),
464 KOBJMETHOD(channel_free, nmchan_free),
465 KOBJMETHOD(channel_setformat, nmchan_setformat),
466 KOBJMETHOD(channel_setspeed, nmchan_setspeed),
467 KOBJMETHOD(channel_setblocksize, nmchan_setblocksize),
468 KOBJMETHOD(channel_trigger, nmchan_trigger),
469 KOBJMETHOD(channel_getptr, nmchan_getptr),
470 KOBJMETHOD(channel_getcaps, nmchan_getcaps),
471 { 0, 0 }
473 CHANNEL_DECLARE(nmchan);
475 /* The interrupt handler */
476 static void
477 nm_intr(void *p)
479 struct sc_info *sc = (struct sc_info *)p;
480 int status, x;
482 status = nm_rd(sc, NM_INT_REG, sc->irsz);
483 if (status == 0)
484 return;
486 if (status & sc->playint) {
487 status &= ~sc->playint;
488 sc->pch.wmark += sc->pch.blksize;
489 sc->pch.wmark %= NM_BUFFSIZE;
490 nm_wr(sc, NM_PBUFFER_WMARK, sc->pbuf + sc->pch.wmark, 4);
492 nm_ackint(sc, sc->playint);
493 chn_intr(sc->pch.channel);
495 if (status & sc->recint) {
496 status &= ~sc->recint;
497 sc->rch.wmark += sc->rch.blksize;
498 sc->rch.wmark %= NM_BUFFSIZE;
499 nm_wr(sc, NM_RBUFFER_WMARK, sc->rbuf + sc->rch.wmark, 4);
501 nm_ackint(sc, sc->recint);
502 chn_intr(sc->rch.channel);
504 if (status & sc->misc1int) {
505 status &= ~sc->misc1int;
506 nm_ackint(sc, sc->misc1int);
507 x = nm_rd(sc, 0x400, 1);
508 nm_wr(sc, 0x400, x | 2, 1);
509 device_printf(sc->dev, "misc int 1\n");
511 if (status & sc->misc2int) {
512 status &= ~sc->misc2int;
513 nm_ackint(sc, sc->misc2int);
514 x = nm_rd(sc, 0x400, 1);
515 nm_wr(sc, 0x400, x & ~2, 1);
516 device_printf(sc->dev, "misc int 2\n");
518 if (status) {
519 nm_ackint(sc, status);
520 device_printf(sc->dev, "unknown int\n");
524 /* -------------------------------------------------------------------- */
527 * Probe and attach the card
530 static int
531 nm_init(struct sc_info *sc)
533 u_int32_t ofs, i;
535 if (sc->type == NM256AV_PCI_ID) {
536 sc->ac97_base = NM_MIXER_OFFSET;
537 sc->ac97_status = NM_MIXER_STATUS_OFFSET;
538 sc->ac97_busy = NM_MIXER_READY_MASK;
540 sc->buftop = 2560 * 1024;
542 sc->irsz = 2;
543 sc->playint = NM_PLAYBACK_INT;
544 sc->recint = NM_RECORD_INT;
545 sc->misc1int = NM_MISC_INT_1;
546 sc->misc2int = NM_MISC_INT_2;
547 } else if (sc->type == NM256ZX_PCI_ID) {
548 sc->ac97_base = NM_MIXER_OFFSET;
549 sc->ac97_status = NM2_MIXER_STATUS_OFFSET;
550 sc->ac97_busy = NM2_MIXER_READY_MASK;
552 sc->buftop = (nm_rd(sc, 0xa0b, 2)? 6144 : 4096) * 1024;
554 sc->irsz = 4;
555 sc->playint = NM2_PLAYBACK_INT;
556 sc->recint = NM2_RECORD_INT;
557 sc->misc1int = NM2_MISC_INT_1;
558 sc->misc2int = NM2_MISC_INT_2;
559 } else return -1;
560 sc->badintr = 0;
561 ofs = sc->buftop - 0x0400;
562 sc->buftop -= 0x1400;
564 if (bootverbose)
565 device_printf(sc->dev, "buftop is 0x%08x\n", sc->buftop);
566 if ((nm_rdbuf(sc, ofs, 4) & NM_SIG_MASK) == NM_SIGNATURE) {
567 i = nm_rdbuf(sc, ofs + 4, 4);
568 if (i != 0 && i != 0xffffffff) {
569 if (bootverbose)
570 device_printf(sc->dev, "buftop is changed to 0x%08x\n", i);
571 sc->buftop = i;
575 sc->cbuf = sc->buftop - NM_MAX_COEFFICIENT;
576 sc->rbuf = sc->cbuf - NM_BUFFSIZE;
577 sc->pbuf = sc->rbuf - NM_BUFFSIZE;
578 sc->acbuf = sc->pbuf - (NM_TOTAL_COEFF_COUNT * 4);
580 nm_wr(sc, 0, 0x11, 1);
581 nm_wr(sc, NM_RECORD_ENABLE_REG, 0, 1);
582 nm_wr(sc, 0x214, 0, 2);
584 return 0;
587 static int
588 nm_pci_probe(device_t dev)
590 struct sc_info *sc = NULL;
591 char *s = NULL;
592 u_int32_t subdev, i, data;
594 subdev = (pci_get_subdevice(dev) << 16) | pci_get_subvendor(dev);
595 switch (pci_get_devid(dev)) {
596 case NM256AV_PCI_ID:
597 i = 0;
598 while ((i < NUM_BADCARDS) && (badcards[i] != subdev))
599 i++;
601 /* Try to catch other non-ac97 cards */
603 if (i == NUM_BADCARDS) {
604 if (!(sc = kmalloc(sizeof(*sc), M_DEVBUF, M_NOWAIT | M_ZERO))) {
605 device_printf(dev, "cannot allocate softc\n");
606 return ENXIO;
609 data = pci_read_config(dev, PCIR_COMMAND, 2);
610 pci_write_config(dev, PCIR_COMMAND, data |
611 PCIM_CMD_PORTEN | PCIM_CMD_MEMEN |
612 PCIM_CMD_BUSMASTEREN, 2);
614 sc->regid = PCIR_MAPS + 4;
615 sc->reg = bus_alloc_resource(dev, SYS_RES_MEMORY,
616 &sc->regid, 0, ~0, 1,
617 RF_ACTIVE);
619 if (!sc->reg) {
620 device_printf(dev, "unable to map register space\n");
621 pci_write_config(dev, PCIR_COMMAND, data, 2);
622 kfree(sc, M_DEVBUF);
623 return ENXIO;
627 * My Panasonic CF-M2EV needs resetting device
628 * before checking mixer is present or not.
629 * t.ichinoseki@nifty.com.
631 nm_wr(sc, 0, 0x11, 1); /* reset device */
632 if ((nm_rd(sc, NM_MIXER_PRESENCE, 2) &
633 NM_PRESENCE_MASK) != NM_PRESENCE_VALUE) {
634 i = 0; /* non-ac97 card, but not listed */
635 DEB(device_printf(dev, "subdev = 0x%x - badcard?\n",
636 subdev));
638 pci_write_config(dev, PCIR_COMMAND, data, 2);
639 bus_release_resource(dev, SYS_RES_MEMORY, sc->regid,
640 sc->reg);
641 kfree(sc, M_DEVBUF);
644 if (i == NUM_BADCARDS)
645 s = "NeoMagic 256AV";
646 DEB(else)
647 DEB(device_printf(dev, "this is a non-ac97 NM256AV, not attaching\n"));
649 break;
651 case NM256ZX_PCI_ID:
652 s = "NeoMagic 256ZX";
653 break;
656 if (s) device_set_desc(dev, s);
657 return s? 0 : ENXIO;
660 static int
661 nm_pci_attach(device_t dev)
663 u_int32_t data;
664 struct sc_info *sc;
665 struct ac97_info *codec = 0;
666 char status[SND_STATUSLEN];
668 if ((sc = kmalloc(sizeof(*sc), M_DEVBUF, M_NOWAIT | M_ZERO)) == NULL) {
669 device_printf(dev, "cannot allocate softc\n");
670 return ENXIO;
673 sc->dev = dev;
674 sc->type = pci_get_devid(dev);
676 data = pci_read_config(dev, PCIR_COMMAND, 2);
677 data |= (PCIM_CMD_PORTEN|PCIM_CMD_MEMEN|PCIM_CMD_BUSMASTEREN);
678 pci_write_config(dev, PCIR_COMMAND, data, 2);
679 data = pci_read_config(dev, PCIR_COMMAND, 2);
681 sc->bufid = PCIR_MAPS;
682 sc->buf = bus_alloc_resource(dev, SYS_RES_MEMORY, &sc->bufid,
683 0, ~0, 1, RF_ACTIVE);
684 sc->regid = PCIR_MAPS + 4;
685 sc->reg = bus_alloc_resource(dev, SYS_RES_MEMORY, &sc->regid,
686 0, ~0, 1, RF_ACTIVE);
688 if (!sc->buf || !sc->reg) {
689 device_printf(dev, "unable to map register space\n");
690 goto bad;
693 if (nm_init(sc) == -1) {
694 device_printf(dev, "unable to initialize the card\n");
695 goto bad;
698 codec = AC97_CREATE(dev, sc, nm_ac97);
699 if (codec == NULL) goto bad;
700 if (mixer_init(dev, ac97_getmixerclass(), codec) == -1) goto bad;
702 sc->irqid = 0;
703 sc->irq = bus_alloc_resource(dev, SYS_RES_IRQ, &sc->irqid,
704 0, ~0, 1, RF_ACTIVE | RF_SHAREABLE);
705 if (!sc->irq || snd_setup_intr(dev, sc->irq, 0, nm_intr, sc, &sc->ih, NULL)) {
706 device_printf(dev, "unable to map interrupt\n");
707 goto bad;
710 ksnprintf(status, SND_STATUSLEN, "at memory 0x%lx, 0x%lx irq %ld",
711 rman_get_start(sc->buf), rman_get_start(sc->reg),
712 rman_get_start(sc->irq));
714 if (pcm_register(dev, sc, 1, 1)) goto bad;
715 pcm_addchan(dev, PCMDIR_REC, &nmchan_class, sc);
716 pcm_addchan(dev, PCMDIR_PLAY, &nmchan_class, sc);
717 pcm_setstatus(dev, status);
719 return 0;
721 bad:
722 if (codec) ac97_destroy(codec);
723 if (sc->buf) bus_release_resource(dev, SYS_RES_MEMORY, sc->bufid, sc->buf);
724 if (sc->reg) bus_release_resource(dev, SYS_RES_MEMORY, sc->regid, sc->reg);
725 if (sc->ih) bus_teardown_intr(dev, sc->irq, sc->ih);
726 if (sc->irq) bus_release_resource(dev, SYS_RES_IRQ, sc->irqid, sc->irq);
727 kfree(sc, M_DEVBUF);
728 return ENXIO;
731 static int
732 nm_pci_detach(device_t dev)
734 int r;
735 struct sc_info *sc;
737 r = pcm_unregister(dev);
738 if (r)
739 return r;
741 sc = pcm_getdevinfo(dev);
742 bus_release_resource(dev, SYS_RES_MEMORY, sc->bufid, sc->buf);
743 bus_release_resource(dev, SYS_RES_MEMORY, sc->regid, sc->reg);
744 bus_teardown_intr(dev, sc->irq, sc->ih);
745 bus_release_resource(dev, SYS_RES_IRQ, sc->irqid, sc->irq);
746 kfree(sc, M_DEVBUF);
748 return 0;
751 static int
752 nm_pci_suspend(device_t dev)
754 struct sc_info *sc;
756 sc = pcm_getdevinfo(dev);
758 /* stop playing */
759 if (sc->pch.active) {
760 nm_wr(sc, NM_PLAYBACK_ENABLE_REG, 0, 1);
761 nm_wr(sc, NM_AUDIO_MUTE_REG, NM_AUDIO_MUTE_BOTH, 2);
763 /* stop recording */
764 if (sc->rch.active) {
765 nm_wr(sc, NM_RECORD_ENABLE_REG, 0, 1);
767 return 0;
770 static int
771 nm_pci_resume(device_t dev)
773 struct sc_info *sc;
775 sc = pcm_getdevinfo(dev);
778 * Reinit audio device.
779 * Don't call nm_init(). It would change buftop if X ran or
780 * is running. This makes playing and recording buffer address
781 * shift but these buffers of channel layer are not changed.
782 * As a result of this inconsistency, periodic noise will be
783 * generated while playing.
785 nm_wr(sc, 0, 0x11, 1);
786 nm_wr(sc, 0x214, 0, 2);
788 /* Reinit mixer */
789 if (mixer_reinit(dev) == -1) {
790 device_printf(dev, "unable to reinitialize the mixer\n");
791 return ENXIO;
793 /* restart playing */
794 if (sc->pch.active) {
795 nm_wr(sc, NM_PLAYBACK_ENABLE_REG, NM_PLAYBACK_FREERUN |
796 NM_PLAYBACK_ENABLE_FLAG, 1);
797 nm_wr(sc, NM_AUDIO_MUTE_REG, 0, 2);
799 /* restart recording */
800 if (sc->rch.active) {
801 nm_wr(sc, NM_RECORD_ENABLE_REG, NM_RECORD_FREERUN |
802 NM_RECORD_ENABLE_FLAG, 1);
804 return 0;
807 static device_method_t nm_methods[] = {
808 /* Device interface */
809 DEVMETHOD(device_probe, nm_pci_probe),
810 DEVMETHOD(device_attach, nm_pci_attach),
811 DEVMETHOD(device_detach, nm_pci_detach),
812 DEVMETHOD(device_suspend, nm_pci_suspend),
813 DEVMETHOD(device_resume, nm_pci_resume),
814 { 0, 0 }
817 static driver_t nm_driver = {
818 "pcm",
819 nm_methods,
820 PCM_SOFTC_SIZE,
823 DRIVER_MODULE(snd_neomagic, pci, nm_driver, pcm_devclass, 0, 0);
824 MODULE_DEPEND(snd_neomagic, snd_pcm, PCM_MINVER, PCM_PREFVER, PCM_MAXVER);
825 MODULE_VERSION(snd_neomagic, 1);