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