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