1 /* $OpenBSD: neo.c,v 1.16 2003/04/27 11:22:53 ho 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 two ring buffers out of its
65 * memory. How 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 * might 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 over 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 * the glitches due to drivers that spend too 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 detection 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 void *powerhook;
160 };
161
162 /* -------------------------------------------------------------------- */
163
164 /*
165 * prototypes
166 */
167
168 static int nm_waitcd(struct neo_softc *sc);
169 static int nm_loadcoeff(struct neo_softc *sc, int dir, int num);
170 static int nm_init(struct neo_softc *);
171
172 int nmchan_getptr(struct neo_softc *, int);
173 /* talk to the card */
174 static u_int32_t nm_rd(struct neo_softc *, int, int);
175 static void nm_wr(struct neo_softc *, int, u_int32_t, int);
176 static u_int32_t nm_rdbuf(struct neo_softc *, int, int);
177 static void nm_wrbuf(struct neo_softc *, int, u_int32_t, int);
178
179 int neo_match(struct device *, void *, void *);
180 void neo_attach(struct device *, struct device *, void *);
181 int neo_intr(void *);
182
183 int neo_open(void *, int);
184 void neo_close(void *);
185 int neo_query_encoding(void *, struct audio_encoding *);
186 int neo_set_params(void *, int, int, struct audio_params *, struct audio_params *);
187 int neo_round_blocksize(void *, int);
188 int neo_trigger_output(void *, void *, void *, int, void (*)(void *),
189 void *, struct audio_params *);
190 int neo_trigger_input(void *, void *, void *, int, void (*)(void *),
191 void *, struct audio_params *);
192 int neo_halt_output(void *);
193 int neo_halt_input(void *);
194 int neo_getdev(void *, struct audio_device *);
195 int neo_mixer_set_port(void *, mixer_ctrl_t *);
196 int neo_mixer_get_port(void *, mixer_ctrl_t *);
197 int neo_attach_codec(void *sc, struct ac97_codec_if *);
198 int neo_read_codec(void *sc, u_int8_t a, u_int16_t *d);
199 int neo_write_codec(void *sc, u_int8_t a, u_int16_t d);
200 void neo_reset_codec(void *sc);
201 enum ac97_host_flags neo_flags_codec(void *sc);
202 int neo_query_devinfo(void *, mixer_devinfo_t *);
203 void *neo_malloc(void *, int, size_t, int, int);
204 void neo_free(void *, void *, int);
205 size_t neo_round_buffersize(void *, int, size_t);
206 int neo_get_props(void *);
207 void neo_set_mixer(struct neo_softc *sc, int a, int d);
208 void neo_power(int why, void *arg);
209
210
211 struct cfdriver neo_cd = {
212 NULL, "neo", DV_DULL
213 };
214
215
216 struct cfattach neo_ca = {
217 sizeof(struct neo_softc), neo_match, neo_attach
218 };
219
220
221 struct audio_device neo_device = {
222 "NeoMagic 256",
223 "",
224 "neo"
225 };
226
227 #if 0
228 static u_int32_t badcards[] = {
229 0x0007103c,
230 0x008f1028,
231 };
232 #endif
233
234 #define NUM_BADCARDS (sizeof(badcards) / sizeof(u_int32_t))
235
236 /* The actual rates supported by the card. */
237 static int samplerates[9] = {
238 8000,
239 11025,
240 16000,
241 22050,
242 24000,
243 32000,
244 44100,
245 48000,
246 99999999
247 };
248
249 /* -------------------------------------------------------------------- */
250
251 struct audio_hw_if neo_hw_if = {
252 neo_open,
253 neo_close,
254 NULL,
255 neo_query_encoding,
256 neo_set_params,
257 #if 1
258 neo_round_blocksize,
259 #else
260 NULL,
261 #endif
262 NULL,
263 NULL,
264 NULL,
265 NULL,
266 NULL,
267 neo_halt_output,
268 neo_halt_input,
269 NULL,
270 neo_getdev,
271 NULL,
272 neo_mixer_set_port,
273 neo_mixer_get_port,
274 neo_query_devinfo,
275 neo_malloc,
276 neo_free,
277 neo_round_buffersize,
278 0, /* neo_mappage, */
279 neo_get_props,
280 neo_trigger_output,
281 neo_trigger_input,
282
283 };
284
285 /* -------------------------------------------------------------------- */
286
287 /* Hardware */
288 static u_int32_t
nm_rd(struct neo_softc * sc,int regno,int size)289 nm_rd(struct neo_softc *sc, int regno, int size)
290 {
291 bus_space_tag_t st = sc->regiot;
292 bus_space_handle_t sh = sc->regioh;
293
294 switch (size) {
295 case 1:
296 return bus_space_read_1(st, sh, regno);
297 case 2:
298 return bus_space_read_2(st, sh, regno);
299 case 4:
300 return bus_space_read_4(st, sh, regno);
301 default:
302 return (0xffffffff);
303 }
304 }
305
306 static void
nm_wr(struct neo_softc * sc,int regno,u_int32_t data,int size)307 nm_wr(struct neo_softc *sc, int regno, u_int32_t data, int size)
308 {
309 bus_space_tag_t st = sc->regiot;
310 bus_space_handle_t sh = sc->regioh;
311
312 switch (size) {
313 case 1:
314 bus_space_write_1(st, sh, regno, data);
315 break;
316 case 2:
317 bus_space_write_2(st, sh, regno, data);
318 break;
319 case 4:
320 bus_space_write_4(st, sh, regno, data);
321 break;
322 }
323 }
324
325 static u_int32_t
nm_rdbuf(struct neo_softc * sc,int regno,int size)326 nm_rdbuf(struct neo_softc *sc, int regno, int size)
327 {
328 bus_space_tag_t st = sc->bufiot;
329 bus_space_handle_t sh = sc->bufioh;
330
331 switch (size) {
332 case 1:
333 return bus_space_read_1(st, sh, regno);
334 case 2:
335 return bus_space_read_2(st, sh, regno);
336 case 4:
337 return bus_space_read_4(st, sh, regno);
338 default:
339 return (0xffffffff);
340 }
341 }
342
343 static void
nm_wrbuf(struct neo_softc * sc,int regno,u_int32_t data,int size)344 nm_wrbuf(struct neo_softc *sc, int regno, u_int32_t data, int size)
345 {
346 bus_space_tag_t st = sc->bufiot;
347 bus_space_handle_t sh = sc->bufioh;
348
349 switch (size) {
350 case 1:
351 bus_space_write_1(st, sh, regno, data);
352 break;
353 case 2:
354 bus_space_write_2(st, sh, regno, data);
355 break;
356 case 4:
357 bus_space_write_4(st, sh, regno, data);
358 break;
359 }
360 }
361
362 /* ac97 codec */
363 static int
nm_waitcd(struct neo_softc * sc)364 nm_waitcd(struct neo_softc *sc)
365 {
366 int cnt = 10;
367 int fail = 1;
368
369 while (cnt-- > 0) {
370 if (nm_rd(sc, sc->ac97_status, 2) & sc->ac97_busy)
371 DELAY(100);
372 else {
373 fail = 0;
374 break;
375 }
376 }
377 return (fail);
378 }
379
380
381 static void
nm_ackint(struct neo_softc * sc,u_int32_t num)382 nm_ackint(struct neo_softc *sc, u_int32_t num)
383 {
384 if (sc->type == NM256AV_PCI_ID)
385 nm_wr(sc, NM_INT_REG, num << 1, 2);
386 else if (sc->type == NM256ZX_PCI_ID)
387 nm_wr(sc, NM_INT_REG, num, 4);
388 }
389
390 static int
nm_loadcoeff(struct neo_softc * sc,int dir,int num)391 nm_loadcoeff(struct neo_softc *sc, int dir, int num)
392 {
393 int ofs, sz, i;
394 u_int32_t addr;
395
396 addr = (dir == AUMODE_PLAY)? 0x01c : 0x21c;
397 if (dir == AUMODE_RECORD)
398 num += 8;
399 sz = coefficientSizes[num];
400 ofs = 0;
401 while (num-- > 0)
402 ofs+= coefficientSizes[num];
403 for (i = 0; i < sz; i++)
404 nm_wrbuf(sc, sc->cbuf + i, coefficients[ofs + i], 1);
405 nm_wr(sc, addr, sc->cbuf, 4);
406 if (dir == AUMODE_PLAY)
407 sz--;
408 nm_wr(sc, addr + 4, sc->cbuf + sz, 4);
409 return (0);
410 }
411
412 int
nmchan_getptr(sc,mode)413 nmchan_getptr(sc, mode)
414 struct neo_softc *sc;
415 int mode;
416 {
417 if (mode == AUMODE_PLAY)
418 return (nm_rd(sc, NM_PBUFFER_CURRP, 4) - sc->pbuf);
419 else
420 return (nm_rd(sc, NM_RBUFFER_CURRP, 4) - sc->rbuf);
421 }
422
423
424 /* The interrupt handler */
425 int
neo_intr(void * p)426 neo_intr(void *p)
427 {
428 struct neo_softc *sc = (struct neo_softc *)p;
429 int status, x;
430 int rv = 0;
431
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
nm_init(struct neo_softc * sc)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
neo_attach(parent,self,aux)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 sc->powerhook = powerhook_establish(neo_power, sc);
615
616 audio_attach_mi(&neo_hw_if, sc, &sc->dev);
617
618 return;
619 }
620
621 void
neo_power(int why,void * addr)622 neo_power(int why, void *addr)
623 {
624 struct neo_softc *sc = (struct neo_softc *)addr;
625
626 if (why == PWR_RESUME) {
627 nm_init(sc);
628 (sc->codec_if->vtbl->restore_ports)(sc->codec_if);
629 }
630 }
631
632
633
634 int
neo_match(parent,match,aux)635 neo_match(parent, match, aux)
636 struct device *parent;
637 void *match;
638 void *aux;
639 {
640 struct pci_attach_args *pa = (struct pci_attach_args *) aux;
641 #if 0
642 u_int32_t subdev, badcard;
643 #endif
644
645 if (PCI_VENDOR(pa->pa_id) != PCI_VENDOR_NEOMAGIC)
646 return (0);
647
648 #if 0
649 subdev = (pci_get_subdevice(dev) << 16) | pci_get_subvendor(dev);
650 #endif
651 switch (PCI_PRODUCT(pa->pa_id)) {
652 case PCI_PRODUCT_NEOMAGIC_NM256AV:
653 #if 0
654 i = 0;
655 while ((i < NUM_BADCARDS) && (badcards[i] != subdev))
656 i++;
657 if (i == NUM_BADCARDS)
658 s = "NeoMagic 256AV";
659 DEB(else)
660 DEB(device_printf(dev, "this is a non-ac97 NM256AV, not attaching\n"));
661 return (1);
662 #endif
663 case PCI_PRODUCT_NEOMAGIC_NM256ZX:
664 return (1);
665 }
666
667 return (0);
668 }
669
670 int
neo_read_codec(sc_,a,d)671 neo_read_codec(sc_, a, d)
672 void *sc_;
673 u_int8_t a;
674 u_int16_t *d;
675 {
676 struct neo_softc *sc = sc_;
677
678 if (!nm_waitcd(sc)) {
679 *d = nm_rd(sc, sc->ac97_base + a, 2);
680 DELAY(1000);
681 return 0;
682 }
683
684 return (ENXIO);
685 }
686
687
688 int
neo_write_codec(sc_,a,d)689 neo_write_codec(sc_, a, d)
690 void *sc_;
691 u_int8_t a;
692 u_int16_t d;
693 {
694 struct neo_softc *sc = sc_;
695 int cnt = 3;
696
697 if (!nm_waitcd(sc)) {
698 while (cnt-- > 0) {
699 nm_wr(sc, sc->ac97_base + a, d, 2);
700 if (!nm_waitcd(sc)) {
701 DELAY(1000);
702 return (0);
703 }
704 }
705 }
706
707 return (ENXIO);
708 }
709
710
711 int
neo_attach_codec(sc_,codec_if)712 neo_attach_codec(sc_, codec_if)
713 void *sc_;
714 struct ac97_codec_if *codec_if;
715 {
716 struct neo_softc *sc = sc_;
717
718 sc->codec_if = codec_if;
719 return (0);
720 }
721
722 void
neo_reset_codec(sc)723 neo_reset_codec(sc)
724 void *sc;
725 {
726 nm_wr(sc, 0x6c0, 0x01, 1);
727 nm_wr(sc, 0x6cc, 0x87, 1);
728 nm_wr(sc, 0x6cc, 0x80, 1);
729 nm_wr(sc, 0x6cc, 0x00, 1);
730
731 return;
732 }
733
734
735 enum ac97_host_flags
neo_flags_codec(sc)736 neo_flags_codec(sc)
737 void *sc;
738 {
739 return (AC97_HOST_DONT_READANY);
740 }
741
742 int
neo_open(addr,flags)743 neo_open(addr, flags)
744 void *addr;
745 int flags;
746 {
747 return (0);
748 }
749
750 /*
751 * Close function is called at splaudio().
752 */
753 void
neo_close(addr)754 neo_close(addr)
755 void *addr;
756 {
757 struct neo_softc *sc = addr;
758
759 neo_halt_output(sc);
760 neo_halt_input(sc);
761
762 sc->pintr = 0;
763 sc->rintr = 0;
764 }
765
766 int
neo_query_encoding(addr,fp)767 neo_query_encoding(addr, fp)
768 void *addr;
769 struct audio_encoding *fp;
770 {
771 switch (fp->index) {
772 case 0:
773 strlcpy(fp->name, AudioEulinear, sizeof fp->name);
774 fp->encoding = AUDIO_ENCODING_ULINEAR;
775 fp->precision = 8;
776 fp->flags = 0;
777 return (0);
778 case 1:
779 strlcpy(fp->name, AudioEmulaw, sizeof fp->name);
780 fp->encoding = AUDIO_ENCODING_ULAW;
781 fp->precision = 8;
782 fp->flags = AUDIO_ENCODINGFLAG_EMULATED;
783 return (0);
784 case 2:
785 strlcpy(fp->name, AudioEalaw, sizeof fp->name);
786 fp->encoding = AUDIO_ENCODING_ALAW;
787 fp->precision = 8;
788 fp->flags = AUDIO_ENCODINGFLAG_EMULATED;
789 return (0);
790 case 3:
791 strlcpy(fp->name, AudioEslinear, sizeof fp->name);
792 fp->encoding = AUDIO_ENCODING_SLINEAR;
793 fp->precision = 8;
794 fp->flags = AUDIO_ENCODINGFLAG_EMULATED;
795 return (0);
796 case 4:
797 strlcpy(fp->name, AudioEslinear_le, sizeof fp->name);
798 fp->encoding = AUDIO_ENCODING_SLINEAR_LE;
799 fp->precision = 16;
800 fp->flags = 0;
801 return (0);
802 case 5:
803 strlcpy(fp->name, AudioEulinear_le, sizeof fp->name);
804 fp->encoding = AUDIO_ENCODING_ULINEAR_LE;
805 fp->precision = 16;
806 fp->flags = AUDIO_ENCODINGFLAG_EMULATED;
807 return (0);
808 case 6:
809 strlcpy(fp->name, AudioEslinear_be, sizeof fp->name);
810 fp->encoding = AUDIO_ENCODING_SLINEAR_BE;
811 fp->precision = 16;
812 fp->flags = AUDIO_ENCODINGFLAG_EMULATED;
813 return (0);
814 case 7:
815 strlcpy(fp->name, AudioEulinear_be, sizeof fp->name);
816 fp->encoding = AUDIO_ENCODING_ULINEAR_BE;
817 fp->precision = 16;
818 fp->flags = AUDIO_ENCODINGFLAG_EMULATED;
819 return (0);
820 default:
821 return (EINVAL);
822 }
823 }
824
825 /* Todo: don't commit settings to card until we've verified all parameters */
826 int
neo_set_params(addr,setmode,usemode,play,rec)827 neo_set_params(addr, setmode, usemode, play, rec)
828 void *addr;
829 int setmode, usemode;
830 struct audio_params *play, *rec;
831 {
832 struct neo_softc *sc = addr;
833 u_int32_t base;
834 u_int8_t x;
835 int mode;
836 struct audio_params *p;
837
838 for (mode = AUMODE_RECORD; mode != -1;
839 mode = mode == AUMODE_RECORD ? AUMODE_PLAY : -1) {
840 if ((setmode & mode) == 0)
841 continue;
842
843 p = mode == AUMODE_PLAY ? play : rec;
844
845 if (p == NULL) continue;
846
847 for (x = 0; x < 8; x++)
848 if (p->sample_rate < (samplerates[x] + samplerates[x + 1]) / 2)
849 break;
850
851 if (x == 8) return (EINVAL);
852
853 p->sample_rate = samplerates[x];
854 nm_loadcoeff(sc, mode, x);
855
856 x <<= 4;
857 x &= NM_RATE_MASK;
858 if (p->precision == 16) x |= NM_RATE_BITS_16;
859 if (p->channels == 2) x |= NM_RATE_STEREO;
860
861 base = (mode == AUMODE_PLAY) ?
862 NM_PLAYBACK_REG_OFFSET : NM_RECORD_REG_OFFSET;
863 nm_wr(sc, base + NM_RATE_REG_OFFSET, x, 1);
864
865 p->factor = 1;
866 p->sw_code = 0;
867 switch (p->encoding) {
868 case AUDIO_ENCODING_SLINEAR_BE:
869 if (p->precision == 16)
870 p->sw_code = swap_bytes;
871 else
872 p->sw_code = change_sign8;
873 break;
874 case AUDIO_ENCODING_SLINEAR_LE:
875 if (p->precision != 16)
876 p->sw_code = change_sign8;
877 break;
878 case AUDIO_ENCODING_ULINEAR_BE:
879 if (p->precision == 16) {
880 if (mode == AUMODE_PLAY)
881 p->sw_code = swap_bytes_change_sign16;
882 else
883 p->sw_code = change_sign16_swap_bytes;
884 }
885 break;
886 case AUDIO_ENCODING_ULINEAR_LE:
887 if (p->precision == 16)
888 p->sw_code = change_sign16;
889 break;
890 case AUDIO_ENCODING_ULAW:
891 if (mode == AUMODE_PLAY) {
892 p->factor = 2;
893 p->sw_code = mulaw_to_slinear16;
894 } else
895 p->sw_code = ulinear8_to_mulaw;
896 break;
897 case AUDIO_ENCODING_ALAW:
898 if (mode == AUMODE_PLAY) {
899 p->factor = 2;
900 p->sw_code = alaw_to_slinear16;
901 } else
902 p->sw_code = ulinear8_to_alaw;
903 break;
904 default:
905 return (EINVAL);
906 }
907 }
908
909
910 return (0);
911 }
912
913 int
neo_round_blocksize(addr,blk)914 neo_round_blocksize(addr, blk)
915 void *addr;
916 int blk;
917 {
918 return (NM_BUFFSIZE / 2);
919 }
920
921 int
neo_trigger_output(addr,start,end,blksize,intr,arg,param)922 neo_trigger_output(addr, start, end, blksize, intr, arg, param)
923 void *addr;
924 void *start, *end;
925 int blksize;
926 void (*intr)(void *);
927 void *arg;
928 struct audio_params *param;
929 {
930 struct neo_softc *sc = addr;
931 int ssz;
932
933 sc->pintr = intr;
934 sc->parg = arg;
935
936 ssz = (param->precision * param->factor == 16)? 2 : 1;
937 if (param->channels == 2)
938 ssz <<= 1;
939
940 sc->pbufsize = ((char *)end - (char *)start);
941 sc->pblksize = blksize;
942 sc->pwmark = blksize;
943
944 nm_wr(sc, NM_PBUFFER_START, sc->pbuf, 4);
945 nm_wr(sc, NM_PBUFFER_END, sc->pbuf + sc->pbufsize - ssz, 4);
946 nm_wr(sc, NM_PBUFFER_CURRP, sc->pbuf, 4);
947 nm_wr(sc, NM_PBUFFER_WMARK, sc->pbuf + sc->pwmark, 4);
948 nm_wr(sc, NM_PLAYBACK_ENABLE_REG, NM_PLAYBACK_FREERUN |
949 NM_PLAYBACK_ENABLE_FLAG, 1);
950 nm_wr(sc, NM_AUDIO_MUTE_REG, 0, 2);
951
952 return (0);
953 }
954
955
956
957 int
neo_trigger_input(addr,start,end,blksize,intr,arg,param)958 neo_trigger_input(addr, start, end, blksize, intr, arg, param)
959 void *addr;
960 void *start, *end;
961 int blksize;
962 void (*intr)(void *);
963 void *arg;
964 struct audio_params *param;
965 {
966 struct neo_softc *sc = addr;
967 int ssz;
968
969 sc->rintr = intr;
970 sc->rarg = arg;
971
972 ssz = (param->precision * param->factor == 16)? 2 : 1;
973 if (param->channels == 2)
974 ssz <<= 1;
975
976 sc->rbufsize = ((char *)end - (char *)start);
977 sc->rblksize = blksize;
978 sc->rwmark = blksize;
979
980 nm_wr(sc, NM_RBUFFER_START, sc->rbuf, 4);
981 nm_wr(sc, NM_RBUFFER_END, sc->rbuf + sc->rbufsize, 4);
982 nm_wr(sc, NM_RBUFFER_CURRP, sc->rbuf, 4);
983 nm_wr(sc, NM_RBUFFER_WMARK, sc->rbuf + sc->rwmark, 4);
984 nm_wr(sc, NM_RECORD_ENABLE_REG, NM_RECORD_FREERUN |
985 NM_RECORD_ENABLE_FLAG, 1);
986
987 return (0);
988 }
989
990 int
neo_halt_output(addr)991 neo_halt_output(addr)
992 void *addr;
993 {
994 struct neo_softc *sc = (struct neo_softc *)addr;
995
996 nm_wr(sc, NM_PLAYBACK_ENABLE_REG, 0, 1);
997 nm_wr(sc, NM_AUDIO_MUTE_REG, NM_AUDIO_MUTE_BOTH, 2);
998
999 sc->pintr = 0;
1000
1001 return (0);
1002 }
1003
1004 int
neo_halt_input(addr)1005 neo_halt_input(addr)
1006 void *addr;
1007 {
1008 struct neo_softc *sc = (struct neo_softc *)addr;
1009
1010 nm_wr(sc, NM_RECORD_ENABLE_REG, 0, 1);
1011
1012 sc->rintr = 0;
1013
1014 return (0);
1015 }
1016
1017 int
neo_getdev(addr,retp)1018 neo_getdev(addr, retp)
1019 void *addr;
1020 struct audio_device *retp;
1021 {
1022 *retp = neo_device;
1023 return (0);
1024 }
1025
1026 int
neo_mixer_set_port(addr,cp)1027 neo_mixer_set_port(addr, cp)
1028 void *addr;
1029 mixer_ctrl_t *cp;
1030 {
1031 struct neo_softc *sc = addr;
1032
1033 return ((sc->codec_if->vtbl->mixer_set_port)(sc->codec_if, cp));
1034 }
1035
1036 int
neo_mixer_get_port(addr,cp)1037 neo_mixer_get_port(addr, cp)
1038 void *addr;
1039 mixer_ctrl_t *cp;
1040 {
1041 struct neo_softc *sc = addr;
1042
1043 return ((sc->codec_if->vtbl->mixer_get_port)(sc->codec_if, cp));
1044 }
1045
1046 int
neo_query_devinfo(addr,dip)1047 neo_query_devinfo(addr, dip)
1048 void *addr;
1049 mixer_devinfo_t *dip;
1050 {
1051 struct neo_softc *sc = addr;
1052
1053 return ((sc->codec_if->vtbl->query_devinfo)(sc->codec_if, dip));
1054 }
1055
1056 void *
neo_malloc(addr,direction,size,pool,flags)1057 neo_malloc(addr, direction, size, pool, flags)
1058 void *addr;
1059 int direction;
1060 size_t size;
1061 int pool, flags;
1062 {
1063 struct neo_softc *sc = addr;
1064 void *rv = 0;
1065
1066 switch (direction) {
1067 case AUMODE_PLAY:
1068 rv = (char *)sc->bufioh + sc->pbuf;
1069 break;
1070 case AUMODE_RECORD:
1071 rv = (char *)sc->bufioh + sc->rbuf;
1072 break;
1073 default:
1074 break;
1075 }
1076
1077 return (rv);
1078 }
1079
1080 void
neo_free(addr,ptr,pool)1081 neo_free(addr, ptr, pool)
1082 void *addr;
1083 void *ptr;
1084 int pool;
1085 {
1086 return;
1087 }
1088
1089 size_t
neo_round_buffersize(addr,direction,size)1090 neo_round_buffersize(addr, direction, size)
1091 void *addr;
1092 int direction;
1093 size_t size;
1094 {
1095 return (NM_BUFFSIZE);
1096 }
1097
1098
1099 int
neo_get_props(addr)1100 neo_get_props(addr)
1101 void *addr;
1102 {
1103
1104 return (AUDIO_PROP_INDEPENDENT | AUDIO_PROP_FULLDUPLEX);
1105 }
1106