Annotation of sys/dev/pci/autri.c, Revision 1.1.1.1
1.1 nbrk 1: /* $OpenBSD: autri.c,v 1.20 2007/05/26 00:36:03 krw Exp $ */
2:
3: /*
4: * Copyright (c) 2001 SOMEYA Yoshihiko and KUROSAWA Takahiro.
5: * All rights reserved.
6: *
7: * Redistribution and use in source and binary forms, with or without
8: * modification, are permitted provided that the following conditions
9: * are met:
10: * 1. Redistributions of source code must retain the above copyright
11: * notice, this list of conditions and the following disclaimer.
12: * 2. Redistributions in binary form must reproduce the above copyright
13: * notice, this list of conditions and the following disclaimer in the
14: * documentation and/or other materials provided with the distribution.
15: *
16: * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
17: * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
18: * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
19: * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
20: * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
21: * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
22: * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
23: * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24: * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
25: * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26: */
27:
28: /*
29: * Trident 4DWAVE-DX/NX, SiS 7018, ALi M5451 Sound Driver
30: *
31: * The register information is taken from the ALSA driver.
32: *
33: * Documentation links:
34: * - ftp://ftp.alsa-project.org/pub/manuals/trident/
35: */
36:
37: #include "midi.h"
38:
39: #include <sys/param.h>
40: #include <sys/systm.h>
41: #include <sys/kernel.h>
42: #include <sys/fcntl.h>
43: #include <sys/malloc.h>
44: #include <sys/device.h>
45: #include <sys/proc.h>
46:
47: #include <dev/pci/pcidevs.h>
48: #include <dev/pci/pcireg.h>
49: #include <dev/pci/pcivar.h>
50:
51: #include <sys/audioio.h>
52: #include <dev/audio_if.h>
53: #include <dev/midi_if.h>
54: #include <dev/mulaw.h>
55: #include <dev/auconv.h>
56: #include <dev/ic/ac97.h>
57: #include <dev/ic/mpuvar.h>
58:
59: #include <machine/bus.h>
60: #include <machine/intr.h>
61:
62: #include <dev/pci/autrireg.h>
63: #include <dev/pci/autrivar.h>
64:
65: #ifdef AUDIO_DEBUG
66: # define DPRINTF(x) if (autridebug) printf x
67: # define DPRINTFN(n,x) if (autridebug > (n)) printf x
68: int autridebug = 0;
69: #else
70: # define DPRINTF(x)
71: # define DPRINTFN(n,x)
72: #endif
73:
74: int autri_match(struct device *, void *, void *);
75: void autri_attach(struct device *, struct device *, void *);
76: int autri_intr(void *);
77:
78: #define DMAADDR(p) ((p)->map->dm_segs[0].ds_addr)
79: #define KERNADDR(p) ((void *)((p)->addr))
80:
81: int autri_allocmem(struct autri_softc *, size_t, size_t, struct autri_dma *);
82: int autri_freemem(struct autri_softc *, struct autri_dma *);
83:
84: #define TWRITE1(sc, r, x) bus_space_write_1((sc)->memt, (sc)->memh, (r), (x))
85: #define TWRITE2(sc, r, x) bus_space_write_2((sc)->memt, (sc)->memh, (r), (x))
86: #define TWRITE4(sc, r, x) bus_space_write_4((sc)->memt, (sc)->memh, (r), (x))
87: #define TREAD1(sc, r) bus_space_read_1((sc)->memt, (sc)->memh, (r))
88: #define TREAD2(sc, r) bus_space_read_2((sc)->memt, (sc)->memh, (r))
89: #define TREAD4(sc, r) bus_space_read_4((sc)->memt, (sc)->memh, (r))
90:
91: static __inline void autri_reg_set_1(struct autri_softc *, int, uint8_t);
92: static __inline void autri_reg_clear_1(struct autri_softc *, int, uint8_t);
93: static __inline void autri_reg_set_4(struct autri_softc *, int, uint32_t);
94: static __inline void autri_reg_clear_4(struct autri_softc *, int, uint32_t);
95:
96: int autri_attach_codec(void *sc, struct ac97_codec_if *);
97: int autri_read_codec(void *sc, u_int8_t a, u_int16_t *d);
98: int autri_write_codec(void *sc, u_int8_t a, u_int16_t d);
99: void autri_reset_codec(void *sc);
100: enum ac97_host_flags autri_flags_codec(void *);
101:
102: void autri_powerhook(int why,void *addr);
103: int autri_init(void *sc);
104: struct autri_dma *autri_find_dma(struct autri_softc *, void *);
105: void autri_setup_channel(struct autri_softc *sc,int mode,
106: struct audio_params *param);
107: void autri_enable_interrupt(struct autri_softc *sc, int ch);
108: void autri_disable_interrupt(struct autri_softc *sc, int ch);
109: void autri_startch(struct autri_softc *sc, int ch, int ch_intr);
110: void autri_stopch(struct autri_softc *sc, int ch, int ch_intr);
111: void autri_enable_loop_interrupt(void *sc);
112: #if 0
113: void autri_disable_loop_interrupt(void *sc);
114: #endif
115:
116: struct cfdriver autri_cd = {
117: NULL, "autri", DV_DULL
118: };
119:
120: struct cfattach autri_ca = {
121: sizeof(struct autri_softc), autri_match, autri_attach
122: };
123:
124: int autri_open(void *, int);
125: void autri_close(void *);
126: int autri_query_encoding(void *, struct audio_encoding *);
127: int autri_set_params(void *, int, int, struct audio_params *,
128: struct audio_params *);
129: int autri_round_blocksize(void *, int);
130: int autri_trigger_output(void *, void *, void *, int, void (*)(void *),
131: void *, struct audio_params *);
132: int autri_trigger_input(void *, void *, void *, int, void (*)(void *),
133: void *, struct audio_params *);
134: int autri_halt_output(void *);
135: int autri_halt_input(void *);
136: int autri_getdev(void *, struct audio_device *);
137: int autri_mixer_set_port(void *, mixer_ctrl_t *);
138: int autri_mixer_get_port(void *, mixer_ctrl_t *);
139: void *autri_malloc(void *, int, size_t, int, int);
140: void autri_free(void *, void *, int);
141: paddr_t autri_mappage(void *, void *, off_t, int);
142: int autri_get_props(void *);
143: int autri_query_devinfo(void *addr, mixer_devinfo_t *dip);
144:
145: int autri_get_portnum_by_name(struct autri_softc *, char *, char *, char *);
146:
147: struct audio_hw_if autri_hw_if = {
148: autri_open,
149: autri_close,
150: NULL, /* drain */
151: autri_query_encoding,
152: autri_set_params,
153: autri_round_blocksize,
154: NULL, /* commit_settings */
155: NULL, /* init_output */
156: NULL, /* init_input */
157: NULL, /* start_output */
158: NULL, /* start_input */
159: autri_halt_output,
160: autri_halt_input,
161: NULL, /* speaker_ctl */
162: autri_getdev,
163: NULL, /* setfd */
164: autri_mixer_set_port,
165: autri_mixer_get_port,
166: autri_query_devinfo,
167: autri_malloc,
168: autri_free,
169: NULL,
170: autri_mappage,
171: autri_get_props,
172: autri_trigger_output,
173: autri_trigger_input,
174: };
175:
176: #if NMIDI > 0
177: void autri_midi_close(void *);
178: void autri_midi_getinfo(void *, struct midi_info *);
179: int autri_midi_open(void *, int, void (*)(void *, int),
180: void (*)(void *), void *);
181: int autri_midi_output(void *, int);
182:
183: struct midi_hw_if autri_midi_hw_if = {
184: autri_midi_open,
185: autri_midi_close,
186: autri_midi_output,
187: NULL, /* flush */
188: autri_midi_getinfo,
189: NULL, /* ioctl */
190: };
191: #endif
192:
193: /*
194: * register set/clear bit
195: */
196: static __inline void
197: autri_reg_set_1(sc, no, mask)
198: struct autri_softc *sc;
199: int no;
200: uint8_t mask;
201: {
202: bus_space_write_1(sc->memt, sc->memh, no,
203: (bus_space_read_1(sc->memt, sc->memh, no) | mask));
204: }
205:
206: static __inline void
207: autri_reg_clear_1(sc, no, mask)
208: struct autri_softc *sc;
209: int no;
210: uint8_t mask;
211: {
212: bus_space_write_1(sc->memt, sc->memh, no,
213: (bus_space_read_1(sc->memt, sc->memh, no) & ~mask));
214: }
215:
216: static __inline void
217: autri_reg_set_4(sc, no, mask)
218: struct autri_softc *sc;
219: int no;
220: uint32_t mask;
221: {
222: bus_space_write_4(sc->memt, sc->memh, no,
223: (bus_space_read_4(sc->memt, sc->memh, no) | mask));
224: }
225:
226: static __inline void
227: autri_reg_clear_4(sc, no, mask)
228: struct autri_softc *sc;
229: int no;
230: uint32_t mask;
231: {
232: bus_space_write_4(sc->memt, sc->memh, no,
233: (bus_space_read_4(sc->memt, sc->memh, no) & ~mask));
234: }
235:
236: /*
237: * AC97 codec
238: */
239: int
240: autri_attach_codec(sc_, codec_if)
241: void *sc_;
242: struct ac97_codec_if *codec_if;
243: {
244: struct autri_codec_softc *sc = sc_;
245:
246: DPRINTF(("autri_attach_codec()\n"));
247:
248: sc->codec_if = codec_if;
249: return 0;
250: }
251:
252: int
253: autri_read_codec(sc_, index, data)
254: void *sc_;
255: u_int8_t index;
256: u_int16_t *data;
257: {
258: struct autri_codec_softc *codec = sc_;
259: struct autri_softc *sc = codec->sc;
260: u_int32_t status, addr, cmd, busy;
261: u_int16_t count;
262:
263: /*DPRINTF(("sc->sc->type : 0x%X",sc->sc->type));*/
264:
265: switch (sc->sc_devid) {
266: case AUTRI_DEVICE_ID_4DWAVE_DX:
267: addr = AUTRI_DX_ACR1;
268: cmd = AUTRI_DX_ACR1_CMD_READ;
269: busy = AUTRI_DX_ACR1_BUSY_READ;
270: break;
271: case AUTRI_DEVICE_ID_4DWAVE_NX:
272: addr = AUTRI_NX_ACR2;
273: cmd = AUTRI_NX_ACR2_CMD_READ;
274: busy = AUTRI_NX_ACR2_BUSY_READ | AUTRI_NX_ACR2_RECV_WAIT;
275: break;
276: case AUTRI_DEVICE_ID_SIS_7018:
277: addr = AUTRI_SIS_ACRD;
278: cmd = AUTRI_SIS_ACRD_CMD_READ;
279: busy = AUTRI_SIS_ACRD_BUSY_READ | AUTRI_SIS_ACRD_AUDIO_BUSY;
280: break;
281: case AUTRI_DEVICE_ID_ALI_M5451:
282: if (sc->sc_revision > 0x01)
283: addr = AUTRI_ALI_ACWR;
284: else
285: addr = AUTRI_ALI_ACRD;
286: cmd = AUTRI_ALI_ACRD_CMD_READ;
287: busy = AUTRI_ALI_ACRD_BUSY_READ;
288: break;
289: default:
290: printf("%s: autri_read_codec : unknown device\n",
291: sc->sc_dev.dv_xname);
292: return -1;
293: }
294:
295: /* wait for 'Ready to Read' */
296: for (count=0; count < 0xffff; count++) {
297: if ((TREAD4(sc, addr) & busy) == 0)
298: break;
299: DELAY(1);
300: }
301:
302: if (count == 0xffff) {
303: printf("%s: Codec timeout. Busy reading AC97 codec.\n",
304: sc->sc_dev.dv_xname);
305: return -1;
306: }
307:
308: /* send Read Command to AC97 */
309: TWRITE4(sc, addr, (index & 0x7f) | cmd);
310:
311: /* wait for 'Returned data is available' */
312: for (count=0; count < 0xffff; count++) {
313: status = TREAD4(sc, addr);
314: if ((status & busy) == 0)
315: break;
316: DELAY(1);
317: }
318:
319: if (count == 0xffff) {
320: printf("%s: Codec timeout. Busy reading AC97 codec.\n",
321: sc->sc_dev.dv_xname);
322: return -1;
323: }
324:
325: *data = (status >> 16) & 0x0000ffff;
326: /*DPRINTF(("autri_read_codec(0x%X) return 0x%X\n",reg,*data));*/
327: return 0;
328: }
329:
330: int
331: autri_write_codec(sc_, index, data)
332: void *sc_;
333: u_int8_t index;
334: u_int16_t data;
335: {
336: struct autri_codec_softc *codec = sc_;
337: struct autri_softc *sc = codec->sc;
338: u_int32_t addr, cmd, busy;
339: u_int16_t count;
340:
341: /*DPRINTF(("autri_write_codec(0x%X,0x%X)\n",index,data));*/
342:
343: switch (sc->sc_devid) {
344: case AUTRI_DEVICE_ID_4DWAVE_DX:
345: addr = AUTRI_DX_ACR0;
346: cmd = AUTRI_DX_ACR0_CMD_WRITE;
347: busy = AUTRI_DX_ACR0_BUSY_WRITE;
348: break;
349: case AUTRI_DEVICE_ID_4DWAVE_NX:
350: addr = AUTRI_NX_ACR1;
351: cmd = AUTRI_NX_ACR1_CMD_WRITE;
352: busy = AUTRI_NX_ACR1_BUSY_WRITE;
353: break;
354: case AUTRI_DEVICE_ID_SIS_7018:
355: addr = AUTRI_SIS_ACWR;
356: cmd = AUTRI_SIS_ACWR_CMD_WRITE;
357: busy = AUTRI_SIS_ACWR_BUSY_WRITE | AUTRI_SIS_ACWR_AUDIO_BUSY;
358: break;
359: case AUTRI_DEVICE_ID_ALI_M5451:
360: addr = AUTRI_ALI_ACWR;
361: cmd = AUTRI_ALI_ACWR_CMD_WRITE;
362: if (sc->sc_revision > 0x01)
363: cmd |= 0x0100;
364: busy = AUTRI_ALI_ACWR_BUSY_WRITE;
365: break;
366: default:
367: printf("%s: autri_write_codec : unknown device.\n",
368: sc->sc_dev.dv_xname);
369: return -1;
370: }
371:
372: /* wait for 'Ready to Write' */
373: for (count=0; count < 0xffff; count++) {
374: if ((TREAD4(sc, addr) & busy) == 0)
375: break;
376: DELAY(1);
377: }
378:
379: if (count == 0xffff) {
380: printf("%s: Codec timeout. Busy writing AC97 codec\n",
381: sc->sc_dev.dv_xname);
382: return -1;
383: }
384:
385: /* send Write Command to AC97 */
386: TWRITE4(sc, addr, (data << 16) | (index & 0x7f) | cmd);
387:
388: return 0;
389: }
390:
391: void
392: autri_reset_codec(sc_)
393: void *sc_;
394: {
395: struct autri_codec_softc *codec = sc_;
396: struct autri_softc *sc = codec->sc;
397: u_int32_t reg, ready;
398: int addr, count = 200;
399:
400: DPRINTF(("autri_reset_codec(codec=%p,sc=%p)\n",codec,sc));
401: DPRINTF(("sc->sc_devid=%X\n",sc->sc_devid));
402:
403: switch (sc->sc_devid) {
404: case AUTRI_DEVICE_ID_4DWAVE_DX:
405: /* warm reset AC97 codec */
406: autri_reg_set_4(sc, AUTRI_DX_ACR2, 1);
407: delay(100);
408: /* release reset */
409: autri_reg_clear_4(sc, AUTRI_DX_ACR2, 1);
410: delay(100);
411:
412: addr = AUTRI_DX_ACR2;
413: ready = AUTRI_DX_ACR2_CODEC_READY;
414: break;
415: case AUTRI_DEVICE_ID_4DWAVE_NX:
416: /* warm reset AC97 codec */
417: autri_reg_set_4(sc, AUTRI_NX_ACR0, 1);
418: delay(100);
419: /* release reset */
420: autri_reg_clear_4(sc, AUTRI_NX_ACR0, 1);
421: delay(100);
422:
423: addr = AUTRI_NX_ACR0;
424: ready = AUTRI_NX_ACR0_CODEC_READY;
425: break;
426: case AUTRI_DEVICE_ID_SIS_7018:
427: /* warm reset AC97 codec */
428: autri_reg_set_4(sc, AUTRI_SIS_SCTRL, 2);
429: delay(1000);
430: /* release reset (warm & cold) */
431: autri_reg_clear_4(sc, AUTRI_SIS_SCTRL, 3);
432: delay(2000);
433:
434: addr = AUTRI_SIS_SCTRL;
435: ready = AUTRI_SIS_SCTRL_CODEC_READY;
436: break;
437: case AUTRI_DEVICE_ID_ALI_M5451:
438: /* warm reset AC97 codec */
439: autri_reg_set_4(sc, AUTRI_ALI_SCTRL, 1);
440: delay(100);
441: /* release reset (warm & cold) */
442: autri_reg_clear_4(sc, AUTRI_ALI_SCTRL, 3);
443: delay(100);
444:
445: addr = AUTRI_ALI_SCTRL;
446: ready = AUTRI_ALI_SCTRL_CODEC_READY;
447: break;
448: }
449:
450: /* wait for 'Codec Ready' */
451: while (count--) {
452: reg = TREAD4(sc, addr);
453: if (reg & ready)
454: break;
455: delay(1000);
456: }
457:
458: if (count == 0)
459: printf("%s: Codec timeout. AC97 is not ready for operation.\n",
460: sc->sc_dev.dv_xname);
461: }
462:
463: enum ac97_host_flags
464: autri_flags_codec(void *v)
465: {
466: struct autri_codec_softc *sc = v;
467:
468: return (sc->flags);
469: }
470:
471: /*
472: *
473: */
474: const struct pci_matchid autri_devices[] = {
475: { PCI_VENDOR_TRIDENT, PCI_PRODUCT_TRIDENT_4DWAVE_NX },
476: { PCI_VENDOR_SIS, PCI_PRODUCT_SIS_7018 },
477: { PCI_VENDOR_ALI, PCI_PRODUCT_ALI_M5451 }
478: };
479:
480: int
481: autri_match(parent, match, aux)
482: struct device *parent;
483: void *match;
484: void *aux;
485: {
486: struct pci_attach_args *pa = aux;
487:
488: if (PCI_VENDOR(pa->pa_id) == PCI_VENDOR_TRIDENT &&
489: PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_TRIDENT_4DWAVE_DX) {
490: /*
491: * IBM makes a pcn network card and improperly
492: * sets the vendor and product ID's. Avoid matching.
493: */
494: if (PCI_CLASS(pa->pa_class) == PCI_CLASS_NETWORK)
495: return (0);
496: else
497: return (1);
498: }
499:
500: return (pci_matchbyid((struct pci_attach_args *)aux, autri_devices,
501: sizeof(autri_devices)/sizeof(autri_devices[0])));
502: }
503:
504: void
505: autri_attach(parent, self, aux)
506: struct device *parent;
507: struct device *self;
508: void *aux;
509: {
510: struct autri_softc *sc = (struct autri_softc *)self;
511: struct pci_attach_args *pa = (struct pci_attach_args *)aux;
512: pci_chipset_tag_t pc = pa->pa_pc;
513: struct autri_codec_softc *codec;
514: bus_size_t iosize;
515: pci_intr_handle_t ih;
516: char const *intrstr;
517: mixer_ctrl_t ctl;
518: int i, r;
519:
520: sc->sc_devid = pa->pa_id;
521: sc->sc_class = pa->pa_class;
522: sc->sc_revision = PCI_REVISION(pa->pa_class);
523:
524: /* map register to memory */
525: if (pci_mapreg_map(pa, AUTRI_PCI_MEMORY_BASE,
526: PCI_MAPREG_TYPE_MEM, 0, &sc->memt, &sc->memh, NULL, &iosize, 0)) {
527: printf("%s: can't map memory space\n", sc->sc_dev.dv_xname);
528: return;
529: }
530:
531: /* map and establish the interrupt */
532: if (pci_intr_map(pa, &ih)) {
533: printf("%s: couldn't map interrupt\n", sc->sc_dev.dv_xname);
534: bus_space_unmap(sc->memt, sc->memh, iosize);
535: return;
536: }
537: intrstr = pci_intr_string(pc, ih);
538: sc->sc_ih = pci_intr_establish(pc, ih, IPL_AUDIO, autri_intr, sc,
539: sc->sc_dev.dv_xname);
540: if (sc->sc_ih == NULL) {
541: printf("%s: couldn't establish interrupt",
542: sc->sc_dev.dv_xname);
543: if (intrstr != NULL)
544: printf(" at %s", intrstr);
545: printf("\n");
546: bus_space_unmap(sc->memt, sc->memh, iosize);
547: return;
548: }
549: printf(": %s\n", intrstr);
550:
551: sc->sc_dmatag = pa->pa_dmat;
552: sc->sc_pc = pc;
553: sc->sc_pt = pa->pa_tag;
554:
555: /* initialize the device */
556: autri_init(sc);
557:
558: /* attach AC97 codec */
559: codec = &sc->sc_codec;
560: memcpy(&codec->sc_dev, &sc->sc_dev, sizeof(codec->sc_dev));
561: codec->sc = sc;
562:
563: codec->host_if.arg = codec;
564: codec->host_if.attach = autri_attach_codec;
565: codec->host_if.reset = autri_reset_codec;
566: codec->host_if.read = autri_read_codec;
567: codec->host_if.write = autri_write_codec;
568: codec->host_if.flags = autri_flags_codec;
569: codec->flags = AC97_HOST_DONT_READ | AC97_HOST_SWAPPED_CHANNELS;
570: if (sc->sc_dev.dv_cfdata->cf_flags & 0x0001)
571: codec->flags &= ~AC97_HOST_SWAPPED_CHANNELS;
572:
573: if ((r = ac97_attach(&codec->host_if)) != 0) {
574: printf("%s: can't attach codec (error 0x%X)\n",
575: sc->sc_dev.dv_xname, r);
576: pci_intr_disestablish(pc, sc->sc_ih);
577: bus_space_unmap(sc->memt, sc->memh, iosize);
578: return;
579: }
580:
581: /* disable mutes */
582: for (i = 0; i < 4; i++) {
583: static struct {
584: char *class, *device;
585: } d[] = {
586: { AudioCoutputs, AudioNmaster},
587: { AudioCinputs, AudioNdac},
588: { AudioCinputs, AudioNcd},
589: { AudioCrecord, AudioNvolume},
590: };
591:
592: ctl.type = AUDIO_MIXER_ENUM;
593: ctl.un.ord = 0;
594:
595: #if 0
596: ctl.dev = sc->sc_codec.codec_if->vtbl->get_portnum_by_name(sc->sc_codec.codec_if,
597: d[i].class, d[i].device, AudioNmute);
598: #endif
599: ctl.dev = autri_get_portnum_by_name(sc,d[i].class,
600: d[i].device, AudioNmute);
601: autri_mixer_set_port(sc, &ctl);
602: }
603:
604: /* set a reasonable default volume */
605: ctl.type = AUDIO_MIXER_VALUE;
606: ctl.un.value.num_channels = 2;
607: ctl.un.value.level[AUDIO_MIXER_LEVEL_LEFT] =
608: ctl.un.value.level[AUDIO_MIXER_LEVEL_RIGHT] = 127;
609:
610: ctl.dev = autri_get_portnum_by_name(sc,AudioCoutputs,AudioNmaster,NULL);
611: autri_mixer_set_port(sc, &ctl);
612:
613: audio_attach_mi(&autri_hw_if, sc, &sc->sc_dev);
614:
615: #if NMIDI > 0
616: midi_attach_mi(&autri_midi_hw_if, sc, &sc->sc_dev);
617: #endif
618:
619: sc->sc_old_power = PWR_RESUME;
620: powerhook_establish(autri_powerhook, sc);
621: }
622:
623: void
624: autri_powerhook(int why,void *addr)
625: {
626: struct autri_softc *sc = addr;
627:
628: if (why == PWR_RESUME && sc->sc_old_power == PWR_SUSPEND) {
629: DPRINTF(("PWR_RESUME\n"));
630: autri_init(sc);
631: /*autri_reset_codec(&sc->sc_codec);*/
632: (sc->sc_codec.codec_if->vtbl->restore_ports)(sc->sc_codec.codec_if);
633: }
634: sc->sc_old_power = why;
635: }
636:
637: int
638: autri_init(sc_)
639: void *sc_;
640: {
641: struct autri_softc *sc = sc_;
642: pcireg_t reg;
643:
644: pci_chipset_tag_t pc = sc->sc_pc;
645: pcitag_t pt = sc->sc_pt;
646:
647: DPRINTF(("in autri_init()\n"));
648: DPRINTFN(5,("pci_conf_read(0x40) : 0x%X\n",pci_conf_read(pc,pt,0x40)));
649: DPRINTFN(5,("pci_conf_read(0x44) : 0x%X\n",pci_conf_read(pc,pt,0x44)));
650:
651: switch (sc->sc_devid) {
652: case AUTRI_DEVICE_ID_4DWAVE_DX:
653: /* disable Legacy Control */
654: pci_conf_write(pc, pt, AUTRI_PCI_DDMA_CFG,0);
655: reg = pci_conf_read(pc, pt, AUTRI_PCI_LEGACY_IOBASE);
656: pci_conf_write(pc, pt, AUTRI_PCI_LEGACY_IOBASE, reg & 0xffff0000);
657: delay(100);
658: /* audio engine reset */
659: reg = pci_conf_read(pc, pt, AUTRI_PCI_LEGACY_IOBASE);
660: pci_conf_write(pc, pt, AUTRI_PCI_LEGACY_IOBASE, reg | 0x00040000);
661: delay(100);
662: /* release reset */
663: reg = pci_conf_read(pc, pt, AUTRI_PCI_LEGACY_IOBASE);
664: pci_conf_write(pc, pt, AUTRI_PCI_LEGACY_IOBASE, reg & ~0x00040000);
665: delay(100);
666: /* DAC on */
667: autri_reg_set_4(sc,AUTRI_DX_ACR2,0x02);
668: break;
669: case AUTRI_DEVICE_ID_4DWAVE_NX:
670: /* disable Legacy Control */
671: pci_conf_write(pc, pt, AUTRI_PCI_DDMA_CFG,0);
672: reg = pci_conf_read(pc, pt, AUTRI_PCI_LEGACY_IOBASE);
673: pci_conf_write(pc, pt, AUTRI_PCI_LEGACY_IOBASE, reg & 0xffff0000);
674: delay(100);
675: /* audio engine reset */
676: reg = pci_conf_read(pc, pt, AUTRI_PCI_LEGACY_IOBASE);
677: pci_conf_write(pc, pt, AUTRI_PCI_LEGACY_IOBASE, reg | 0x00010000);
678: delay(100);
679: /* release reset */
680: reg = pci_conf_read(pc, pt, AUTRI_PCI_LEGACY_IOBASE);
681: pci_conf_write(pc, pt, AUTRI_PCI_LEGACY_IOBASE, reg & ~0x00010000);
682: delay(100);
683: /* DAC on */
684: autri_reg_set_4(sc,AUTRI_NX_ACR0,0x02);
685: break;
686: case AUTRI_DEVICE_ID_SIS_7018:
687: /* disable Legacy Control */
688: pci_conf_write(pc, pt, AUTRI_PCI_DDMA_CFG,0);
689: reg = pci_conf_read(pc, pt, AUTRI_PCI_LEGACY_IOBASE);
690: pci_conf_write(pc, pt, AUTRI_PCI_LEGACY_IOBASE, reg & 0xffff0000);
691: delay(100);
692: /* reset Digital Controller */
693: reg = pci_conf_read(pc, pt, AUTRI_PCI_LEGACY_IOBASE);
694: pci_conf_write(pc, pt, AUTRI_PCI_LEGACY_IOBASE, reg | 0x000c0000);
695: delay(100);
696: /* release reset */
697: reg = pci_conf_read(pc, pt, AUTRI_PCI_LEGACY_IOBASE);
698: pci_conf_write(pc, pt, AUTRI_PCI_LEGACY_IOBASE, reg & ~0x00040000);
699: delay(100);
700: /* disable AC97 GPIO interrupt */
701: TWRITE1(sc, AUTRI_SIS_ACGPIO, 0);
702: /* enable 64 channel mode */
703: autri_reg_set_4(sc, AUTRI_LFO_GC_CIR, BANK_B_EN);
704: break;
705: case AUTRI_DEVICE_ID_ALI_M5451:
706: /* disable Legacy Control */
707: pci_conf_write(pc, pt, AUTRI_PCI_DDMA_CFG,0);
708: reg = pci_conf_read(pc, pt, AUTRI_PCI_LEGACY_IOBASE);
709: pci_conf_write(pc, pt, AUTRI_PCI_LEGACY_IOBASE, reg & 0xffff0000);
710: delay(100);
711: /* reset Digital Controller */
712: reg = pci_conf_read(pc, pt, AUTRI_PCI_LEGACY_IOBASE);
713: pci_conf_write(pc, pt, AUTRI_PCI_LEGACY_IOBASE, reg | 0x000c0000);
714: delay(100);
715: /* release reset */
716: reg = pci_conf_read(pc, pt, AUTRI_PCI_LEGACY_IOBASE);
717: pci_conf_write(pc, pt, AUTRI_PCI_LEGACY_IOBASE, reg & ~0x00040000);
718: delay(100);
719: /* enable PCM input */
720: autri_reg_set_4(sc, AUTRI_ALI_GCONTROL, AUTRI_ALI_GCONTROL_PCM_IN);
721: break;
722: }
723:
724: if (sc->sc_devid == AUTRI_DEVICE_ID_ALI_M5451) {
725: sc->sc_play.ch = 0;
726: sc->sc_play.ch_intr = 1;
727: sc->sc_rec.ch = 31;
728: sc->sc_rec.ch_intr = 2;
729: } else {
730: sc->sc_play.ch = 0x20;
731: sc->sc_play.ch_intr = 0x21;
732: sc->sc_rec.ch = 0x22;
733: sc->sc_rec.ch_intr = 0x23;
734: }
735:
736: /* clear channel status */
737: TWRITE4(sc, AUTRI_STOP_A, 0xffffffff);
738: TWRITE4(sc, AUTRI_STOP_B, 0xffffffff);
739:
740: /* disable channel interrupt */
741: TWRITE4(sc, AUTRI_AINTEN_A, 0);
742: TWRITE4(sc, AUTRI_AINTEN_B, 0);
743:
744: #if 0
745: /* TLB */
746: if (sc->sc_devid == AUTRI_DEVICE_ID_4DWAVE_NX) {
747: TWRITE4(sc,AUTRI_NX_TLBC,0);
748: }
749: #endif
750:
751: autri_enable_loop_interrupt(sc);
752:
753: DPRINTF(("out autri_init()\n"));
754: return 0;
755: }
756:
757: void
758: autri_enable_loop_interrupt(sc_)
759: void *sc_;
760: {
761: struct autri_softc *sc = sc_;
762: u_int32_t reg;
763:
764: /*reg = (ENDLP_IE | MIDLP_IE);*/
765: reg = ENDLP_IE;
766: #if 0
767: if (sc->sc_devid == AUTRI_DEVICE_ID_SIS_7018)
768: reg |= BANK_B_EN;
769: #endif
770: autri_reg_set_4(sc,AUTRI_LFO_GC_CIR,reg);
771: }
772:
773: #if 0
774: void
775: autri_disable_loop_interrupt(sc_)
776: void *sc_;
777: {
778: struct autri_softc *sc = sc_;
779: u_int32_t reg;
780:
781: reg = (ENDLP_IE | MIDLP_IE);
782: autri_reg_clear_4(sc,AUTRI_LFO_GC_CIR,reg);
783: }
784: #endif
785:
786: int
787: autri_intr(p)
788: void *p;
789: {
790: struct autri_softc *sc = p;
791: u_int32_t intsrc;
792: u_int32_t mask, active[2];
793: int ch, endch;
794: /*
795: u_int32_t reg;
796: u_int32_t cso,eso;
797: */
798:
799: intsrc = TREAD4(sc,AUTRI_MISCINT);
800: if ((intsrc & (ADDRESS_IRQ|MPU401_IRQ)) == 0)
801: return 0;
802:
803: if (intsrc & ADDRESS_IRQ) {
804:
805: active[0] = TREAD4(sc,AUTRI_AIN_A);
806: active[1] = TREAD4(sc,AUTRI_AIN_B);
807:
808: if (sc->sc_devid == AUTRI_DEVICE_ID_ALI_M5451) {
809: endch = 32;
810: } else {
811: endch = 64;
812: }
813:
814: for (ch=0; ch<endch; ch++) {
815: mask = 1 << (ch & 0x1f);
816: if (active[(ch & 0x20) ? 1 : 0] & mask) {
817:
818: /* clear interrupt */
819: TWRITE4(sc, (ch & 0x20) ? AUTRI_AIN_B : AUTRI_AIN_A, mask);
820: /* disable interrupt */
821: autri_reg_clear_4(sc,(ch & 0x20) ? AUTRI_AINTEN_B : AUTRI_AINTEN_A, mask);
822: #if 0
823: reg = TREAD4(sc,AUTRI_LFO_GC_CIR) & ~0x0000003f;
824: TWRITE4(sc,AUTRI_LFO_GC_CIR, reg | ch);
825:
826: if (sc->sc_devid == AUTRI_DEVICE_ID_4DWAVE_NX) {
827: cso = TREAD4(sc, 0xe0) & 0x00ffffff;
828: eso = TREAD4(sc, 0xe8) & 0x00ffffff;
829: } else {
830: cso = (TREAD4(sc, 0xe0) >> 16) & 0x0000ffff;
831: eso = (TREAD4(sc, 0xe8) >> 16) & 0x0000ffff;
832: }
833: /*printf("cso=%d, eso=%d\n",cso,eso);*/
834: #endif
835: if (ch == sc->sc_play.ch_intr) {
836: if (sc->sc_play.intr)
837: sc->sc_play.intr(sc->sc_play.intr_arg);
838: }
839:
840: if (ch == sc->sc_rec.ch_intr) {
841: if (sc->sc_rec.intr)
842: sc->sc_rec.intr(sc->sc_rec.intr_arg);
843: }
844:
845: /* enable interrupt */
846: autri_reg_set_4(sc, (ch & 0x20) ? AUTRI_AINTEN_B : AUTRI_AINTEN_A, mask);
847: }
848: }
849: }
850:
851: if (intsrc & MPU401_IRQ) {
852: /* XXX */
853: }
854:
855: autri_reg_set_4(sc,AUTRI_MISCINT,
856: ST_TARGET_REACHED | MIXER_OVERFLOW | MIXER_UNDERFLOW);
857:
858: return 1;
859: }
860:
861: /*
862: *
863: */
864:
865: int
866: autri_allocmem(sc, size, align, p)
867: struct autri_softc *sc;
868: size_t size;
869: size_t align;
870: struct autri_dma *p;
871: {
872: int error;
873:
874: p->size = size;
875: error = bus_dmamem_alloc(sc->sc_dmatag, p->size, align, 0,
876: p->segs, sizeof(p->segs)/sizeof(p->segs[0]),
877: &p->nsegs, BUS_DMA_NOWAIT);
878: if (error)
879: return (error);
880:
881: error = bus_dmamem_map(sc->sc_dmatag, p->segs, p->nsegs, p->size,
882: &p->addr, BUS_DMA_NOWAIT|BUS_DMA_COHERENT);
883: if (error)
884: goto free;
885:
886: error = bus_dmamap_create(sc->sc_dmatag, p->size, 1, p->size,
887: 0, BUS_DMA_NOWAIT, &p->map);
888: if (error)
889: goto unmap;
890:
891: error = bus_dmamap_load(sc->sc_dmatag, p->map, p->addr, p->size, NULL,
892: BUS_DMA_NOWAIT);
893: if (error)
894: goto destroy;
895: return (0);
896:
897: destroy:
898: bus_dmamap_destroy(sc->sc_dmatag, p->map);
899: unmap:
900: bus_dmamem_unmap(sc->sc_dmatag, p->addr, p->size);
901: free:
902: bus_dmamem_free(sc->sc_dmatag, p->segs, p->nsegs);
903: return (error);
904: }
905:
906: int
907: autri_freemem(sc, p)
908: struct autri_softc *sc;
909: struct autri_dma *p;
910: {
911: bus_dmamap_unload(sc->sc_dmatag, p->map);
912: bus_dmamap_destroy(sc->sc_dmatag, p->map);
913: bus_dmamem_unmap(sc->sc_dmatag, p->addr, p->size);
914: bus_dmamem_free(sc->sc_dmatag, p->segs, p->nsegs);
915: return 0;
916: }
917:
918: int
919: autri_open(addr, flags)
920: void *addr;
921: int flags;
922: {
923: DPRINTF(("autri_open()\n"));
924: DPRINTFN(5,("MISCINT : 0x%08X\n",
925: TREAD4((struct autri_softc *)addr, AUTRI_MISCINT)));
926: DPRINTFN(5,("LFO_GC_CIR : 0x%08X\n",
927: TREAD4((struct autri_softc *)addr, AUTRI_LFO_GC_CIR)));
928: return 0;
929: }
930:
931: void
932: autri_close(addr)
933: void *addr;
934: {
935: DPRINTF(("autri_close()\n"));
936: }
937:
938: int
939: autri_query_encoding(addr, fp)
940: void *addr;
941: struct audio_encoding *fp;
942: {
943: switch (fp->index) {
944: case 0:
945: strlcpy(fp->name, AudioEulinear, sizeof fp->name);
946: fp->encoding = AUDIO_ENCODING_ULINEAR;
947: fp->precision = 8;
948: fp->flags = 0;
949: break;
950: case 1:
951: strlcpy(fp->name, AudioEmulaw, sizeof fp->name);
952: fp->encoding = AUDIO_ENCODING_ULAW;
953: fp->precision = 8;
954: fp->flags = AUDIO_ENCODINGFLAG_EMULATED;
955: break;
956: case 2:
957: strlcpy(fp->name, AudioEalaw, sizeof fp->name);
958: fp->encoding = AUDIO_ENCODING_ALAW;
959: fp->precision = 8;
960: fp->flags = AUDIO_ENCODINGFLAG_EMULATED;
961: break;
962: case 3:
963: strlcpy(fp->name, AudioEslinear, sizeof fp->name);
964: fp->encoding = AUDIO_ENCODING_SLINEAR;
965: fp->precision = 8;
966: fp->flags = 0;
967: break;
968: case 4:
969: strlcpy(fp->name, AudioEslinear_le, sizeof fp->name);
970: fp->encoding = AUDIO_ENCODING_SLINEAR_LE;
971: fp->precision = 16;
972: fp->flags = 0;
973: break;
974: case 5:
975: strlcpy(fp->name, AudioEulinear_le, sizeof fp->name);
976: fp->encoding = AUDIO_ENCODING_ULINEAR_LE;
977: fp->precision = 16;
978: fp->flags = 0;
979: break;
980: case 6:
981: strlcpy(fp->name, AudioEslinear_be, sizeof fp->name);
982: fp->encoding = AUDIO_ENCODING_SLINEAR_BE;
983: fp->precision = 16;
984: fp->flags = AUDIO_ENCODINGFLAG_EMULATED;
985: break;
986: case 7:
987: strlcpy(fp->name, AudioEulinear_be, sizeof fp->name);
988: fp->encoding = AUDIO_ENCODING_ULINEAR_BE;
989: fp->precision = 16;
990: fp->flags = AUDIO_ENCODINGFLAG_EMULATED;
991: break;
992: default:
993: return (EINVAL);
994: }
995:
996: return 0;
997: }
998:
999: int
1000: autri_set_params(addr, setmode, usemode, play, rec)
1001: void *addr;
1002: int setmode, usemode;
1003: struct audio_params *play, *rec;
1004: {
1005: struct audio_params *p;
1006: int mode;
1007:
1008: for (mode = AUMODE_RECORD; mode != -1;
1009: mode = mode == AUMODE_RECORD ? AUMODE_PLAY : -1) {
1010: if ((setmode & mode) == 0)
1011: continue;
1012:
1013: p = mode == AUMODE_PLAY ? play : rec;
1014:
1015: if (p->sample_rate < 4000 || p->sample_rate > 48000 ||
1016: (p->precision != 8 && p->precision != 16) ||
1017: (p->channels != 1 && p->channels != 2))
1018: return (EINVAL);
1019:
1020: p->factor = 1;
1021: p->sw_code = 0;
1022: switch (p->encoding) {
1023: case AUDIO_ENCODING_SLINEAR_BE:
1024: case AUDIO_ENCODING_ULINEAR_BE:
1025: if (p->precision == 16)
1026: p->sw_code = swap_bytes;
1027: break;
1028: case AUDIO_ENCODING_SLINEAR_LE:
1029: case AUDIO_ENCODING_ULINEAR_LE:
1030: break;
1031: case AUDIO_ENCODING_ULAW:
1032: if (mode == AUMODE_PLAY)
1033: p->sw_code = mulaw_to_ulinear8;
1034: else
1035: p->sw_code = ulinear8_to_mulaw;
1036:
1037: break;
1038: case AUDIO_ENCODING_ALAW:
1039: if (mode == AUMODE_PLAY)
1040: p->sw_code = alaw_to_ulinear8;
1041: else
1042: p->sw_code = ulinear8_to_alaw;
1043:
1044: break;
1045: default:
1046: return (EINVAL);
1047: }
1048: }
1049:
1050: return 0;
1051: }
1052:
1053: int
1054: autri_round_blocksize(addr, block)
1055: void *addr;
1056: int block;
1057: {
1058: return ((block + 3) & -4);
1059: }
1060:
1061: int
1062: autri_halt_output(addr)
1063: void *addr;
1064: {
1065: struct autri_softc *sc = addr;
1066:
1067: DPRINTF(("autri_halt_output()\n"));
1068:
1069: sc->sc_play.intr = NULL;
1070: autri_stopch(sc, sc->sc_play.ch, sc->sc_play.ch_intr);
1071: autri_disable_interrupt(sc, sc->sc_play.ch_intr);
1072:
1073: return 0;
1074: }
1075:
1076: int
1077: autri_halt_input(addr)
1078: void *addr;
1079: {
1080: struct autri_softc *sc = addr;
1081:
1082: DPRINTF(("autri_halt_input()\n"));
1083:
1084: sc->sc_rec.intr = NULL;
1085: autri_stopch(sc, sc->sc_rec.ch, sc->sc_rec.ch_intr);
1086: autri_disable_interrupt(sc, sc->sc_rec.ch_intr);
1087:
1088: return 0;
1089: }
1090:
1091: int
1092: autri_getdev(addr, retp)
1093: void *addr;
1094: struct audio_device *retp;
1095: {
1096: struct autri_softc *sc = addr;
1097:
1098: DPRINTF(("autri_getdev().\n"));
1099:
1100: strncpy(retp->name, "Trident 4DWAVE", sizeof(retp->name));
1101: snprintf(retp->version, sizeof(retp->version), "0x%02x",
1102: PCI_REVISION(sc->sc_class));
1103:
1104: switch (sc->sc_devid) {
1105: case AUTRI_DEVICE_ID_4DWAVE_DX:
1106: strncpy(retp->config, "4DWAVE-DX", sizeof(retp->config));
1107: break;
1108: case AUTRI_DEVICE_ID_4DWAVE_NX:
1109: strncpy(retp->config, "4DWAVE-NX", sizeof(retp->config));
1110: break;
1111: case AUTRI_DEVICE_ID_SIS_7018:
1112: strncpy(retp->config, "SiS 7018", sizeof(retp->config));
1113: break;
1114: case AUTRI_DEVICE_ID_ALI_M5451:
1115: strncpy(retp->config, "ALi M5451", sizeof(retp->config));
1116: break;
1117: default:
1118: strncpy(retp->config, "unknown", sizeof(retp->config));
1119: }
1120:
1121: return 0;
1122: }
1123:
1124: int
1125: autri_mixer_set_port(addr, cp)
1126: void *addr;
1127: mixer_ctrl_t *cp;
1128: {
1129: struct autri_softc *sc = addr;
1130:
1131: return (sc->sc_codec.codec_if->vtbl->mixer_set_port(
1132: sc->sc_codec.codec_if, cp));
1133: }
1134:
1135: int
1136: autri_mixer_get_port(addr, cp)
1137: void *addr;
1138: mixer_ctrl_t *cp;
1139: {
1140: struct autri_softc *sc = addr;
1141:
1142: return (sc->sc_codec.codec_if->vtbl->mixer_get_port(
1143: sc->sc_codec.codec_if, cp));
1144: }
1145:
1146: int
1147: autri_query_devinfo(addr, dip)
1148: void *addr;
1149: mixer_devinfo_t *dip;
1150: {
1151: struct autri_softc *sc = addr;
1152:
1153: return (sc->sc_codec.codec_if->vtbl->query_devinfo(
1154: sc->sc_codec.codec_if, dip));
1155: }
1156:
1157: int
1158: autri_get_portnum_by_name(sc, class, device, qualifier)
1159: struct autri_softc *sc;
1160: char *class, *device, *qualifier;
1161: {
1162: return (sc->sc_codec.codec_if->vtbl->get_portnum_by_name(
1163: sc->sc_codec.codec_if, class, device, qualifier));
1164: }
1165:
1166: void *
1167: autri_malloc(addr, direction, size, pool, flags)
1168: void *addr;
1169: int direction;
1170: size_t size;
1171: int pool, flags;
1172: {
1173: struct autri_softc *sc = addr;
1174: struct autri_dma *p;
1175: int error;
1176:
1177: p = malloc(sizeof(*p), pool, flags);
1178: if (!p)
1179: return NULL;
1180:
1181: #if 0
1182: error = autri_allocmem(sc, size, 16, p);
1183: #endif
1184: error = autri_allocmem(sc, size, 0x10000, p);
1185: if (error) {
1186: free(p, pool);
1187: return NULL;
1188: }
1189:
1190: p->next = sc->sc_dmas;
1191: sc->sc_dmas = p;
1192: return KERNADDR(p);
1193: }
1194:
1195: void
1196: autri_free(addr, ptr, pool)
1197: void *addr;
1198: void *ptr;
1199: int pool;
1200: {
1201: struct autri_softc *sc = addr;
1202: struct autri_dma **pp, *p;
1203:
1204: for (pp = &sc->sc_dmas; (p = *pp) != NULL; pp = &p->next) {
1205: if (KERNADDR(p) == ptr) {
1206: autri_freemem(sc, p);
1207: *pp = p->next;
1208: free(p, pool);
1209: return;
1210: }
1211: }
1212: }
1213:
1214: struct autri_dma *
1215: autri_find_dma(sc, addr)
1216: struct autri_softc *sc;
1217: void *addr;
1218: {
1219: struct autri_dma *p;
1220:
1221: for (p = sc->sc_dmas; p && KERNADDR(p) != addr; p = p->next)
1222: ;
1223:
1224: return p;
1225: }
1226:
1227: paddr_t
1228: autri_mappage(addr, mem, off, prot)
1229: void *addr;
1230: void *mem;
1231: off_t off;
1232: int prot;
1233: {
1234: struct autri_softc *sc = addr;
1235: struct autri_dma *p;
1236:
1237: if (off < 0)
1238: return (-1);
1239:
1240: p = autri_find_dma(sc, mem);
1241: if (!p)
1242: return (-1);
1243:
1244: return (bus_dmamem_mmap(sc->sc_dmatag, p->segs, p->nsegs,
1245: off, prot, BUS_DMA_WAITOK));
1246: }
1247:
1248: int
1249: autri_get_props(addr)
1250: void *addr;
1251: {
1252: return (AUDIO_PROP_MMAP | AUDIO_PROP_INDEPENDENT |
1253: AUDIO_PROP_FULLDUPLEX);
1254: }
1255:
1256: void
1257: autri_setup_channel(sc, mode, param)
1258: struct autri_softc *sc;
1259: int mode;
1260: struct audio_params *param;
1261: {
1262: int i, ch, channel;
1263: u_int32_t reg, cr[5];
1264: u_int32_t cso, eso;
1265: u_int32_t delta, dch[2], ctrl;
1266: u_int32_t alpha_fms, fm_vol, attribute;
1267:
1268: u_int32_t dmaaddr, dmalen;
1269: int factor, rvol, cvol;
1270: struct autri_chstatus *chst;
1271:
1272: ctrl = AUTRI_CTRL_LOOPMODE;
1273: switch (param->encoding) {
1274: case AUDIO_ENCODING_SLINEAR_BE:
1275: case AUDIO_ENCODING_SLINEAR_LE:
1276: ctrl |= AUTRI_CTRL_SIGNED;
1277: break;
1278: }
1279:
1280: factor = 0;
1281: if (param->precision == 16) {
1282: ctrl |= AUTRI_CTRL_16BIT;
1283: factor++;
1284: }
1285:
1286: if (param->channels == 2) {
1287: ctrl |= AUTRI_CTRL_STEREO;
1288: factor++;
1289: }
1290:
1291: delta = (u_int32_t)param->sample_rate;
1292: if (delta < 4000)
1293: delta = 4000;
1294: if (delta > 48000)
1295: delta = 48000;
1296:
1297: attribute = 0;
1298:
1299: dch[1] = ((delta << 12) / 48000) & 0x0000ffff;
1300: if (mode == AUMODE_PLAY) {
1301: chst = &sc->sc_play;
1302: dch[0] = ((delta << 12) / 48000) & 0x0000ffff;
1303: ctrl |= AUTRI_CTRL_WAVEVOL;
1304: /*
1305: if (sc->sc_devid == AUTRI_DEVICE_ID_ALI_M5451)
1306: ctrl |= 0x80000000;
1307: */
1308: } else {
1309: chst = &sc->sc_rec;
1310: dch[0] = ((48000 << 12) / delta) & 0x0000ffff;
1311: if (sc->sc_devid == AUTRI_DEVICE_ID_SIS_7018) {
1312: ctrl |= AUTRI_CTRL_MUTE_SIS;
1313: attribute = AUTRI_ATTR_PCMREC_SIS;
1314: if (delta != 48000)
1315: attribute |= AUTRI_ATTR_ENASRC_SIS;
1316: }
1317: ctrl |= AUTRI_CTRL_MUTE;
1318: }
1319:
1320: dmaaddr = DMAADDR(chst->dma);
1321: cso = alpha_fms = 0;
1322: rvol = cvol = 0x7f;
1323: fm_vol = 0x0 | ((rvol & 0x7f) << 7) | (cvol & 0x7f);
1324:
1325: for (ch=0; ch<2; ch++) {
1326:
1327: if (ch == 0)
1328: dmalen = (chst->length >> factor);
1329: else {
1330: /* channel for interrupt */
1331: dmalen = (chst->blksize >> factor);
1332: if (sc->sc_devid == AUTRI_DEVICE_ID_SIS_7018)
1333: ctrl |= AUTRI_CTRL_MUTE_SIS;
1334: else
1335: ctrl |= AUTRI_CTRL_MUTE;
1336: attribute = 0;
1337: }
1338:
1339: eso = dmalen - 1;
1340:
1341: switch (sc->sc_devid) {
1342: case AUTRI_DEVICE_ID_4DWAVE_DX:
1343: cr[0] = (cso << 16) | (alpha_fms & 0x0000ffff);
1344: cr[1] = dmaaddr;
1345: cr[2] = (eso << 16) | (dch[ch] & 0x0000ffff);
1346: cr[3] = fm_vol;
1347: cr[4] = ctrl;
1348: break;
1349: case AUTRI_DEVICE_ID_4DWAVE_NX:
1350: cr[0] = (dch[ch] << 24) | (cso & 0x00ffffff);
1351: cr[1] = dmaaddr;
1352: cr[2] = ((dch[ch] << 16) & 0xff000000) | (eso & 0x00ffffff);
1353: cr[3] = (alpha_fms << 16) | (fm_vol & 0x0000ffff);
1354: cr[4] = ctrl;
1355: break;
1356: case AUTRI_DEVICE_ID_SIS_7018:
1357: cr[0] = (cso << 16) | (alpha_fms & 0x0000ffff);
1358: cr[1] = dmaaddr;
1359: cr[2] = (eso << 16) | (dch[ch] & 0x0000ffff);
1360: cr[3] = attribute;
1361: cr[4] = ctrl;
1362: break;
1363: case AUTRI_DEVICE_ID_ALI_M5451:
1364: cr[0] = (cso << 16) | (alpha_fms & 0x0000ffff);
1365: cr[1] = dmaaddr;
1366: cr[2] = (eso << 16) | (dch[ch] & 0x0000ffff);
1367: cr[3] = 0;
1368: cr[4] = ctrl;
1369: break;
1370: }
1371:
1372: /* write channel data */
1373: channel = (ch == 0) ? chst->ch : chst->ch_intr;
1374:
1375: reg = TREAD4(sc,AUTRI_LFO_GC_CIR) & ~0x0000003f;
1376: TWRITE4(sc,AUTRI_LFO_GC_CIR, reg | channel);
1377:
1378: for (i=0; i<5; i++) {
1379: TWRITE4(sc, AUTRI_ARAM_CR + i*sizeof(cr[0]), cr[i]);
1380: DPRINTFN(5,("cr[%d] : 0x%08X\n", i, cr[i]));
1381: }
1382:
1383: /* Bank A only */
1384: if (channel < 0x20) {
1385: TWRITE4(sc, AUTRI_EBUF1, AUTRI_EMOD_STILL);
1386: TWRITE4(sc, AUTRI_EBUF2, AUTRI_EMOD_STILL);
1387: }
1388: }
1389:
1390: }
1391:
1392: int
1393: autri_trigger_output(addr, start, end, blksize, intr, arg, param)
1394: void *addr;
1395: void *start, *end;
1396: int blksize;
1397: void (*intr)(void *);
1398: void *arg;
1399: struct audio_params *param;
1400: {
1401: struct autri_softc *sc = addr;
1402: struct autri_dma *p;
1403:
1404: DPRINTFN(5,("autri_trigger_output: sc=%p start=%p end=%p "
1405: "blksize=%d intr=%p(%p)\n", addr, start, end, blksize, intr, arg));
1406:
1407: sc->sc_play.intr = intr;
1408: sc->sc_play.intr_arg = arg;
1409: sc->sc_play.offset = 0;
1410: sc->sc_play.blksize = blksize;
1411: sc->sc_play.length = (char *)end - (char *)start;
1412:
1413: p = autri_find_dma(sc, start);
1414: if (!p) {
1415: printf("autri_trigger_output: bad addr %p\n", start);
1416: return (EINVAL);
1417: }
1418:
1419: sc->sc_play.dma = p;
1420:
1421: /* */
1422: autri_setup_channel(sc, AUMODE_PLAY, param);
1423:
1424: /* volume set to no attenuation */
1425: TWRITE4(sc, AUTRI_MUSICVOL_WAVEVOL, 0);
1426:
1427: /* enable interrupt */
1428: autri_enable_interrupt(sc, sc->sc_play.ch_intr);
1429:
1430: /* start channel */
1431: autri_startch(sc, sc->sc_play.ch, sc->sc_play.ch_intr);
1432:
1433: return 0;
1434: }
1435:
1436: int
1437: autri_trigger_input(addr, start, end, blksize, intr, arg, param)
1438: void *addr;
1439: void *start, *end;
1440: int blksize;
1441: void (*intr)(void *);
1442: void *arg;
1443: struct audio_params *param;
1444: {
1445: struct autri_softc *sc = addr;
1446: struct autri_dma *p;
1447:
1448: DPRINTFN(5,("autri_trigger_input: sc=%p start=%p end=%p "
1449: "blksize=%d intr=%p(%p)\n", addr, start, end, blksize, intr, arg));
1450:
1451: sc->sc_rec.intr = intr;
1452: sc->sc_rec.intr_arg = arg;
1453: sc->sc_rec.offset = 0;
1454: sc->sc_rec.blksize = blksize;
1455: sc->sc_rec.length = (char *)end - (char *)start;
1456:
1457: /* */
1458: p = autri_find_dma(sc, start);
1459: if (!p) {
1460: printf("autri_trigger_input: bad addr %p\n", start);
1461: return (EINVAL);
1462: }
1463:
1464: sc->sc_rec.dma = p;
1465:
1466: /* */
1467: if (sc->sc_devid == AUTRI_DEVICE_ID_4DWAVE_NX) {
1468: autri_reg_set_4(sc, AUTRI_NX_ACR0, AUTRI_NX_ACR0_PSB_CAPTURE);
1469: TWRITE1(sc, AUTRI_NX_RCI3, AUTRI_NX_RCI3_ENABLE | sc->sc_rec.ch);
1470: }
1471:
1472: #if 0
1473: /* 4DWAVE only allows capturing at a 48KHz rate */
1474: if (sc->sc_devid == AUTRI_DEVICE_ID_4DWAVE_DX ||
1475: sc->sc_devid == AUTRI_DEVICE_ID_4DWAVE_NX)
1476: param->sample_rate = 48000;
1477: #endif
1478:
1479: autri_setup_channel(sc, AUMODE_RECORD, param);
1480:
1481: /* enable interrupt */
1482: autri_enable_interrupt(sc, sc->sc_rec.ch_intr);
1483:
1484: /* start channel */
1485: autri_startch(sc, sc->sc_rec.ch, sc->sc_rec.ch_intr);
1486:
1487: return 0;
1488: }
1489:
1490: #if 0
1491: int
1492: autri_halt(sc)
1493: struct autri_softc *sc;
1494: {
1495: DPRINTF(("autri_halt().\n"));
1496: /*autri_stopch(sc);*/
1497: autri_disable_interrupt(sc, sc->sc_play.channel);
1498: autri_disable_interrupt(sc, sc->sc_rec.channel);
1499: return 0;
1500: }
1501: #endif
1502:
1503: void
1504: autri_enable_interrupt(sc, ch)
1505: struct autri_softc *sc;
1506: int ch;
1507: {
1508: int reg;
1509:
1510: reg = (ch & 0x20) ? AUTRI_AINTEN_B : AUTRI_AINTEN_A;
1511: ch &= 0x1f;
1512:
1513: autri_reg_set_4(sc, reg, 1 << ch);
1514: }
1515:
1516: void
1517: autri_disable_interrupt(sc, ch)
1518: struct autri_softc *sc;
1519: int ch;
1520: {
1521: int reg;
1522:
1523: reg = (ch & 0x20) ? AUTRI_AINTEN_B : AUTRI_AINTEN_A;
1524: ch &= 0x1f;
1525:
1526: autri_reg_clear_4(sc, reg, 1 << ch);
1527: }
1528:
1529: void
1530: autri_startch(sc, ch, ch_intr)
1531: struct autri_softc *sc;
1532: int ch, ch_intr;
1533: {
1534: int reg;
1535: u_int32_t chmask;
1536:
1537: reg = (ch & 0x20) ? AUTRI_START_B : AUTRI_START_A;
1538: ch &= 0x1f;
1539: chmask = (1 << ch) | (1 << ch_intr);
1540:
1541: autri_reg_set_4(sc, reg, chmask);
1542: }
1543:
1544: void
1545: autri_stopch(sc, ch, ch_intr)
1546: struct autri_softc *sc;
1547: int ch, ch_intr;
1548: {
1549: int reg;
1550: u_int32_t chmask;
1551:
1552: reg = (ch & 0x20) ? AUTRI_STOP_B : AUTRI_STOP_A;
1553: ch &= 0x1f;
1554: chmask = (1 << ch) | (1 << ch_intr);
1555:
1556: autri_reg_set_4(sc, reg, chmask);
1557: }
1558:
1559: #if NMIDI > 0
1560: int
1561: autri_midi_open(void *addr, int flags,
1562: void (*iintr)(void *, int),
1563: void (*ointr)(void *),
1564: void *arg)
1565: {
1566: struct autri_softc *sc = addr;
1567:
1568: DPRINTF(("autri_midi_open()\n"));
1569:
1570: DPRINTFN(5,("MPUR1 : 0x%02X\n",TREAD1(sc,AUTRI_MPUR1)));
1571: DPRINTFN(5,("MPUR2 : 0x%02X\n",TREAD1(sc,AUTRI_MPUR2)));
1572:
1573: sc->sc_iintr = iintr;
1574: sc->sc_ointr = ointr;
1575: sc->sc_arg = arg;
1576:
1577: if (flags & FREAD)
1578: autri_reg_clear_1(sc, AUTRI_MPUR2, AUTRI_MIDIIN_ENABLE_INTR);
1579:
1580: if (flags & FWRITE)
1581: autri_reg_set_1(sc, AUTRI_MPUR2, AUTRI_MIDIOUT_CONNECT);
1582:
1583: return (0);
1584: }
1585:
1586: void
1587: autri_midi_close(void *addr)
1588: {
1589: struct autri_softc *sc = addr;
1590:
1591: DPRINTF(("autri_midi_close()\n"));
1592:
1593: tsleep(sc, PWAIT, "autri", hz/10); /* give uart a chance to drain */
1594:
1595: sc->sc_iintr = NULL;
1596: sc->sc_ointr = NULL;
1597: }
1598:
1599: int
1600: autri_midi_output(void *addr, int d)
1601: {
1602: struct autri_softc *sc = addr;
1603: int x;
1604:
1605: for (x = 0; x != MIDI_BUSY_WAIT; x++) {
1606: if ((TREAD1(sc, AUTRI_MPUR1) & AUTRI_MIDIOUT_READY) == 0) {
1607: TWRITE1(sc, AUTRI_MPUR0, d);
1608: return (0);
1609: }
1610: delay(MIDI_BUSY_DELAY);
1611: }
1612: return (EIO);
1613: }
1614:
1615: void
1616: autri_midi_getinfo(void *addr, struct midi_info *mi)
1617: {
1618: mi->name = "4DWAVE MIDI UART";
1619: mi->props = MIDI_PROP_CAN_INPUT;
1620: }
1621:
1622: #endif
CVSweb