xref: /openbsd/sys/dev/pci/autri.c (revision 5dea098c)
1 /*	$OpenBSD: autri.c,v 1.50 2022/10/26 20:19:08 kn 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 
46 #include <dev/pci/pcidevs.h>
47 #include <dev/pci/pcireg.h>
48 #include <dev/pci/pcivar.h>
49 
50 #include <sys/audioio.h>
51 #include <dev/audio_if.h>
52 #include <dev/midi_if.h>
53 #include <dev/ic/ac97.h>
54 #include <dev/ic/mpuvar.h>
55 
56 #include <machine/bus.h>
57 #include <machine/intr.h>
58 
59 #include <dev/pci/autrireg.h>
60 #include <dev/pci/autrivar.h>
61 
62 #ifdef AUDIO_DEBUG
63 # define DPRINTF(x)	if (autridebug) printf x
64 # define DPRINTFN(n,x)	if (autridebug > (n)) printf x
65 int autridebug = 0;
66 #else
67 # define DPRINTF(x)
68 # define DPRINTFN(n,x)
69 #endif
70 
71 int	autri_match(struct device *, void *, void *);
72 void	autri_attach(struct device *, struct device *, void *);
73 int	autri_activate(struct device *, int);
74 int	autri_intr(void *);
75 
76 #define DMAADDR(p) ((p)->map->dm_segs[0].ds_addr)
77 #define KERNADDR(p) ((void *)((p)->addr))
78 
79 int autri_allocmem(struct autri_softc *, size_t, size_t, struct autri_dma *);
80 int autri_freemem(struct autri_softc *, struct autri_dma *);
81 
82 #define TWRITE1(sc, r, x) bus_space_write_1((sc)->memt, (sc)->memh, (r), (x))
83 #define TWRITE2(sc, r, x) bus_space_write_2((sc)->memt, (sc)->memh, (r), (x))
84 #define TWRITE4(sc, r, x) bus_space_write_4((sc)->memt, (sc)->memh, (r), (x))
85 #define TREAD1(sc, r) bus_space_read_1((sc)->memt, (sc)->memh, (r))
86 #define TREAD2(sc, r) bus_space_read_2((sc)->memt, (sc)->memh, (r))
87 #define TREAD4(sc, r) bus_space_read_4((sc)->memt, (sc)->memh, (r))
88 
89 static __inline void autri_reg_set_1(struct autri_softc *, int, uint8_t);
90 static __inline void autri_reg_clear_1(struct autri_softc *, int, uint8_t);
91 static __inline void autri_reg_set_4(struct autri_softc *, int, uint32_t);
92 static __inline void autri_reg_clear_4(struct autri_softc *, int, uint32_t);
93 
94 int	autri_attach_codec(void *sc, struct ac97_codec_if *);
95 int	autri_read_codec(void *sc, u_int8_t a, u_int16_t *d);
96 int	autri_write_codec(void *sc, u_int8_t a, u_int16_t d);
97 void	autri_reset_codec(void *sc);
98 enum ac97_host_flags	autri_flags_codec(void *);
99 
100 int  autri_init(void *sc);
101 struct autri_dma *autri_find_dma(struct autri_softc *, void *);
102 void autri_setup_channel(struct autri_softc *sc,int mode,
103 				    struct audio_params *param);
104 void autri_enable_interrupt(struct autri_softc *sc, int ch);
105 void autri_disable_interrupt(struct autri_softc *sc, int ch);
106 void autri_startch(struct autri_softc *sc, int ch, int ch_intr);
107 void autri_stopch(struct autri_softc *sc, int ch, int ch_intr);
108 void autri_enable_loop_interrupt(void *sc);
109 #if 0
110 void autri_disable_loop_interrupt(void *sc);
111 #endif
112 
113 struct cfdriver autri_cd = {
114 	NULL, "autri", DV_DULL
115 };
116 
117 const struct cfattach autri_ca = {
118 	sizeof(struct autri_softc), autri_match, autri_attach, NULL,
119 	autri_activate
120 };
121 
122 int	autri_open(void *, int);
123 void	autri_close(void *);
124 int	autri_set_params(void *, int, int, struct audio_params *,
125 	    struct audio_params *);
126 int	autri_round_blocksize(void *, int);
127 int	autri_trigger_output(void *, void *, void *, int, void (*)(void *),
128 	    void *, struct audio_params *);
129 int	autri_trigger_input(void *, void *, void *, int, void (*)(void *),
130 	    void *, struct audio_params *);
131 int	autri_halt_output(void *);
132 int	autri_halt_input(void *);
133 int	autri_mixer_set_port(void *, mixer_ctrl_t *);
134 int	autri_mixer_get_port(void *, mixer_ctrl_t *);
135 void   *autri_malloc(void *, int, size_t, int, int);
136 void	autri_free(void *, void *, int);
137 int	autri_query_devinfo(void *addr, mixer_devinfo_t *dip);
138 
139 int	autri_get_portnum_by_name(struct autri_softc *, char *, char *, char *);
140 
141 const struct audio_hw_if autri_hw_if = {
142 	.open = autri_open,
143 	.close = autri_close,
144 	.set_params = autri_set_params,
145 	.round_blocksize = autri_round_blocksize,
146 	.halt_output = autri_halt_output,
147 	.halt_input = autri_halt_input,
148 	.set_port = autri_mixer_set_port,
149 	.get_port = autri_mixer_get_port,
150 	.query_devinfo = autri_query_devinfo,
151 	.allocm = autri_malloc,
152 	.freem = autri_free,
153 	.trigger_output = autri_trigger_output,
154 	.trigger_input = autri_trigger_input,
155 };
156 
157 #if NMIDI > 0
158 void	autri_midi_close(void *);
159 void	autri_midi_getinfo(void *, struct midi_info *);
160 int	autri_midi_open(void *, int, void (*)(void *, int),
161 			   void (*)(void *), void *);
162 int	autri_midi_output(void *, int);
163 
164 const struct midi_hw_if autri_midi_hw_if = {
165 	autri_midi_open,
166 	autri_midi_close,
167 	autri_midi_output,
168 	NULL,			/* flush */
169 	autri_midi_getinfo,
170 	NULL,			/* ioctl */
171 };
172 #endif
173 
174 /*
175  * register set/clear bit
176  */
177 static __inline void
178 autri_reg_set_1(struct autri_softc *sc, int no, uint8_t mask)
179 {
180 	bus_space_write_1(sc->memt, sc->memh, no,
181 	    (bus_space_read_1(sc->memt, sc->memh, no) | mask));
182 }
183 
184 static __inline void
185 autri_reg_clear_1(struct autri_softc *sc, int no, uint8_t mask)
186 {
187 	bus_space_write_1(sc->memt, sc->memh, no,
188 	    (bus_space_read_1(sc->memt, sc->memh, no) & ~mask));
189 }
190 
191 static __inline void
192 autri_reg_set_4(struct autri_softc *sc, int no, uint32_t mask)
193 {
194 	bus_space_write_4(sc->memt, sc->memh, no,
195 	    (bus_space_read_4(sc->memt, sc->memh, no) | mask));
196 }
197 
198 static __inline void
199 autri_reg_clear_4(struct autri_softc *sc, int no, uint32_t mask)
200 {
201 	bus_space_write_4(sc->memt, sc->memh, no,
202 	    (bus_space_read_4(sc->memt, sc->memh, no) & ~mask));
203 }
204 
205 /*
206  * AC97 codec
207  */
208 int
209 autri_attach_codec(void *sc_, struct ac97_codec_if *codec_if)
210 {
211 	struct autri_codec_softc *sc = sc_;
212 
213 	DPRINTF(("autri_attach_codec()\n"));
214 
215 	sc->codec_if = codec_if;
216 	return 0;
217 }
218 
219 int
220 autri_read_codec(void *sc_, u_int8_t index, u_int16_t *data)
221 {
222 	struct autri_codec_softc *codec = sc_;
223 	struct autri_softc *sc = codec->sc;
224 	u_int32_t status, addr, cmd, busy;
225 	u_int16_t count;
226 
227 	/*DPRINTF(("sc->sc->type : 0x%X",sc->sc->type));*/
228 
229 	switch (sc->sc_devid) {
230 	case AUTRI_DEVICE_ID_4DWAVE_DX:
231 		addr = AUTRI_DX_ACR1;
232 		cmd  = AUTRI_DX_ACR1_CMD_READ;
233 		busy = AUTRI_DX_ACR1_BUSY_READ;
234 		break;
235 	case AUTRI_DEVICE_ID_4DWAVE_NX:
236 		addr = AUTRI_NX_ACR2;
237 		cmd  = AUTRI_NX_ACR2_CMD_READ;
238 		busy = AUTRI_NX_ACR2_BUSY_READ | AUTRI_NX_ACR2_RECV_WAIT;
239 		break;
240 	case AUTRI_DEVICE_ID_SIS_7018:
241 		addr = AUTRI_SIS_ACRD;
242 		cmd  = AUTRI_SIS_ACRD_CMD_READ;
243 		busy = AUTRI_SIS_ACRD_BUSY_READ | AUTRI_SIS_ACRD_AUDIO_BUSY;
244 		break;
245 	case AUTRI_DEVICE_ID_ALI_M5451:
246 		if (sc->sc_revision > 0x01)
247 			addr = AUTRI_ALI_ACWR;
248 		else
249 			addr = AUTRI_ALI_ACRD;
250 		cmd  = AUTRI_ALI_ACRD_CMD_READ;
251 		busy = AUTRI_ALI_ACRD_BUSY_READ;
252 		break;
253 	default:
254 		printf("%s: autri_read_codec : unknown device\n",
255 		    sc->sc_dev.dv_xname);
256 		return -1;
257 	}
258 
259 	/* wait for 'Ready to Read' */
260 	for (count=0; count < 0xffff; count++) {
261 		if ((TREAD4(sc, addr) & busy) == 0)
262 			break;
263 		DELAY(1);
264 	}
265 
266 	if (count == 0xffff) {
267 		printf("%s: Codec timeout. Busy reading AC97 codec.\n",
268 		    sc->sc_dev.dv_xname);
269 		return -1;
270 	}
271 
272 	/* send Read Command to AC97 */
273 	TWRITE4(sc, addr, (index & 0x7f) | cmd);
274 
275 	/* wait for 'Returned data is available' */
276 	for (count=0; count < 0xffff; count++) {
277 		status = TREAD4(sc, addr);
278 		if ((status & busy) == 0)
279 			break;
280 		DELAY(1);
281 	}
282 
283 	if (count == 0xffff) {
284 		printf("%s: Codec timeout. Busy reading AC97 codec.\n",
285 		    sc->sc_dev.dv_xname);
286 		return -1;
287 	}
288 
289 	*data =  (status >> 16) & 0x0000ffff;
290 	/*DPRINTF(("autri_read_codec(0x%X) return 0x%X\n",reg,*data));*/
291 	return 0;
292 }
293 
294 int
295 autri_write_codec(void *sc_, u_int8_t index, u_int16_t data)
296 {
297 	struct autri_codec_softc *codec = sc_;
298 	struct autri_softc *sc = codec->sc;
299 	u_int32_t addr, cmd, busy;
300 	u_int16_t count;
301 
302 	/*DPRINTF(("autri_write_codec(0x%X,0x%X)\n",index,data));*/
303 
304 	switch (sc->sc_devid) {
305 	case AUTRI_DEVICE_ID_4DWAVE_DX:
306 		addr = AUTRI_DX_ACR0;
307 		cmd  = AUTRI_DX_ACR0_CMD_WRITE;
308 		busy = AUTRI_DX_ACR0_BUSY_WRITE;
309 		break;
310 	case AUTRI_DEVICE_ID_4DWAVE_NX:
311 		addr = AUTRI_NX_ACR1;
312 		cmd  = AUTRI_NX_ACR1_CMD_WRITE;
313 		busy = AUTRI_NX_ACR1_BUSY_WRITE;
314 		break;
315 	case AUTRI_DEVICE_ID_SIS_7018:
316 		addr = AUTRI_SIS_ACWR;
317 		cmd  = AUTRI_SIS_ACWR_CMD_WRITE;
318 		busy = AUTRI_SIS_ACWR_BUSY_WRITE | AUTRI_SIS_ACWR_AUDIO_BUSY;
319 		break;
320 	case AUTRI_DEVICE_ID_ALI_M5451:
321 		addr = AUTRI_ALI_ACWR;
322 		cmd  = AUTRI_ALI_ACWR_CMD_WRITE;
323 		if (sc->sc_revision > 0x01)
324 			cmd  |= 0x0100;
325 		busy = AUTRI_ALI_ACWR_BUSY_WRITE;
326 		break;
327 	default:
328 		printf("%s: autri_write_codec : unknown device.\n",
329 		    sc->sc_dev.dv_xname);
330 		return -1;
331 	}
332 
333 	/* wait for 'Ready to Write' */
334 	for (count=0; count < 0xffff; count++) {
335 		if ((TREAD4(sc, addr) & busy) == 0)
336 			break;
337 		DELAY(1);
338 	}
339 
340 	if (count == 0xffff) {
341 		printf("%s: Codec timeout. Busy writing AC97 codec\n",
342 		    sc->sc_dev.dv_xname);
343 		return -1;
344 	}
345 
346 	/* send Write Command to AC97 */
347 	TWRITE4(sc, addr, (data << 16) | (index & 0x7f) | cmd);
348 
349 	return 0;
350 }
351 
352 void
353 autri_reset_codec(void *sc_)
354 {
355 	struct autri_codec_softc *codec = sc_;
356 	struct autri_softc *sc = codec->sc;
357 	u_int32_t reg, ready;
358 	int addr, count = 200;
359 
360 	DPRINTF(("autri_reset_codec(codec=%p,sc=%p)\n",codec,sc));
361 	DPRINTF(("sc->sc_devid=%X\n",sc->sc_devid));
362 
363 	switch (sc->sc_devid) {
364 	case AUTRI_DEVICE_ID_4DWAVE_DX:
365 		/* warm reset AC97 codec */
366 		autri_reg_set_4(sc, AUTRI_DX_ACR2, 1);
367 		delay(100);
368 		/* release reset */
369 		autri_reg_clear_4(sc, AUTRI_DX_ACR2, 1);
370 		delay(100);
371 
372 		addr = AUTRI_DX_ACR2;
373 		ready = AUTRI_DX_ACR2_CODEC_READY;
374 		break;
375 	case AUTRI_DEVICE_ID_4DWAVE_NX:
376 		/* warm reset AC97 codec */
377 		autri_reg_set_4(sc, AUTRI_NX_ACR0, 1);
378 		delay(100);
379 		/* release reset */
380 		autri_reg_clear_4(sc, AUTRI_NX_ACR0, 1);
381 		delay(100);
382 
383 		addr = AUTRI_NX_ACR0;
384 		ready = AUTRI_NX_ACR0_CODEC_READY;
385 		break;
386 	case AUTRI_DEVICE_ID_SIS_7018:
387 		/* warm reset AC97 codec */
388 		autri_reg_set_4(sc, AUTRI_SIS_SCTRL, 2);
389 		delay(1000);
390 		/* release reset (warm & cold) */
391 		autri_reg_clear_4(sc, AUTRI_SIS_SCTRL, 3);
392 		delay(2000);
393 
394 		addr = AUTRI_SIS_SCTRL;
395 		ready = AUTRI_SIS_SCTRL_CODEC_READY;
396 		break;
397 	case AUTRI_DEVICE_ID_ALI_M5451:
398 		/* warm reset AC97 codec */
399 		autri_reg_set_4(sc, AUTRI_ALI_SCTRL, 1);
400 		delay(100);
401 		/* release reset (warm & cold) */
402 		autri_reg_clear_4(sc, AUTRI_ALI_SCTRL, 3);
403 		delay(100);
404 
405 		addr = AUTRI_ALI_SCTRL;
406 		ready = AUTRI_ALI_SCTRL_CODEC_READY;
407 		break;
408 	}
409 
410 	/* wait for 'Codec Ready' */
411 	while (count--) {
412 		reg = TREAD4(sc, addr);
413 		if (reg & ready)
414 			break;
415 		delay(1000);
416 	}
417 
418 	if (count == 0)
419 		printf("%s: Codec timeout. AC97 is not ready for operation.\n",
420 		    sc->sc_dev.dv_xname);
421 }
422 
423 enum ac97_host_flags
424 autri_flags_codec(void *v)
425 {
426 	struct autri_codec_softc *sc = v;
427 
428 	return (sc->flags);
429 }
430 
431 /*
432  *
433  */
434 const struct pci_matchid autri_devices[] = {
435 	{ PCI_VENDOR_TRIDENT, PCI_PRODUCT_TRIDENT_4DWAVE_NX },
436 	{ PCI_VENDOR_SIS, PCI_PRODUCT_SIS_7018 },
437 	{ PCI_VENDOR_ALI, PCI_PRODUCT_ALI_M5451 }
438 };
439 
440 int
441 autri_match(struct device *parent, void *match, void *aux)
442 {
443 	struct pci_attach_args *pa = aux;
444 
445 	if (PCI_VENDOR(pa->pa_id) == PCI_VENDOR_TRIDENT &&
446 	    PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_TRIDENT_4DWAVE_DX) {
447 		/*
448 		 * IBM makes a pcn network card and improperly
449 		 * sets the vendor and product ID's.  Avoid matching.
450 		 */
451 		if (PCI_CLASS(pa->pa_class) == PCI_CLASS_NETWORK)
452 			return (0);
453 		else
454 			return (1);
455 	}
456 
457 	return (pci_matchbyid((struct pci_attach_args *)aux, autri_devices,
458 	    nitems(autri_devices)));
459 }
460 
461 void
462 autri_attach(struct device *parent, struct device *self, void *aux)
463 {
464 	struct autri_softc *sc = (struct autri_softc *)self;
465 	struct pci_attach_args *pa = (struct pci_attach_args *)aux;
466 	pci_chipset_tag_t pc = pa->pa_pc;
467 	struct autri_codec_softc *codec;
468 	bus_size_t iosize;
469 	pci_intr_handle_t ih;
470 	char const *intrstr;
471 	mixer_ctrl_t ctl;
472 	int i, r;
473 
474 	sc->sc_devid = pa->pa_id;
475 	sc->sc_class = pa->pa_class;
476 	sc->sc_revision = PCI_REVISION(pa->pa_class);
477 
478 	/* map register to memory */
479 	if (pci_mapreg_map(pa, AUTRI_PCI_MEMORY_BASE,
480 	    PCI_MAPREG_TYPE_MEM, 0, &sc->memt, &sc->memh, NULL, &iosize, 0)) {
481 		printf("%s: can't map mem space\n", sc->sc_dev.dv_xname);
482 		return;
483 	}
484 
485 	/* map and establish the interrupt */
486 	if (pci_intr_map(pa, &ih)) {
487 		printf("%s: couldn't map interrupt\n", sc->sc_dev.dv_xname);
488 		bus_space_unmap(sc->memt, sc->memh, iosize);
489 		return;
490 	}
491 	intrstr = pci_intr_string(pc, ih);
492 	sc->sc_ih = pci_intr_establish(pc, ih, IPL_AUDIO | IPL_MPSAFE,
493 	    autri_intr, sc, sc->sc_dev.dv_xname);
494 	if (sc->sc_ih == NULL) {
495 		printf("%s: couldn't establish interrupt",
496 		    sc->sc_dev.dv_xname);
497 		if (intrstr != NULL)
498 			printf(" at %s", intrstr);
499 		printf("\n");
500 		bus_space_unmap(sc->memt, sc->memh, iosize);
501 		return;
502 	}
503 	printf(": %s\n", intrstr);
504 
505 	sc->sc_dmatag = pa->pa_dmat;
506 	sc->sc_pc = pc;
507 	sc->sc_pt = pa->pa_tag;
508 
509 	/* initialize the device */
510 	autri_init(sc);
511 
512 	/* attach AC97 codec */
513 	codec = &sc->sc_codec;
514 	memcpy(&codec->sc_dev, &sc->sc_dev, sizeof(codec->sc_dev));
515 	codec->sc = sc;
516 
517 	codec->host_if.arg = codec;
518 	codec->host_if.attach = autri_attach_codec;
519 	codec->host_if.reset = autri_reset_codec;
520 	codec->host_if.read = autri_read_codec;
521 	codec->host_if.write = autri_write_codec;
522 	codec->host_if.flags = autri_flags_codec;
523 	codec->flags = AC97_HOST_DONT_READ | AC97_HOST_SWAPPED_CHANNELS;
524 	if (sc->sc_dev.dv_cfdata->cf_flags & 0x0001)
525 		codec->flags &= ~AC97_HOST_SWAPPED_CHANNELS;
526 
527 	if ((r = ac97_attach(&codec->host_if)) != 0) {
528 		printf("%s: can't attach codec (error 0x%X)\n",
529 		    sc->sc_dev.dv_xname, r);
530 		pci_intr_disestablish(pc, sc->sc_ih);
531 		bus_space_unmap(sc->memt, sc->memh, iosize);
532 		return;
533 	}
534 
535 	/* disable mutes */
536 	for (i = 0; i < 4; i++) {
537 		static struct {
538 			char *class, *device;
539 		} d[] = {
540 			{ AudioCoutputs, AudioNmaster},
541 			{ AudioCinputs, AudioNdac},
542 			{ AudioCinputs, AudioNcd},
543 			{ AudioCrecord, AudioNvolume},
544 		};
545 
546 		ctl.type = AUDIO_MIXER_ENUM;
547 		ctl.un.ord = 0;
548 
549 #if 0
550 		ctl.dev = sc->sc_codec.codec_if->vtbl->get_portnum_by_name(sc->sc_codec.codec_if,
551 		    d[i].class, d[i].device, AudioNmute);
552 #endif
553 		ctl.dev = autri_get_portnum_by_name(sc,d[i].class,
554 						   d[i].device, AudioNmute);
555 		autri_mixer_set_port(sc, &ctl);
556 	}
557 
558 	/* set a reasonable default volume */
559 	ctl.type = AUDIO_MIXER_VALUE;
560 	ctl.un.value.num_channels = 2;
561 	ctl.un.value.level[AUDIO_MIXER_LEVEL_LEFT] =
562 	ctl.un.value.level[AUDIO_MIXER_LEVEL_RIGHT] = 127;
563 
564 	ctl.dev = autri_get_portnum_by_name(sc,AudioCoutputs,AudioNmaster,NULL);
565 	autri_mixer_set_port(sc, &ctl);
566 
567 	audio_attach_mi(&autri_hw_if, sc, NULL, &sc->sc_dev);
568 
569 #if NMIDI > 0
570 	midi_attach_mi(&autri_midi_hw_if, sc, &sc->sc_dev);
571 #endif
572 }
573 
574 int
575 autri_activate(struct device *self, int act)
576 {
577 	struct autri_softc *sc = (struct autri_softc *)self;
578 
579 	if (act == DVACT_RESUME) {
580 		autri_init(sc);
581 		ac97_resume(&sc->sc_codec.host_if, sc->sc_codec.codec_if);
582 	}
583 	return (config_activate_children(self, act));
584 }
585 
586 int
587 autri_init(void *sc_)
588 {
589 	struct autri_softc *sc = sc_;
590 	pcireg_t reg;
591 
592 	pci_chipset_tag_t pc = sc->sc_pc;
593 	pcitag_t pt = sc->sc_pt;
594 
595 	DPRINTF(("in autri_init()\n"));
596 	DPRINTFN(5,("pci_conf_read(0x40) : 0x%X\n",pci_conf_read(pc,pt,0x40)));
597 	DPRINTFN(5,("pci_conf_read(0x44) : 0x%X\n",pci_conf_read(pc,pt,0x44)));
598 
599 	switch (sc->sc_devid) {
600 	case AUTRI_DEVICE_ID_4DWAVE_DX:
601 		/* disable Legacy Control */
602 		pci_conf_write(pc, pt, AUTRI_PCI_DDMA_CFG,0);
603 		reg = pci_conf_read(pc, pt, AUTRI_PCI_LEGACY_IOBASE);
604 		pci_conf_write(pc, pt, AUTRI_PCI_LEGACY_IOBASE, reg & 0xffff0000);
605 		delay(100);
606 		/* audio engine reset */
607 		reg = pci_conf_read(pc, pt, AUTRI_PCI_LEGACY_IOBASE);
608 		pci_conf_write(pc, pt, AUTRI_PCI_LEGACY_IOBASE, reg | 0x00040000);
609 		delay(100);
610 		/* release reset */
611 		reg = pci_conf_read(pc, pt, AUTRI_PCI_LEGACY_IOBASE);
612 		pci_conf_write(pc, pt, AUTRI_PCI_LEGACY_IOBASE, reg & ~0x00040000);
613 		delay(100);
614 		/* DAC on */
615 		autri_reg_set_4(sc,AUTRI_DX_ACR2,0x02);
616 		break;
617 	case AUTRI_DEVICE_ID_4DWAVE_NX:
618 		/* disable Legacy Control */
619 		pci_conf_write(pc, pt, AUTRI_PCI_DDMA_CFG,0);
620 		reg = pci_conf_read(pc, pt, AUTRI_PCI_LEGACY_IOBASE);
621 		pci_conf_write(pc, pt, AUTRI_PCI_LEGACY_IOBASE, reg & 0xffff0000);
622 		delay(100);
623 		/* audio engine reset */
624 		reg = pci_conf_read(pc, pt, AUTRI_PCI_LEGACY_IOBASE);
625 		pci_conf_write(pc, pt, AUTRI_PCI_LEGACY_IOBASE, reg | 0x00010000);
626 		delay(100);
627 		/* release reset */
628 		reg = pci_conf_read(pc, pt, AUTRI_PCI_LEGACY_IOBASE);
629 		pci_conf_write(pc, pt, AUTRI_PCI_LEGACY_IOBASE, reg & ~0x00010000);
630 		delay(100);
631 		/* DAC on */
632 		autri_reg_set_4(sc,AUTRI_NX_ACR0,0x02);
633 		break;
634 	case AUTRI_DEVICE_ID_SIS_7018:
635 		/* disable Legacy Control */
636 		pci_conf_write(pc, pt, AUTRI_PCI_DDMA_CFG,0);
637 		reg = pci_conf_read(pc, pt, AUTRI_PCI_LEGACY_IOBASE);
638 		pci_conf_write(pc, pt, AUTRI_PCI_LEGACY_IOBASE, reg & 0xffff0000);
639 		delay(100);
640 		/* reset Digital Controller */
641 		reg = pci_conf_read(pc, pt, AUTRI_PCI_LEGACY_IOBASE);
642 		pci_conf_write(pc, pt, AUTRI_PCI_LEGACY_IOBASE, reg | 0x000c0000);
643 		delay(100);
644 		/* release reset */
645 		reg = pci_conf_read(pc, pt, AUTRI_PCI_LEGACY_IOBASE);
646 		pci_conf_write(pc, pt, AUTRI_PCI_LEGACY_IOBASE, reg & ~0x00040000);
647 		delay(100);
648 		/* disable AC97 GPIO interrupt */
649 		TWRITE1(sc, AUTRI_SIS_ACGPIO, 0);
650 		/* enable 64 channel mode */
651 		autri_reg_set_4(sc, AUTRI_LFO_GC_CIR, BANK_B_EN);
652 		break;
653 	case AUTRI_DEVICE_ID_ALI_M5451:
654 		/* disable Legacy Control */
655 		pci_conf_write(pc, pt, AUTRI_PCI_DDMA_CFG,0);
656 		reg = pci_conf_read(pc, pt, AUTRI_PCI_LEGACY_IOBASE);
657 		pci_conf_write(pc, pt, AUTRI_PCI_LEGACY_IOBASE, reg & 0xffff0000);
658 		delay(100);
659 		/* reset Digital Controller */
660 		reg = pci_conf_read(pc, pt, AUTRI_PCI_LEGACY_IOBASE);
661 		pci_conf_write(pc, pt, AUTRI_PCI_LEGACY_IOBASE, reg | 0x000c0000);
662 		delay(100);
663 		/* release reset */
664 		reg = pci_conf_read(pc, pt, AUTRI_PCI_LEGACY_IOBASE);
665 		pci_conf_write(pc, pt, AUTRI_PCI_LEGACY_IOBASE, reg & ~0x00040000);
666 		delay(100);
667 		/* enable PCM input */
668 		autri_reg_set_4(sc, AUTRI_ALI_GCONTROL, AUTRI_ALI_GCONTROL_PCM_IN);
669 		break;
670 	}
671 
672 	if (sc->sc_devid == AUTRI_DEVICE_ID_ALI_M5451) {
673 		sc->sc_play.ch      = 0;
674 		sc->sc_play.ch_intr = 1;
675 		sc->sc_rec.ch       = 2;
676 		sc->sc_rec.ch_intr  = 3;
677 	} else {
678 		sc->sc_play.ch      = 0x20;
679 		sc->sc_play.ch_intr = 0x21;
680 		sc->sc_rec.ch       = 0x22;
681 		sc->sc_rec.ch_intr  = 0x23;
682 	}
683 
684 	/* clear channel status */
685 	TWRITE4(sc, AUTRI_STOP_A, 0xffffffff);
686 	TWRITE4(sc, AUTRI_STOP_B, 0xffffffff);
687 
688 	/* disable channel interrupt */
689 	TWRITE4(sc, AUTRI_AINTEN_A, 0);
690 	TWRITE4(sc, AUTRI_AINTEN_B, 0);
691 
692 #if 0
693 	/* TLB */
694 	if (sc->sc_devid == AUTRI_DEVICE_ID_4DWAVE_NX) {
695 		TWRITE4(sc,AUTRI_NX_TLBC,0);
696 	}
697 #endif
698 
699 	autri_enable_loop_interrupt(sc);
700 
701 	DPRINTF(("out autri_init()\n"));
702 	return 0;
703 }
704 
705 void
706 autri_enable_loop_interrupt(void *sc_)
707 {
708 	struct autri_softc *sc = sc_;
709 	u_int32_t reg;
710 
711 	/*reg = (ENDLP_IE | MIDLP_IE);*/
712 	reg = ENDLP_IE;
713 #if 0
714 	if (sc->sc_devid == AUTRI_DEVICE_ID_SIS_7018)
715 		reg |= BANK_B_EN;
716 #endif
717 	autri_reg_set_4(sc,AUTRI_LFO_GC_CIR,reg);
718 }
719 
720 #if 0
721 void
722 autri_disable_loop_interrupt(void *sc_)
723 {
724 	struct autri_softc *sc = sc_;
725 	u_int32_t reg;
726 
727 	reg = (ENDLP_IE | MIDLP_IE);
728 	autri_reg_clear_4(sc,AUTRI_LFO_GC_CIR,reg);
729 }
730 #endif
731 
732 int
733 autri_intr(void *p)
734 {
735 	struct autri_softc *sc = p;
736 	u_int32_t intsrc;
737 	u_int32_t mask, active[2];
738 	int ch, endch;
739 /*
740 	u_int32_t reg;
741 	u_int32_t cso,eso;
742 */
743 
744 	mtx_enter(&audio_lock);
745 	intsrc = TREAD4(sc,AUTRI_MISCINT);
746 	if ((intsrc & (ADDRESS_IRQ|MPU401_IRQ)) == 0) {
747 		mtx_leave(&audio_lock);
748 		return 0;
749 	}
750 
751 	if (intsrc & ADDRESS_IRQ) {
752 
753 		active[0] = TREAD4(sc,AUTRI_AIN_A);
754 		active[1] = TREAD4(sc,AUTRI_AIN_B);
755 
756 		if (sc->sc_devid == AUTRI_DEVICE_ID_ALI_M5451) {
757 			endch = 32;
758 		} else {
759 			endch = 64;
760 		}
761 
762 		for (ch=0; ch<endch; ch++) {
763 			mask = 1 << (ch & 0x1f);
764 			if (active[(ch & 0x20) ? 1 : 0] & mask) {
765 
766 				/* clear interrupt */
767 				TWRITE4(sc, (ch & 0x20) ? AUTRI_AIN_B : AUTRI_AIN_A, mask);
768 				/* disable interrupt */
769 				autri_reg_clear_4(sc,(ch & 0x20) ? AUTRI_AINTEN_B : AUTRI_AINTEN_A, mask);
770 #if 0
771 				reg = TREAD4(sc,AUTRI_LFO_GC_CIR) & ~0x0000003f;
772 				TWRITE4(sc,AUTRI_LFO_GC_CIR, reg | ch);
773 
774 				if (sc->sc_devid == AUTRI_DEVICE_ID_4DWAVE_NX) {
775 				  cso = TREAD4(sc, 0xe0) & 0x00ffffff;
776 				  eso = TREAD4(sc, 0xe8) & 0x00ffffff;
777 				} else {
778 				  cso = (TREAD4(sc, 0xe0) >> 16) & 0x0000ffff;
779 				  eso = (TREAD4(sc, 0xe8) >> 16) & 0x0000ffff;
780 				}
781 				/*printf("cso=%d, eso=%d\n",cso,eso);*/
782 #endif
783 				if (ch == sc->sc_play.ch_intr) {
784 					if (sc->sc_play.intr)
785 						sc->sc_play.intr(sc->sc_play.intr_arg);
786 				}
787 
788 				if (ch == sc->sc_rec.ch_intr) {
789 					if (sc->sc_rec.intr)
790 						sc->sc_rec.intr(sc->sc_rec.intr_arg);
791 				}
792 
793 				/* enable interrupt */
794 				autri_reg_set_4(sc, (ch & 0x20) ? AUTRI_AINTEN_B : AUTRI_AINTEN_A, mask);
795 			}
796 		}
797 	}
798 
799 	if (intsrc & MPU401_IRQ) {
800 		/* XXX */
801 	}
802 
803 	autri_reg_set_4(sc,AUTRI_MISCINT,
804 		ST_TARGET_REACHED | MIXER_OVERFLOW | MIXER_UNDERFLOW);
805 	mtx_leave(&audio_lock);
806 	return 1;
807 }
808 
809 /*
810  *
811  */
812 
813 int
814 autri_allocmem(struct autri_softc *sc, size_t size, size_t align,
815     struct autri_dma *p)
816 {
817 	int error;
818 
819 	p->size = size;
820 	error = bus_dmamem_alloc(sc->sc_dmatag, p->size, align, 0,
821 	    p->segs, nitems(p->segs), &p->nsegs, BUS_DMA_NOWAIT);
822 	if (error)
823 		return (error);
824 
825 	error = bus_dmamem_map(sc->sc_dmatag, p->segs, p->nsegs, p->size,
826 	    &p->addr, BUS_DMA_NOWAIT|BUS_DMA_COHERENT);
827 	if (error)
828 		goto free;
829 
830 	error = bus_dmamap_create(sc->sc_dmatag, p->size, 1, p->size,
831 	    0, BUS_DMA_NOWAIT, &p->map);
832 	if (error)
833 		goto unmap;
834 
835 	error = bus_dmamap_load(sc->sc_dmatag, p->map, p->addr, p->size, NULL,
836 	    BUS_DMA_NOWAIT);
837 	if (error)
838 		goto destroy;
839 	return (0);
840 
841 destroy:
842 	bus_dmamap_destroy(sc->sc_dmatag, p->map);
843 unmap:
844 	bus_dmamem_unmap(sc->sc_dmatag, p->addr, p->size);
845 free:
846 	bus_dmamem_free(sc->sc_dmatag, p->segs, p->nsegs);
847 	return (error);
848 }
849 
850 int
851 autri_freemem(struct autri_softc *sc, struct autri_dma *p)
852 {
853 	bus_dmamap_unload(sc->sc_dmatag, p->map);
854 	bus_dmamap_destroy(sc->sc_dmatag, p->map);
855 	bus_dmamem_unmap(sc->sc_dmatag, p->addr, p->size);
856 	bus_dmamem_free(sc->sc_dmatag, p->segs, p->nsegs);
857 	return 0;
858 }
859 
860 int
861 autri_open(void *addr, int flags)
862 {
863 	DPRINTF(("autri_open()\n"));
864 	DPRINTFN(5,("MISCINT    : 0x%08X\n",
865 	    TREAD4((struct autri_softc *)addr, AUTRI_MISCINT)));
866 	DPRINTFN(5,("LFO_GC_CIR : 0x%08X\n",
867 	    TREAD4((struct autri_softc *)addr, AUTRI_LFO_GC_CIR)));
868 	return 0;
869 }
870 
871 void
872 autri_close(void *addr)
873 {
874 	DPRINTF(("autri_close()\n"));
875 }
876 
877 int
878 autri_set_params(void *addr, int setmode, int usemode, struct audio_params *play,
879     struct audio_params *rec)
880 {
881 	struct audio_params *p;
882 	int mode;
883 
884 	for (mode = AUMODE_RECORD; mode != -1;
885 	    mode = mode == AUMODE_RECORD ? AUMODE_PLAY : -1) {
886 		if ((setmode & mode) == 0)
887 			continue;
888 		p = mode == AUMODE_PLAY ? play : rec;
889 		p->sample_rate = 48000;
890 		if (p->precision != 8)
891 			p->precision = 16;
892 		if (p->channels != 1)
893 			p->channels = 2;
894 		p->encoding = p->precision == 16 ?
895 		    AUDIO_ENCODING_SLINEAR_LE : AUDIO_ENCODING_ULINEAR_LE;
896 		p->bps = AUDIO_BPS(p->precision);
897 		p->msb = 1;
898 	}
899 
900 	return 0;
901 }
902 
903 int
904 autri_round_blocksize(void *addr, int block)
905 {
906 	return ((block + 3) & -4);
907 }
908 
909 int
910 autri_halt_output(void *addr)
911 {
912 	struct autri_softc *sc = addr;
913 
914 	DPRINTF(("autri_halt_output()\n"));
915 	mtx_enter(&audio_lock);
916 	sc->sc_play.intr = NULL;
917 	autri_stopch(sc, sc->sc_play.ch, sc->sc_play.ch_intr);
918 	autri_disable_interrupt(sc, sc->sc_play.ch_intr);
919 	mtx_leave(&audio_lock);
920 	return 0;
921 }
922 
923 int
924 autri_halt_input(void *addr)
925 {
926 	struct autri_softc *sc = addr;
927 
928 	DPRINTF(("autri_halt_input()\n"));
929 	mtx_enter(&audio_lock);
930 	sc->sc_rec.intr = NULL;
931 	autri_stopch(sc, sc->sc_rec.ch, sc->sc_rec.ch_intr);
932 	autri_disable_interrupt(sc, sc->sc_rec.ch_intr);
933 	mtx_leave(&audio_lock);
934 	return 0;
935 }
936 
937 int
938 autri_mixer_set_port(void *addr, mixer_ctrl_t *cp)
939 {
940 	struct autri_softc *sc = addr;
941 
942 	return (sc->sc_codec.codec_if->vtbl->mixer_set_port(
943 	    sc->sc_codec.codec_if, cp));
944 }
945 
946 int
947 autri_mixer_get_port(void *addr, mixer_ctrl_t *cp)
948 {
949 	struct autri_softc *sc = addr;
950 
951 	return (sc->sc_codec.codec_if->vtbl->mixer_get_port(
952 	    sc->sc_codec.codec_if, cp));
953 }
954 
955 int
956 autri_query_devinfo(void *addr, mixer_devinfo_t *dip)
957 {
958 	struct autri_softc *sc = addr;
959 
960 	return (sc->sc_codec.codec_if->vtbl->query_devinfo(
961 	    sc->sc_codec.codec_if, dip));
962 }
963 
964 int
965 autri_get_portnum_by_name(struct autri_softc *sc, char *class, char *device,
966     char *qualifier)
967 {
968 	return (sc->sc_codec.codec_if->vtbl->get_portnum_by_name(
969 	    sc->sc_codec.codec_if, class, device, qualifier));
970 }
971 
972 void *
973 autri_malloc(void *addr, int direction, size_t size, int pool, int flags)
974 {
975 	struct autri_softc *sc = addr;
976 	struct autri_dma *p;
977 	int error;
978 
979 	p = malloc(sizeof(*p), pool, flags);
980 	if (!p)
981 		return NULL;
982 
983 #if 0
984 	error = autri_allocmem(sc, size, 16, p);
985 #endif
986 	error = autri_allocmem(sc, size, 0x10000, p);
987 	if (error) {
988 		free(p, pool, sizeof(*p));
989 		return NULL;
990 	}
991 
992 	p->next = sc->sc_dmas;
993 	sc->sc_dmas = p;
994 	return KERNADDR(p);
995 }
996 
997 void
998 autri_free(void *addr, void *ptr, int pool)
999 {
1000 	struct autri_softc *sc = addr;
1001 	struct autri_dma **pp, *p;
1002 
1003 	for (pp = &sc->sc_dmas; (p = *pp) != NULL; pp = &p->next) {
1004 		if (KERNADDR(p) == ptr) {
1005 			autri_freemem(sc, p);
1006 			*pp = p->next;
1007 			free(p, pool, sizeof(*p));
1008 			return;
1009 		}
1010 	}
1011 }
1012 
1013 struct autri_dma *
1014 autri_find_dma(struct autri_softc *sc, void *addr)
1015 {
1016 	struct autri_dma *p;
1017 
1018 	for (p = sc->sc_dmas; p && KERNADDR(p) != addr; p = p->next)
1019 		;
1020 
1021 	return p;
1022 }
1023 
1024 void
1025 autri_setup_channel(struct autri_softc *sc, int mode, struct audio_params *param)
1026 {
1027 	int i, ch, channel;
1028 	u_int32_t reg, cr[5];
1029 	u_int32_t cso, eso;
1030 	u_int32_t delta, dch[2], ctrl;
1031 	u_int32_t alpha_fms, fm_vol, attribute;
1032 
1033 	u_int32_t dmaaddr, dmalen;
1034 	int factor, rvol, cvol;
1035 	struct autri_chstatus *chst;
1036 
1037 	ctrl = AUTRI_CTRL_LOOPMODE;
1038 	switch (param->encoding) {
1039 	case AUDIO_ENCODING_SLINEAR_BE:
1040 	case AUDIO_ENCODING_SLINEAR_LE:
1041 		ctrl |= AUTRI_CTRL_SIGNED;
1042 		break;
1043 	}
1044 
1045 	factor = 0;
1046 	if (param->precision == 16) {
1047 		ctrl |= AUTRI_CTRL_16BIT;
1048 		factor++;
1049 	}
1050 
1051 	if (param->channels == 2) {
1052 		ctrl |= AUTRI_CTRL_STEREO;
1053 		factor++;
1054 	}
1055 
1056 	delta = (u_int32_t)param->sample_rate;
1057 	if (delta < 4000)
1058 		delta = 4000;
1059 	if (delta > 48000)
1060 		delta = 48000;
1061 
1062 	attribute = 0;
1063 
1064 	dch[1] = ((delta << 12) / 48000) & 0x0000ffff;
1065 	if (mode == AUMODE_PLAY) {
1066 		chst = &sc->sc_play;
1067 		dch[0] = ((delta << 12) / 48000) & 0x0000ffff;
1068 		ctrl |= AUTRI_CTRL_WAVEVOL;
1069 /*
1070 		if (sc->sc_devid == AUTRI_DEVICE_ID_ALI_M5451)
1071 			ctrl |= 0x80000000;
1072 */
1073 	} else {
1074 		chst = &sc->sc_rec;
1075 		dch[0] = ((48000 << 12) / delta) & 0x0000ffff;
1076 		if (sc->sc_devid == AUTRI_DEVICE_ID_SIS_7018) {
1077 			ctrl |= AUTRI_CTRL_MUTE_SIS;
1078 			attribute = AUTRI_ATTR_PCMREC_SIS;
1079 			if (delta != 48000)
1080 				attribute |= AUTRI_ATTR_ENASRC_SIS;
1081 		}
1082 		ctrl |= AUTRI_CTRL_MUTE;
1083 	}
1084 
1085 	dmaaddr = DMAADDR(chst->dma);
1086 	cso = alpha_fms = 0;
1087 	rvol = cvol = 0x7f;
1088 	fm_vol = 0x0 | ((rvol & 0x7f) << 7) | (cvol & 0x7f);
1089 
1090 	for (ch=0; ch<2; ch++) {
1091 
1092 		if (ch == 0)
1093 			dmalen = (chst->length >> factor);
1094 		else {
1095 			/* channel for interrupt */
1096 			dmalen = (chst->blksize >> factor);
1097 			if (sc->sc_devid == AUTRI_DEVICE_ID_SIS_7018)
1098 				ctrl |= AUTRI_CTRL_MUTE_SIS;
1099 			else
1100 				ctrl |= AUTRI_CTRL_MUTE;
1101 			attribute = 0;
1102 		}
1103 
1104 		eso = dmalen - 1;
1105 
1106 		switch (sc->sc_devid) {
1107 		case AUTRI_DEVICE_ID_4DWAVE_DX:
1108 			cr[0] = (cso << 16) | (alpha_fms & 0x0000ffff);
1109 			cr[1] = dmaaddr;
1110 			cr[2] = (eso << 16) | (dch[ch] & 0x0000ffff);
1111 			cr[3] = fm_vol;
1112 			cr[4] = ctrl;
1113 			break;
1114 		case AUTRI_DEVICE_ID_4DWAVE_NX:
1115 			cr[0] = (dch[ch] << 24) | (cso & 0x00ffffff);
1116 			cr[1] = dmaaddr;
1117 			cr[2] = ((dch[ch] << 16) & 0xff000000) | (eso & 0x00ffffff);
1118 			cr[3] = (alpha_fms << 16) | (fm_vol & 0x0000ffff);
1119 			cr[4] = ctrl;
1120 			break;
1121 		case AUTRI_DEVICE_ID_SIS_7018:
1122 			cr[0] = (cso << 16) | (alpha_fms & 0x0000ffff);
1123 			cr[1] = dmaaddr;
1124 			cr[2] = (eso << 16) | (dch[ch] & 0x0000ffff);
1125 			cr[3] = attribute;
1126 			cr[4] = ctrl;
1127 			break;
1128 		case AUTRI_DEVICE_ID_ALI_M5451:
1129 			cr[0] = (cso << 16) | (alpha_fms & 0x0000ffff);
1130 			cr[1] = dmaaddr;
1131 			cr[2] = (eso << 16) | (dch[ch] & 0x0000ffff);
1132 			cr[3] = 0;
1133 			cr[4] = ctrl;
1134 			break;
1135 		}
1136 
1137 		/* write channel data */
1138 		channel = (ch == 0) ? chst->ch : chst->ch_intr;
1139 
1140 		reg = TREAD4(sc,AUTRI_LFO_GC_CIR) & ~0x0000003f;
1141 		TWRITE4(sc,AUTRI_LFO_GC_CIR, reg | channel);
1142 
1143 		for (i=0; i<5; i++) {
1144 			TWRITE4(sc, AUTRI_ARAM_CR + i*sizeof(cr[0]), cr[i]);
1145 			DPRINTFN(5,("cr[%d] : 0x%08X\n", i, cr[i]));
1146 		}
1147 
1148 		/* Bank A only */
1149 		if (channel < 0x20) {
1150 			TWRITE4(sc, AUTRI_EBUF1, AUTRI_EMOD_STILL);
1151 			TWRITE4(sc, AUTRI_EBUF2, AUTRI_EMOD_STILL);
1152 		}
1153 	}
1154 
1155 }
1156 
1157 int
1158 autri_trigger_output(void *addr, void *start, void *end, int blksize,
1159     void (*intr)(void *), void *arg, struct audio_params *param)
1160 {
1161 	struct autri_softc *sc = addr;
1162 	struct autri_dma *p;
1163 
1164 	DPRINTFN(5,("autri_trigger_output: sc=%p start=%p end=%p "
1165 	    "blksize=%d intr=%p(%p)\n", addr, start, end, blksize, intr, arg));
1166 
1167 	sc->sc_play.intr = intr;
1168 	sc->sc_play.intr_arg = arg;
1169 	sc->sc_play.offset = 0;
1170 	sc->sc_play.blksize = blksize;
1171 	sc->sc_play.length = (char *)end - (char *)start;
1172 
1173 	p = autri_find_dma(sc, start);
1174 	if (!p) {
1175 		printf("autri_trigger_output: bad addr %p\n", start);
1176 		return (EINVAL);
1177 	}
1178 
1179 	sc->sc_play.dma = p;
1180 
1181 	/* */
1182 	mtx_enter(&audio_lock);
1183 	autri_setup_channel(sc, AUMODE_PLAY, param);
1184 
1185 	/* volume set to no attenuation */
1186 	TWRITE4(sc, AUTRI_MUSICVOL_WAVEVOL, 0);
1187 
1188 	/* enable interrupt */
1189 	autri_enable_interrupt(sc, sc->sc_play.ch_intr);
1190 
1191 	/* start channel */
1192 	autri_startch(sc, sc->sc_play.ch, sc->sc_play.ch_intr);
1193 	mtx_leave(&audio_lock);
1194 	return 0;
1195 }
1196 
1197 int
1198 autri_trigger_input(void *addr, void *start, void *end, int blksize, void (*intr)(void *), void *arg, struct audio_params *param)
1199 {
1200 	struct autri_softc *sc = addr;
1201 	struct autri_dma *p;
1202 
1203 	DPRINTFN(5,("autri_trigger_input: sc=%p start=%p end=%p "
1204 	    "blksize=%d intr=%p(%p)\n", addr, start, end, blksize, intr, arg));
1205 
1206 	sc->sc_rec.intr = intr;
1207 	sc->sc_rec.intr_arg = arg;
1208 	sc->sc_rec.offset = 0;
1209 	sc->sc_rec.blksize = blksize;
1210 	sc->sc_rec.length = (char *)end - (char *)start;
1211 
1212 	/* */
1213 	p = autri_find_dma(sc, start);
1214 	if (!p) {
1215 		printf("autri_trigger_input: bad addr %p\n", start);
1216 		return (EINVAL);
1217 	}
1218 
1219 	sc->sc_rec.dma = p;
1220 	mtx_enter(&audio_lock);
1221 
1222 	/* */
1223 	if (sc->sc_devid == AUTRI_DEVICE_ID_4DWAVE_NX) {
1224 		autri_reg_set_4(sc, AUTRI_NX_ACR0, AUTRI_NX_ACR0_PSB_CAPTURE);
1225 		TWRITE1(sc, AUTRI_NX_RCI3, AUTRI_NX_RCI3_ENABLE | sc->sc_rec.ch);
1226 	}
1227 
1228 #if 0
1229 	/* 4DWAVE only allows capturing at a 48KHz rate */
1230 	if (sc->sc_devid == AUTRI_DEVICE_ID_4DWAVE_DX ||
1231 	    sc->sc_devid == AUTRI_DEVICE_ID_4DWAVE_NX)
1232 		param->sample_rate = 48000;
1233 #endif
1234 
1235 	autri_setup_channel(sc, AUMODE_RECORD, param);
1236 
1237 	/* enable interrupt */
1238 	autri_enable_interrupt(sc, sc->sc_rec.ch_intr);
1239 
1240 	/* start channel */
1241 	autri_startch(sc, sc->sc_rec.ch, sc->sc_rec.ch_intr);
1242 	mtx_leave(&audio_lock);
1243 	return 0;
1244 }
1245 
1246 #if 0
1247 int
1248 autri_halt(struct autri_softc *sc)
1249 {
1250 	DPRINTF(("autri_halt().\n"));
1251 	/*autri_stopch(sc);*/
1252 	autri_disable_interrupt(sc, sc->sc_play.channel);
1253 	autri_disable_interrupt(sc, sc->sc_rec.channel);
1254 	return 0;
1255 }
1256 #endif
1257 
1258 void
1259 autri_enable_interrupt(struct autri_softc *sc, int ch)
1260 {
1261 	int reg;
1262 
1263 	reg = (ch & 0x20) ? AUTRI_AINTEN_B : AUTRI_AINTEN_A;
1264 	ch &= 0x1f;
1265 
1266 	autri_reg_set_4(sc, reg, 1 << ch);
1267 }
1268 
1269 void
1270 autri_disable_interrupt(struct autri_softc *sc, int ch)
1271 {
1272 	int reg;
1273 
1274 	reg = (ch & 0x20) ? AUTRI_AINTEN_B : AUTRI_AINTEN_A;
1275 	ch &= 0x1f;
1276 
1277 	autri_reg_clear_4(sc, reg, 1 << ch);
1278 }
1279 
1280 void
1281 autri_startch(struct autri_softc *sc, int ch, int ch_intr)
1282 {
1283 	int reg;
1284 	u_int32_t chmask;
1285 
1286 	reg = (ch & 0x20) ? AUTRI_START_B : AUTRI_START_A;
1287 	ch &= 0x1f;
1288 	chmask = (1 << ch) | (1 << ch_intr);
1289 
1290 	autri_reg_set_4(sc, reg, chmask);
1291 }
1292 
1293 void
1294 autri_stopch(struct autri_softc *sc, int ch, int ch_intr)
1295 {
1296 	int reg;
1297 	u_int32_t chmask;
1298 
1299 	reg = (ch & 0x20) ? AUTRI_STOP_B : AUTRI_STOP_A;
1300 	ch &= 0x1f;
1301 	chmask = (1 << ch) | (1 << ch_intr);
1302 
1303 	autri_reg_set_4(sc, reg, chmask);
1304 }
1305 
1306 #if NMIDI > 0
1307 int
1308 autri_midi_open(void *addr, int flags, void (*iintr)(void *, int),
1309     void (*ointr)(void *), void *arg)
1310 {
1311 	struct autri_softc *sc = addr;
1312 
1313 	DPRINTF(("autri_midi_open()\n"));
1314 
1315 	DPRINTFN(5,("MPUR1 : 0x%02X\n",TREAD1(sc,AUTRI_MPUR1)));
1316 	DPRINTFN(5,("MPUR2 : 0x%02X\n",TREAD1(sc,AUTRI_MPUR2)));
1317 
1318 	sc->sc_iintr = iintr;
1319 	sc->sc_ointr = ointr;
1320 	sc->sc_arg = arg;
1321 
1322 	if (flags & FREAD)
1323 		autri_reg_clear_1(sc, AUTRI_MPUR2, AUTRI_MIDIIN_ENABLE_INTR);
1324 
1325 	if (flags & FWRITE)
1326 		autri_reg_set_1(sc, AUTRI_MPUR2, AUTRI_MIDIOUT_CONNECT);
1327 
1328 	return (0);
1329 }
1330 
1331 void
1332 autri_midi_close(void *addr)
1333 {
1334 	struct autri_softc *sc = addr;
1335 
1336 	DPRINTF(("autri_midi_close()\n"));
1337 
1338 	/* give uart a chance to drain */
1339 	tsleep_nsec(sc, PWAIT, "autri", MSEC_TO_NSEC(100));
1340 
1341 	sc->sc_iintr = NULL;
1342 	sc->sc_ointr = NULL;
1343 }
1344 
1345 int
1346 autri_midi_output(void *addr, int d)
1347 {
1348 	struct autri_softc *sc = addr;
1349 
1350 	if ((TREAD1(sc, AUTRI_MPUR1) & AUTRI_MIDIOUT_READY) != 0) {
1351 		TWRITE1(sc, AUTRI_MPUR0, d);
1352 		return 0;
1353 	}
1354 	return 1;
1355 }
1356 
1357 void
1358 autri_midi_getinfo(void *addr, struct midi_info *mi)
1359 {
1360 	mi->name = "4DWAVE MIDI UART";
1361 	mi->props = MIDI_PROP_CAN_INPUT;
1362 }
1363 
1364 #endif
1365