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