xref: /openbsd/sys/dev/pci/maestro.c (revision 133306f0)
1 /*	$OpenBSD: maestro.c,v 1.3 2001/01/16 12:07:19 espie Exp $	*/
2 /* $FreeBSD: /c/ncvs/src/sys/dev/sound/pci/maestro.c,v 1.3 2000/11/21 12:22:11 julian Exp $ */
3 /*
4  * FreeBSD's ESS Agogo/Maestro driver
5  * Converted from FreeBSD's pcm to OpenBSD's audio.
6  * Copyright (c) 2000, 2001 David Leonard & Marc Espie
7  * All rights reserved.
8  *
9  * Redistribution and use in source and binary forms, with or without
10  * modification, are permitted provided that the following conditions
11  * are met:
12  * 1. Redistributions of source code must retain the above copyright
13  *    notice, this list of conditions and the following disclaimer.
14  * 2. Redistributions in binary form must reproduce the above copyright
15  *    notice, this list of conditions and the following disclaimer in the
16  *    documentation and/or other materials provided with the distribution.
17  *
18  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
19  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
22  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
24  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
26  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
27  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
28  * SUCH DAMAGE.
29  */
30 /*-
31  * (FreeBSD) Credits:
32  * Copyright (c) 2000 Taku YAMAMOTO <taku@cent.saitama-u.ac.jp>
33  *
34  * Part of this code (especially in many magic numbers) was heavily inspired
35  * by the Linux driver originally written by
36  * Alan Cox <alan.cox@linux.org>, modified heavily by
37  * Zach Brown <zab@zabbo.net>.
38  *
39  * busdma()-ize and buffer size reduction were suggested by
40  * Cameron Grant <gandalf@vilnya.demon.co.uk>.
41  * Also he showed me the way to use busdma() suite.
42  *
43  * Internal speaker problems on NEC VersaPro's and Dell Inspiron 7500
44  * were looked at by
45  * Munehiro Matsuda <haro@tk.kubota.co.jp>,
46  * who brought patches based on the Linux driver with some simplification.
47  */
48 
49 #include <sys/param.h>
50 #include <sys/systm.h>
51 #include <sys/kernel.h>
52 #include <sys/malloc.h>
53 #include <sys/device.h>
54 #include <sys/proc.h>
55 #include <sys/queue.h>
56 #include <sys/fcntl.h>
57 
58 #include <dev/pci/pcidevs.h>
59 #include <dev/pci/pcivar.h>
60 
61 #include <sys/audioio.h>
62 #include <dev/audio_if.h>
63 #include <dev/mulaw.h>
64 #include <dev/auconv.h>
65 
66 #include <dev/ic/ac97.h>
67 #include <dev/pci/maestro_reg.h>
68 
69 #ifdef AUDIO_DEBUG
70 #define DPRINTF(x)	if (maestrodebug) printf x
71 #define DLPRINTF(i, x)	if (maestrodebug & i) printf x
72 int	maestrodebug = 0;
73 u_long maestrointr_called;
74 u_long maestrodma_effective;
75 
76 #define MAESTRODEBUG_INTR 1
77 #define MAESTRODEBUG_TIMER 2
78 #else
79 #define DPRINTF(x)
80 #define DLPRINTF(i, x)
81 #endif
82 
83 #define MAESTRO_BUFSIZ		0x4000
84 #define lengthof(array)		(sizeof (array) / sizeof (array)[0])
85 
86 #define STEP_VOLUME		0x22
87 #define MIDDLE_VOLUME		(STEP_VOLUME * 4)
88 
89 typedef struct salloc_pool {
90 	struct salloc_zone {
91 		SLIST_ENTRY(salloc_zone) link;
92 		caddr_t		addr;
93 		size_t		size;
94 	} *zones;
95 	SLIST_HEAD(salloc_head, salloc_zone) free, used, spare;
96 } *salloc_t;
97 
98 struct maestro_softc;
99 
100 #define MAESTRO_PLAY	1
101 #define MAESTRO_STEREO	2
102 #define MAESTRO_8BIT	4
103 #define MAESTRO_UNSIGNED	8
104 #define MAESTRO_RUNNING	16
105 
106 struct maestro_channel {
107 	struct maestro_softc 	*sc;
108 	int			num;
109 	u_int32_t		blocksize;
110 	u_int16_t		mode;
111 	u_int32_t		speed;
112 	u_int32_t		dv;
113 	u_int16_t		start;
114 	u_int16_t		threshold;
115 	u_int16_t		end;
116 	u_int16_t		current;
117 	u_int			wpwa;
118 	void			(*intr) __P((void *));
119 	void			*intr_arg;
120 };
121 
122 struct maestro_softc {
123 	struct device		dev;
124 
125 	void			*ih;
126 	pci_chipset_tag_t	pc;
127 	pcitag_t		pt;
128 
129 #define MAESTRO_FLAG_SETUPGPIO	0x0001
130 	int			flags;
131 	bus_space_tag_t		iot;
132 	bus_space_handle_t	ioh;
133 	bus_dma_tag_t		dmat;
134 
135 	caddr_t			dmabase;
136 	bus_addr_t		physaddr;
137 	size_t			dmasize;
138 	bus_dmamap_t		dmamap;
139 	bus_dma_segment_t	dmaseg;
140 	salloc_t		dmapool;
141 
142 	struct ac97_codec_if	*codec_if;
143 	struct ac97_host_if	host_if;
144 	struct audio_device	*sc_audev;
145 
146 	void			*powerhook;
147 	int			suspend;
148 
149 	struct maestro_channel	play;
150 	struct maestro_channel	record;
151 };
152 
153 
154 typedef	u_int16_t wpreg_t;
155 typedef	u_int16_t wcreg_t;
156 
157 salloc_t salloc_new __P((caddr_t, size_t, int));
158 void	salloc_destroy __P((salloc_t));
159 caddr_t	salloc_alloc __P((salloc_t, size_t));
160 void	salloc_free __P((salloc_t, caddr_t));
161 void	salloc_insert __P((salloc_t, struct salloc_head *,
162 		struct salloc_zone *, int));
163 
164 int	maestro_match __P((struct device *, void *, void *));
165 void	maestro_attach __P((struct device *, struct device *, void *));
166 int	maestro_intr __P((void *));
167 
168 int	maestro_open __P((void *, int));
169 void	maestro_close __P((void *));
170 int	maestro_query_encoding __P((void *, struct audio_encoding *));
171 int	maestro_set_params __P((void *, int, int, struct audio_params *,
172 			    struct audio_params *));
173 int	maestro_round_blocksize __P((void *, int));
174 int	maestro_halt_output __P((void *));
175 int	maestro_halt_input __P((void *));
176 int	maestro_getdev __P((void *, struct audio_device *));
177 int	maestro_set_port __P((void *, mixer_ctrl_t *));
178 int	maestro_get_port __P((void *, mixer_ctrl_t *));
179 int	maestro_query_devinfo __P((void *, mixer_devinfo_t *));
180 void	*maestro_malloc __P((void *, int, size_t, int, int));
181 void	maestro_free __P((void *, void *, int));
182 size_t	maestro_round_buffersize __P((void *, int, size_t));
183 int	maestro_mappage __P((void *, void *, int, int));
184 int	maestro_get_props __P((void *));
185 int	maestro_trigger_output __P((void *, void *, void *, int, void (*)(void *),
186 				void *, struct audio_params *));
187 int	maestro_trigger_input __P((void *, void *, void *, int, void (*)(void *),
188 			       void *, struct audio_params *));
189 
190 int	maestro_attach_codec __P((void *, struct ac97_codec_if *));
191 int	maestro_read_codec __P((void *, u_int8_t, u_int16_t *));
192 int	maestro_write_codec __P((void *, u_int8_t, u_int16_t));
193 void	maestro_reset_codec __P((void *));
194 
195 void	maestro_initcodec __P((void *));
196 
197 void	maestro_set_speed __P((struct maestro_channel *, u_long *));
198 void	maestro_init __P((struct maestro_softc *));
199 void	maestro_power __P((struct maestro_softc *, int));
200 void	maestro_powerhook __P((int, void *));
201 
202 void 	maestro_channel_start __P((struct maestro_channel *));
203 void 	maestro_channel_stop __P((struct maestro_channel *));
204 void 	maestro_channel_advance_dma __P((struct maestro_channel *));
205 
206 int	maestro_get_flags __P((struct pci_attach_args *));
207 
208 void	ringbus_setdest __P((struct maestro_softc *, int, int));
209 
210 wpreg_t	wp_reg_read __P((struct maestro_softc *, int));
211 void	wp_reg_write __P((struct maestro_softc *, int, wpreg_t));
212 wpreg_t	wp_apu_read __P((struct maestro_softc *, int, int));
213 void	wp_apu_write __P((struct maestro_softc *, int, int, wpreg_t));
214 void	wp_settimer __P((struct maestro_softc *, u_int));
215 void	wp_starttimer __P((struct maestro_softc *));
216 void	wp_stoptimer __P((struct maestro_softc *));
217 
218 wcreg_t	wc_reg_read __P((struct maestro_softc *, int));
219 void	wc_reg_write __P((struct maestro_softc *, int, wcreg_t));
220 wcreg_t	wc_ctrl_read __P((struct maestro_softc *, int));
221 void	wc_ctrl_write __P((struct maestro_softc *, int, wcreg_t));
222 
223 u_int maestro_calc_timer_freq __P((struct maestro_channel *));
224 void maestro_update_timer __P((struct maestro_softc *));
225 
226 struct cfdriver maestro_cd = {
227 	NULL, "maestro", DV_DULL
228 };
229 
230 struct cfattach maestro_ca = {
231 	sizeof (struct maestro_softc), maestro_match, maestro_attach
232 };
233 
234 struct audio_hw_if maestro_hw_if = {
235 	maestro_open,
236 	maestro_close,
237 	NULL,
238 	maestro_query_encoding,
239 	maestro_set_params,
240 	maestro_round_blocksize,
241 	NULL,
242 	NULL,
243 	NULL,
244 	NULL,
245 	NULL,
246 	maestro_halt_output,
247 	maestro_halt_input,
248 	NULL,
249 	maestro_getdev,
250 	NULL,
251 	maestro_set_port,
252 	maestro_get_port,
253 	maestro_query_devinfo,
254 	NULL,
255 	maestro_free,
256 	NULL,
257 	maestro_mappage,
258 	maestro_get_props,
259 	maestro_trigger_output,
260 	maestro_trigger_input,
261 	maestro_malloc,
262 	maestro_round_buffersize
263 };
264 
265 struct audio_device maestro_audev = {
266 	"ESS Maestro", "", "maestro"
267 };
268 
269 struct {
270 	int vendor, product;
271 	char *name;
272 	int flags;
273 } maestro_pcitab[] = {
274 	{ PCI_VENDOR_ESSTECH, PCI_PRODUCT_ESSTECH_MAESTROII,
275 	  "ESS Technology Maestro-2", 0 },
276 	{ PCI_VENDOR_ESSTECH, PCI_PRODUCT_ESSTECH_MAESTRO2E,
277 	  "ESS Technology Maestro-2E", 0 },
278 	{ 0x1285, 0x0100, "ESS Technology Maestro-1", 0 },
279 	{ PCI_VENDOR_NEC, 0x8058, "NEC Versa(?)", MAESTRO_FLAG_SETUPGPIO },
280 	{ PCI_VENDOR_NEC, 0x803c, "NEC VersaProNX VA26D", MAESTRO_FLAG_SETUPGPIO }
281 };
282 #define NMAESTRO_PCITAB	lengthof(maestro_pcitab)
283 
284 int
285 maestro_get_flags(pa)
286 	struct pci_attach_args *pa;
287 {
288 	int i;
289 
290 	/* Distinguish audio devices from modems with the same manfid */
291 	if (PCI_CLASS(pa->pa_class) != PCI_CLASS_MULTIMEDIA)
292 		return (-1);
293 	if (PCI_SUBCLASS(pa->pa_class) != PCI_SUBCLASS_MULTIMEDIA_AUDIO)
294 		return (-1);
295 	for (i = 0; i < NMAESTRO_PCITAB; i++)
296 		if (PCI_VENDOR(pa->pa_id) == maestro_pcitab[i].vendor &&
297 		    PCI_PRODUCT(pa->pa_id) == maestro_pcitab[i].product)
298 			return (maestro_pcitab[i].flags);
299 	return (-1);
300 }
301 
302 /* -----------------------------
303  * Driver interface.
304  */
305 
306 int
307 maestro_match(parent, match, aux)
308 	struct device *parent;
309 	void *match;
310 	void *aux;
311 {
312 	struct pci_attach_args *pa = (struct pci_attach_args *)aux;
313 
314 /* This is grossly inelegant, but we can't store results at match time. */
315 	if (maestro_get_flags(pa) == -1)
316 		return (0);
317 	else
318 		return (1);
319 }
320 
321 void
322 maestro_attach(parent, self, aux)
323 	struct device *parent;
324 	struct device *self;
325 	void *aux;
326 {
327 	struct maestro_softc *sc = (struct maestro_softc *)self;
328 	struct pci_attach_args *pa = (struct pci_attach_args *)aux;
329 	pci_chipset_tag_t pc = pa->pa_pc;
330 	char const *intrstr;
331 	pci_intr_handle_t ih;
332 	int error;
333 	pcireg_t data;
334 	u_int16_t cdata;
335 	int dmastage = 0;
336 	int rseg;
337 
338 	printf("\n");
339 	sc->sc_audev = &maestro_audev;
340 	sc->flags = maestro_get_flags(pa);
341 
342 	sc->pc = pa->pa_pc;
343 	sc->pt = pa->pa_tag;
344 	sc->dmat = pa->pa_dmat;
345 
346 	/* Map interrupt */
347 	if (pci_intr_map(pc, pa->pa_intrtag, pa->pa_intrpin, pa->pa_intrline,
348 	    &ih)) {
349 		printf("%s: couldn't map interrupt\n", sc->dev.dv_xname);
350 		return;
351 	}
352 	intrstr = pci_intr_string(pc, ih);
353 	sc->ih = pci_intr_establish(pc, ih, IPL_AUDIO, maestro_intr, sc,
354 	    sc->dev.dv_xname);
355 	if (sc->ih == NULL) {
356 		printf("%s: couldn't establish interrupt", sc->dev.dv_xname);
357 		if (intrstr != NULL)
358 			printf(" at %s\n", intrstr);
359 		return;
360 	}
361 	printf("%s: interrupting at %s, ", sc->dev.dv_xname, intrstr);
362 
363 	/* Rangers, power up */
364 	maestro_power(sc, PPMI_D0);
365 	DELAY(100000);
366 
367 	/* Map i/o */
368 	if ((error = pci_mapreg_map(pa, PCI_MAPS, PCI_MAPREG_TYPE_IO,
369 	    0, &sc->iot, &sc->ioh, NULL, NULL)) != 0) {
370 		printf("couldn't map i/o space\n");
371 		goto bad;
372 	};
373 
374 	/* Enable bus mastering */
375 	data = pci_conf_read(sc->pc, sc->pt, PCI_COMMAND_STATUS_REG);
376 	if ((data & PCI_COMMAND_MASTER_ENABLE) == 0)
377 		pci_conf_write(sc->pc, sc->pt, PCI_COMMAND_STATUS_REG,
378 			data | PCI_COMMAND_MASTER_ENABLE);
379 
380 	/* Allocate fixed DMA segment :-( */
381 	sc->dmasize = MAESTRO_BUFSIZ * 16;
382 	if ((error = bus_dmamem_alloc(sc->dmat, sc->dmasize, NBPG, 0,
383 	    &sc->dmaseg, 1, &rseg, BUS_DMA_NOWAIT)) != 0) {
384 		printf("%s: unable to alloc dma, error %d\n",
385 		    sc->dev.dv_xname, error);
386 		goto bad;
387 	}
388 	dmastage = 1;
389 	if ((error = bus_dmamem_map(sc->dmat, &sc->dmaseg, 1,
390 	    sc->dmasize, &sc->dmabase, BUS_DMA_NOWAIT |
391 	    BUS_DMA_COHERENT)) != 0) {
392 		printf("%s: unable to map dma, error %d\n",
393 		    sc->dev.dv_xname, error);
394 		goto bad;
395 	}
396 	dmastage = 2;
397 	if ((error = bus_dmamap_create(sc->dmat, sc->dmasize, 1,
398 	    sc->dmasize, 0, BUS_DMA_NOWAIT, &sc->dmamap)) != 0) {
399 		printf("%s: unable to create dma map, error %d\n",
400 		    sc->dev.dv_xname, error);
401 		goto bad;
402 	}
403 	dmastage = 3;
404 	if ((error = bus_dmamap_load(sc->dmat, sc->dmamap,
405 	    sc->dmabase, sc->dmasize, NULL, BUS_DMA_NOWAIT)) != 0) {
406 		printf("%s: unable to load dma map, error %d\n",
407 		    sc->dev.dv_xname, error);
408 		goto bad;
409 	}
410 
411 	/* XXX
412 	 * The first byte of the allocated memory is not usable,
413 	 * the WP sometimes uses it to store status.
414 	 */
415 	/* Make DMA memory pool */
416 	if ((sc->dmapool = salloc_new(sc->dmabase+16, sc->dmasize-16,
417 	    128/*overkill?*/)) == NULL) {
418 		printf("%s: unable to make dma pool\n", sc->dev.dv_xname);
419 		goto bad;
420 	}
421 
422 	sc->physaddr = sc->dmamap->dm_segs[0].ds_addr;
423 
424 	/* Kick device */
425 	maestro_init(sc);
426 	maestro_read_codec(sc, 0, &cdata);
427 	if (cdata == 0x80) {
428 		printf("%s: PT101 codec unsupported, no mixer\n",
429 		    sc->dev.dv_xname);
430 		/* Init values from Linux, no idea what this does. */
431 		maestro_write_codec(sc, 0x2a, 0x0001);
432 		maestro_write_codec(sc, 0x2C, 0x0000);
433 		maestro_write_codec(sc, 0x2C, 0xFFFF);
434 		maestro_write_codec(sc, 0x10, 0x9F1F);
435 		maestro_write_codec(sc, 0x12, 0x0808);
436 		maestro_write_codec(sc, 0x14, 0x9F1F);
437 		maestro_write_codec(sc, 0x16, 0x9F1F);
438 		maestro_write_codec(sc, 0x18, 0x0404);
439 		maestro_write_codec(sc, 0x1A, 0x0000);
440 		maestro_write_codec(sc, 0x1C, 0x0000);
441 		maestro_write_codec(sc, 0x02, 0x0404);
442 		maestro_write_codec(sc, 0x04, 0x0808);
443 		maestro_write_codec(sc, 0x0C, 0x801F);
444 		maestro_write_codec(sc, 0x0E, 0x801F);
445 		/* no control over the mixer, sorry */
446 		sc->codec_if = NULL;
447 	} else {
448 		/* Attach the AC'97 */
449 		sc->host_if.arg = sc;
450 		sc->host_if.attach = maestro_attach_codec;
451 		sc->host_if.read = maestro_read_codec;
452 		sc->host_if.write = maestro_write_codec;
453 		sc->host_if.reset = maestro_reset_codec;
454 		if (ac97_attach(&sc->host_if) != 0) {
455 			printf("%s: couldn't attach codec\n", sc->dev.dv_xname);
456 			goto bad;
457 		}
458 	}
459 
460 	sc->play.mode = MAESTRO_PLAY;
461 	sc->play.sc = sc;
462 	sc->play.num = 0;
463 	sc->record.sc = sc;
464 	sc->record.num = 2;
465 	sc->record.mode = 0;
466 
467 	/* Attach audio */
468 	audio_attach_mi(&maestro_hw_if, sc, &sc->dev);
469 
470 	/* Hook power changes */
471 	sc->suspend = PWR_RESUME;
472 	sc->powerhook = powerhook_establish(maestro_powerhook, sc);
473 
474 	return;
475 
476  bad:
477 	/* Power down. */
478 	maestro_power(sc, PPMI_D3);
479 	if (sc->ih)
480 		pci_intr_disestablish(pc, sc->ih);
481 	printf("%s: disabled\n", sc->dev.dv_xname);
482 	if (sc->dmapool)
483 		salloc_destroy(sc->dmapool);
484 	if (dmastage >= 3)
485 		bus_dmamap_destroy(sc->dmat, sc->dmamap);
486 	if (dmastage >= 2)
487 		bus_dmamem_unmap(sc->dmat, sc->dmabase, sc->dmasize);
488 	if (dmastage >= 1)
489 		bus_dmamem_free(sc->dmat, &sc->dmaseg, 1);
490 }
491 
492 void
493 maestro_init(sc)
494 	struct maestro_softc *sc;
495 {
496 	int reg;
497 	pcireg_t data;
498 
499 	/* Disable all legacy emulations. */
500 	data = pci_conf_read(sc->pc, sc->pt, CONF_LEGACY);
501 	data |= LEGACY_DISABLED;
502 	pci_conf_write(sc->pc, sc->pt, CONF_LEGACY, data);
503 
504 	/* Disconnect from CHI. (Makes Dell inspiron 7500 work?)
505 	 * Enable posted write.
506 	 * Prefer PCI timing rather than that of ISA.
507 	 * Don't swap L/R. */
508 	data = pci_conf_read(sc->pc, sc->pt, CONF_MAESTRO);
509 	data |= MAESTRO_CHIBUS | MAESTRO_POSTEDWRITE | MAESTRO_DMA_PCITIMING;
510 	data &= ~MAESTRO_SWAP_LR;
511 	pci_conf_write(sc->pc, sc->pt, CONF_MAESTRO, data);
512 	/* Reset direct sound. */
513 	bus_space_write_2(sc->iot, sc->ioh, PORT_HOSTINT_CTRL,
514 	    HOSTINT_CTRL_DSOUND_RESET);
515 	DELAY(10000);	/* XXX - too long? */
516 	bus_space_write_2(sc->iot, sc->ioh, PORT_HOSTINT_CTRL, 0);
517 	DELAY(10000);
518 
519 	/* Enable direct sound and hardware volume control interruptions. */
520 	bus_space_write_2(sc->iot, sc->ioh, PORT_HOSTINT_CTRL,
521 	    HOSTINT_CTRL_DSOUND_INT_ENABLED | HOSTINT_CTRL_HWVOL_ENABLED);
522 
523 	/* Setup Wave Processor. */
524 
525 	/* Enable WaveCache, set DMA base address. */
526 	wp_reg_write(sc, WPREG_WAVE_ROMRAM,
527 	    WP_WAVE_VIRTUAL_ENABLED | WP_WAVE_DRAM_ENABLED);
528 	bus_space_write_2(sc->iot, sc->ioh, PORT_WAVCACHE_CTRL,
529 	    WAVCACHE_ENABLED | WAVCACHE_WTSIZE_4MB);
530 
531 	for (reg = WAVCACHE_PCMBAR; reg < WAVCACHE_PCMBAR + 4; reg++)
532 		wc_reg_write(sc, reg,
533 			sc->physaddr >> WAVCACHE_BASEADDR_SHIFT);
534 
535 	/* Setup Codec/Ringbus. */
536 	maestro_initcodec(sc);
537 	bus_space_write_4(sc->iot, sc->ioh, PORT_RINGBUS_CTRL,
538 	    RINGBUS_CTRL_RINGBUS_ENABLED | RINGBUS_CTRL_ACLINK_ENABLED);
539 
540 	wp_reg_write(sc, WPREG_BASE, 0x8500);	/* Parallel I/O */
541 	ringbus_setdest(sc, RINGBUS_SRC_ADC,
542 	    RINGBUS_DEST_STEREO | RINGBUS_DEST_DSOUND_IN);
543 	ringbus_setdest(sc, RINGBUS_SRC_DSOUND,
544 	    RINGBUS_DEST_STEREO | RINGBUS_DEST_DAC);
545 
546 	/* Setup ASSP. Needed for Dell Inspiron 7500? */
547 	bus_space_write_1(sc->iot, sc->ioh, PORT_ASSP_CTRL_B, 0x00);
548 	bus_space_write_1(sc->iot, sc->ioh, PORT_ASSP_CTRL_A, 0x03);
549 	bus_space_write_1(sc->iot, sc->ioh, PORT_ASSP_CTRL_C, 0x00);
550 
551 	/*
552 	 * Reset hw volume to a known value so that we may handle diffs
553 	 * off to AC'97.
554 	 */
555 
556 	bus_space_write_1(sc->iot, sc->ioh, PORT_HWVOL_MASTER, MIDDLE_VOLUME);
557 	/* Setup GPIO if needed (NEC systems) */
558 	if (sc->flags & MAESTRO_FLAG_SETUPGPIO) {
559 		/* Matthew Braithwaite <matt@braithwaite.net> reported that
560 		 * NEC Versa LX doesn't need GPIO operation. */
561 		bus_space_write_2(sc->iot, sc->ioh,
562 		    PORT_GPIO_MASK, 0x9ff);
563 		bus_space_write_2(sc->iot, sc->ioh, PORT_GPIO_DIR,
564 		    bus_space_read_2(sc->iot, sc->ioh, PORT_GPIO_DIR) | 0x600);
565 		bus_space_write_2(sc->iot, sc->ioh,
566 		    PORT_GPIO_DATA, 0x200);
567 	}
568 }
569 
570 /* -----------------------------
571  * Audio interface
572  */
573 
574 int
575 maestro_round_blocksize(self, blk)
576 	void *self;
577 	int blk;
578 {
579 	return (blk & ~0xf);
580 }
581 
582 size_t
583 maestro_round_buffersize(self, direction, size)
584 	void *self;
585 	int direction;
586 	size_t size;
587 {
588 	return (size);
589 }
590 
591 void *
592 maestro_malloc(arg, dir, size, pool, flags)
593 	void *arg;
594 	int dir;
595 	size_t size;
596 	int pool, flags;
597 {
598 	struct maestro_softc *sc = (struct maestro_softc *)arg;
599 
600 	return (salloc_alloc(sc->dmapool, size));
601 }
602 
603 void
604 maestro_free(self, ptr, pool)
605 	void *self, *ptr;
606 	int pool;
607 {
608 	struct maestro_softc *sc = (struct maestro_softc *)self;
609 
610 	salloc_free(sc->dmapool, ptr);
611 }
612 
613 int
614 maestro_mappage(self, mem, off, prot)
615 	void *self, *mem;
616 	int off, prot;
617 {
618 	struct maestro_softc *sc = (struct maestro_softc *)self;
619 
620 	if (off < 0)
621 		return -1;
622 	return bus_dmamem_mmap(sc->dmat, &sc->dmaseg, 1,
623 	    (caddr_t)mem - sc->dmabase + off, prot, BUS_DMA_WAITOK);
624 }
625 
626 int
627 maestro_get_props(self)
628 	void *self;
629 {
630 	/* struct maestro_softc *sc = (struct maestro_softc *)self; */
631 
632 	return (AUDIO_PROP_MMAP | AUDIO_PROP_INDEPENDENT); /* XXX */
633 }
634 
635 int
636 maestro_getdev(self, retp)
637 	void *self;
638 	struct audio_device *retp;
639 {
640 	struct maestro_softc *sc = (struct maestro_softc *)self;
641 
642 	*retp = *sc->sc_audev;
643 	return 0;
644 }
645 
646 int
647 maestro_set_port(self, cp)
648 	void *self;
649 	mixer_ctrl_t *cp;
650 {
651 	struct ac97_codec_if *c = ((struct maestro_softc *)self)->codec_if;
652 
653 	if (c)
654 		return (c->vtbl->mixer_set_port(c, cp));
655 	else
656 		return (ENXIO);
657 }
658 
659 int
660 maestro_get_port(self, cp)
661 	void *self;
662 	mixer_ctrl_t *cp;
663 {
664 	struct ac97_codec_if *c = ((struct maestro_softc *)self)->codec_if;
665 
666 	if (c)
667 		return (c->vtbl->mixer_get_port(c, cp));
668 	else
669 		return (ENXIO);
670 }
671 
672 int
673 maestro_query_devinfo(self, cp)
674 	void *self;
675 	mixer_devinfo_t *cp;
676 {
677 	struct ac97_codec_if *c = ((struct maestro_softc *)self)->codec_if;
678 
679 	if (c)
680 		return (c->vtbl->query_devinfo(c, cp));
681 	else
682 		return (ENXIO);
683 }
684 
685 struct audio_encoding maestro_tab[] = {
686 	{0, AudioEslinear_le, AUDIO_ENCODING_SLINEAR_LE, 16, 0},
687 	{1, AudioEslinear, AUDIO_ENCODING_SLINEAR, 8, 0},
688 	{2, AudioEulinear, AUDIO_ENCODING_ULINEAR, 8, 0},
689 	{3, AudioEslinear_be, AUDIO_ENCODING_SLINEAR_BE, 16,
690 	    AUDIO_ENCODINGFLAG_EMULATED},
691 	{4, AudioEulinear_le, AUDIO_ENCODING_ULINEAR_LE, 16,
692 	    AUDIO_ENCODINGFLAG_EMULATED},
693 	{5, AudioEulinear_be, AUDIO_ENCODING_ULINEAR_BE, 16,
694 	    AUDIO_ENCODINGFLAG_EMULATED},
695 	{6, AudioEmulaw, AUDIO_ENCODING_ULAW, 8,
696 	    AUDIO_ENCODINGFLAG_EMULATED},
697 	{7, AudioEalaw, AUDIO_ENCODING_ALAW, 8,
698 	    AUDIO_ENCODINGFLAG_EMULATED}
699 };
700 
701 int
702 maestro_query_encoding(hdl, fp)
703 	void *hdl;
704 	struct audio_encoding *fp;
705 {
706 	if (fp->index < 0 || fp->index >= lengthof(maestro_tab))
707 		return (EINVAL);
708 	*fp = maestro_tab[fp->index];
709 	return (0);
710 }
711 
712 #define UNUSED __attribute__((unused))
713 
714 void
715 maestro_set_speed(ch, prate)
716 	struct maestro_channel *ch;
717 	u_long *prate;
718 {
719 	ch->speed = *prate;
720 	if ((ch->mode & (MAESTRO_8BIT | MAESTRO_STEREO)) == MAESTRO_8BIT)
721 		ch->speed /= 2;
722 
723 	/* special common case */
724 	if (ch->speed == 48000) {
725 		ch->dv = 0x10000;
726 	} else {
727 		/* compute 16 bits fixed point value of speed/48000,
728 		 * being careful not to overflow */
729 		 ch->dv = (((ch->speed % 48000) << 16U) + 24000) / 48000
730 		    + ((ch->speed / 48000) << 16U);
731 		/* And this is the real rate obtained */
732 		ch->speed = (ch->dv >> 16U) * 48000 +
733 		    (((ch->dv & 0xffff)*48000)>>16U);
734 	}
735 	*prate = ch->speed;
736 	if ((ch->mode & (MAESTRO_8BIT | MAESTRO_STEREO)) == MAESTRO_8BIT)
737 		*prate *= 2;
738 }
739 
740 u_int
741 maestro_calc_timer_freq(ch)
742 	struct maestro_channel *ch;
743 {
744 	u_int	ss = 2;
745 
746 	if (ch->mode & MAESTRO_8BIT)
747 		ss = 1;
748 	return (ch->speed * ss) / ch->blocksize;
749 }
750 
751 void
752 maestro_update_timer(sc)
753 	struct maestro_softc *sc;
754 {
755 	u_int freq = 0;
756 	u_int n;
757 
758 	if (sc->play.mode & MAESTRO_RUNNING)
759 		freq = maestro_calc_timer_freq(&sc->play);
760 	if (sc->record.mode & MAESTRO_RUNNING) {
761 		n = maestro_calc_timer_freq(&sc->record);
762 		if (freq < n)
763 			freq = n;
764 	}
765 	if (freq) {
766 		wp_settimer(sc, freq);
767 		wp_starttimer(sc);
768     	} else
769 		wp_stoptimer(sc);
770 }
771 
772 
773 int
774 maestro_set_params(hdl, setmode, usemode, play, rec)
775 	void *hdl;
776 	int setmode, usemode;
777 	struct audio_params *play, *rec;
778 {
779 	struct maestro_softc *sc = (struct maestro_softc *)hdl;
780 
781 	if ((setmode & AUMODE_PLAY) == 0)
782 		return (0);
783 
784 	/* Disallow parameter change on a running audio for now */
785 	if (sc->play.mode & MAESTRO_RUNNING)
786 		return (EINVAL);
787 
788 	if (play->sample_rate < 4000)
789 		play->sample_rate = 4000;
790 	else if (play->sample_rate > 48000)
791 		play->sample_rate = 48000;
792 
793 	play->factor = 1;
794 	play->sw_code = NULL;
795 	if (play->channels != 1 && play->channels != 2)
796 		return (EINVAL);
797 
798 
799 	sc->play.mode = MAESTRO_PLAY;
800 	if (play->channels == 2)
801 		sc->play.mode |= MAESTRO_STEREO;
802 
803 	if (play->encoding == AUDIO_ENCODING_ULAW) {
804 		play->factor = 2;
805 		play->sw_code = mulaw_to_slinear16_le;
806 	} else if (play->encoding == AUDIO_ENCODING_ALAW) {
807 		play->factor = 2;
808 		play->sw_code = alaw_to_slinear16_le;
809 	} else if (play->precision == 8) {
810 		sc->play.mode |= MAESTRO_8BIT;
811 		if (play->encoding == AUDIO_ENCODING_ULINEAR_LE ||
812 		    play->encoding == AUDIO_ENCODING_ULINEAR_BE)
813 		    sc->play.mode |= MAESTRO_UNSIGNED;
814 	}
815 	else if (play->encoding == AUDIO_ENCODING_ULINEAR_LE)
816 		play->sw_code = change_sign16_le;
817 	else if (play->encoding == AUDIO_ENCODING_SLINEAR_BE)
818 		play->sw_code = swap_bytes;
819 	else if (play->encoding == AUDIO_ENCODING_ULINEAR_BE)
820 		play->sw_code = change_sign16_swap_bytes_le;
821 	else if (play->encoding != AUDIO_ENCODING_SLINEAR_LE)
822 		return (EINVAL);
823 
824 	maestro_set_speed(&sc->play, &play->sample_rate);
825 	return (0);
826 }
827 
828 int
829 maestro_open(hdl, flags)
830 	void *hdl;
831 	int flags;
832 {
833 	struct maestro_softc *sc = (struct maestro_softc *)hdl;
834 	DPRINTF(("%s: open(%d)\n", sc->dev.dv_xname, flags));
835 
836 	if ((OFLAGS(flags) & O_ACCMODE) != O_WRONLY)
837 		return (EINVAL);
838 	sc->play.mode = MAESTRO_PLAY;
839 	sc->record.mode = 0;
840 #ifdef AUDIO_DEBUG
841 	maestrointr_called = 0;
842 	maestrodma_effective = 0;
843 #endif
844 	return (0);
845 }
846 
847 void
848 maestro_close(hdl)
849 	void *hdl;
850 {
851 	struct maestro_softc *sc UNUSED = (struct maestro_softc *)hdl;
852 	/* nothing to do */
853 }
854 
855 
856 void
857 maestro_channel_stop(ch)
858 	struct maestro_channel *ch;
859 {
860 	wp_apu_write(ch->sc, ch->num, APUREG_APUTYPE,
861 	    APUTYPE_INACTIVE << APU_APUTYPE_SHIFT);
862 	if (ch->mode & MAESTRO_STEREO)
863 	    wp_apu_write(ch->sc, ch->num+1, APUREG_APUTYPE,
864 		APUTYPE_INACTIVE << APU_APUTYPE_SHIFT);
865 	/* four channels for record... */
866 	if (ch->mode & MAESTRO_PLAY)
867 		return;
868 	wp_apu_write(ch->sc, ch->num+2, APUREG_APUTYPE,
869 	    APUTYPE_INACTIVE << APU_APUTYPE_SHIFT);
870 	if (ch->mode & MAESTRO_STEREO)
871 	    wp_apu_write(ch->sc, ch->num+3, APUREG_APUTYPE,
872 		APUTYPE_INACTIVE << APU_APUTYPE_SHIFT);
873 
874 }
875 
876 int
877 maestro_halt_input(hdl)
878 	void *hdl;
879 {
880 	struct maestro_softc *sc = (struct maestro_softc *)hdl;
881 	maestro_channel_stop(&sc->record);
882 	sc->record.mode &= ~MAESTRO_RUNNING;
883 	maestro_update_timer(sc);
884 	return 0;
885 }
886 
887 int
888 maestro_halt_output(hdl)
889 	void *hdl;
890 {
891 	struct maestro_softc *sc = (struct maestro_softc *)hdl;
892 
893 	maestro_channel_stop(&sc->play);
894 	sc->play.mode &= ~MAESTRO_RUNNING;
895 	maestro_update_timer(sc);
896 	return 0;
897 }
898 
899 int
900 maestro_trigger_input(hdl, start, end, blksize, intr, arg, param)
901 	void *hdl;
902 	void *start, *end;
903 	int blksize;
904 	void (*intr) __P((void *));
905 	void *arg;
906 	struct audio_params *param;
907 {
908 	struct maestro_softc *sc = (struct maestro_softc *)hdl;
909 
910 	sc->record.mode |= MAESTRO_RUNNING;
911 
912 	maestro_channel_start(&sc->record);
913 
914 	sc->record.threshold = sc->record.start;
915 	maestro_update_timer(sc);
916 	return 0;
917 }
918 
919 void
920 maestro_channel_start(ch)
921 	struct maestro_channel *ch;
922 {
923 	struct maestro_softc *sc = ch->sc;
924 	int n = ch->num;
925 	int aputype;
926 	wcreg_t wcreg = (sc->physaddr - 16) & WAVCACHE_CHCTL_ADDRTAG_MASK;
927 
928 	switch(ch->mode & (MAESTRO_STEREO | MAESTRO_8BIT)) {
929 	case 0:
930 		aputype = APUTYPE_16BITLINEAR;
931 		break;
932 	case MAESTRO_STEREO:
933 		aputype = APUTYPE_16BITSTEREO;
934 		break;
935 	case MAESTRO_8BIT:
936 		aputype = APUTYPE_8BITLINEAR;
937 		break;
938 	case MAESTRO_8BIT|MAESTRO_STEREO:
939 		aputype = APUTYPE_8BITSTEREO;
940 		break;
941 	}
942 	if (ch->mode & MAESTRO_UNSIGNED)
943 		wcreg |= WAVCACHE_CHCTL_U8;
944 	if ((ch->mode & MAESTRO_STEREO) == 0) {
945 		DPRINTF(("Setting mono parameters\n"));
946 		wp_apu_write(sc, n, APUREG_WAVESPACE, ch->wpwa & 0xff00);
947 		wp_apu_write(sc, n, APUREG_CURPTR, ch->current);
948 		wp_apu_write(sc, n, APUREG_ENDPTR, ch->end);
949 		wp_apu_write(sc, n, APUREG_LOOPLEN, ch->end - ch->start);
950 		wp_apu_write(sc, n, APUREG_AMPLITUDE, 0xe800);
951 		wp_apu_write(sc, n, APUREG_POSITION, 0x8f00
952 		    | (RADIUS_CENTERCIRCLE << APU_RADIUS_SHIFT)
953 		    | (PAN_FRONT << APU_PAN_SHIFT));
954 		wp_apu_write(sc, n, APUREG_FREQ_LOBYTE, APU_plus6dB
955 		    | ((ch->dv & 0xff) << APU_FREQ_LOBYTE_SHIFT));
956 		wp_apu_write(sc, n, APUREG_FREQ_HIWORD, ch->dv >> 8);
957 		wc_ctrl_write(sc, n, wcreg);
958 		wp_apu_write(sc, n, APUREG_APUTYPE,
959 		    (aputype << APU_APUTYPE_SHIFT) | APU_DMA_ENABLED | 0xf);
960 	} else {
961 		wcreg |= WAVCACHE_CHCTL_STEREO;
962 		DPRINTF(("Setting stereo parameters\n"));
963 		wp_apu_write(sc, n+1, APUREG_WAVESPACE, ch->wpwa & 0xff00);
964 		wp_apu_write(sc, n+1, APUREG_CURPTR, ch->current);
965 		wp_apu_write(sc, n+1, APUREG_ENDPTR, ch->end);
966 		wp_apu_write(sc, n+1, APUREG_LOOPLEN, ch->end - ch->start);
967 		wp_apu_write(sc, n+1, APUREG_AMPLITUDE, 0xe800);
968 		wp_apu_write(sc, n+1, APUREG_POSITION, 0x8f00
969 		    | (RADIUS_CENTERCIRCLE << APU_RADIUS_SHIFT)
970 		    | (PAN_LEFT << APU_PAN_SHIFT));
971 		wp_apu_write(sc, n+1, APUREG_FREQ_LOBYTE, APU_plus6dB
972 		    | ((ch->dv & 0xff) << APU_FREQ_LOBYTE_SHIFT));
973 		wp_apu_write(sc, n+1, APUREG_FREQ_HIWORD, ch->dv >> 8);
974 		if (ch->mode & MAESTRO_8BIT)
975 			wp_apu_write(sc, n, APUREG_WAVESPACE,
976 			    ch->wpwa & 0xff00);
977 		    else
978 			wp_apu_write(sc, n, APUREG_WAVESPACE,
979 			    (ch->wpwa|(APU_STEREO >> 1)) & 0xff00);
980 		wp_apu_write(sc, n, APUREG_CURPTR, ch->current);
981 		wp_apu_write(sc, n, APUREG_ENDPTR, ch->end);
982 		wp_apu_write(sc, n, APUREG_LOOPLEN, ch->end - ch->start);
983 		wp_apu_write(sc, n, APUREG_AMPLITUDE, 0xe800);
984 		wp_apu_write(sc, n, APUREG_POSITION, 0x8f00
985 		    | (RADIUS_CENTERCIRCLE << APU_RADIUS_SHIFT)
986 		    | (PAN_RIGHT << APU_PAN_SHIFT));
987 		wp_apu_write(sc, n, APUREG_FREQ_LOBYTE, APU_plus6dB
988 		    | ((ch->dv & 0xff) << APU_FREQ_LOBYTE_SHIFT));
989 		wp_apu_write(sc, n, APUREG_FREQ_HIWORD, ch->dv >> 8);
990 		wc_ctrl_write(sc, n, wcreg);
991 		wc_ctrl_write(sc, n+1, wcreg);
992 		wp_apu_write(sc, n, APUREG_APUTYPE,
993 		    (aputype << APU_APUTYPE_SHIFT) | APU_DMA_ENABLED | 0xf);
994 		wp_apu_write(sc, n+1, APUREG_APUTYPE,
995 		    (aputype << APU_APUTYPE_SHIFT) | APU_DMA_ENABLED | 0xf);
996 	}
997 }
998 
999 int
1000 maestro_trigger_output(hdl, start, end, blksize, intr, arg, param)
1001 	void *hdl;
1002 	void *start, *end;
1003 	int blksize;
1004 	void (*intr) __P((void *));
1005 	void *arg;
1006 	struct audio_params *param;
1007 {
1008 	struct maestro_softc *sc = (struct maestro_softc *)hdl;
1009 
1010 	u_int offset = ((caddr_t)start - sc->dmabase) >> 1;
1011 	u_int size = (end - start) >> 1;
1012 	sc->play.mode |= MAESTRO_RUNNING;
1013 	sc->play.wpwa = APU_USE_SYSMEM | (offset >> 8);
1014 	DPRINTF(("maestro_trigger_output: start=%x, end=%x, blksize=%x ",
1015 		start, end, blksize));
1016     	DPRINTF(("offset = %x, size=%x\n", offset, size));
1017 
1018 	sc->play.intr = intr;
1019 	sc->play.intr_arg = arg;
1020 	sc->play.blocksize = blksize;
1021 	sc->play.end = offset+size;
1022 	sc->play.start = offset;
1023 	sc->play.current = sc->play.start;
1024 	if ((sc->play.mode & (MAESTRO_STEREO | MAESTRO_8BIT)) == MAESTRO_STEREO) {
1025 		sc->play.wpwa >>= 1;
1026 		sc->play.start >>= 1;
1027 		sc->play.end >>= 1;
1028 		sc->play.blocksize >>= 1;
1029 	}
1030 	maestro_channel_start(&sc->play);
1031 
1032 	sc->play.threshold = sc->play.start;
1033 	maestro_update_timer(sc);
1034 
1035 	return 0;
1036 }
1037 
1038 /* -----------------------------
1039  * Codec interface
1040  */
1041 
1042 int
1043 maestro_read_codec(self, regno, datap)
1044 	void *self;
1045 	u_int8_t regno;
1046 	u_int16_t *datap;
1047 {
1048 	struct maestro_softc *sc = (struct maestro_softc *)self;
1049 	int t;
1050 
1051 	/* We have to wait for a SAFE time to write addr/data */
1052 	for (t = 0; t < 20; t++) {
1053 		if ((bus_space_read_1(sc->iot, sc->ioh, PORT_CODEC_STAT)
1054 		    & CODEC_STAT_MASK) != CODEC_STAT_PROGLESS)
1055 			break;
1056 		DELAY(2);	/* 20.8us / 13 */
1057 	}
1058 	if (t == 20)
1059 		printf("%s: maestro_read_codec() PROGLESS timed out.\n",
1060 		    sc->dev.dv_xname);
1061 		/* XXX return 1 */
1062 
1063 	bus_space_write_1(sc->iot, sc->ioh, PORT_CODEC_CMD,
1064 	    CODEC_CMD_READ | regno);
1065 	DELAY(21);	/* AC97 cycle = 20.8usec */
1066 
1067 	/* Wait for data retrieve */
1068 	for (t = 0; t < 20; t++) {
1069 		if ((bus_space_read_1(sc->iot, sc->ioh, PORT_CODEC_STAT)
1070 		    & CODEC_STAT_MASK) == CODEC_STAT_RW_DONE)
1071 			break;
1072 		DELAY(2);	/* 20.8us / 13 */
1073 	}
1074 	if (t == 20)
1075 		/* Timed out, but perform dummy read. */
1076 		printf("%s: maestro_read_codec() RW_DONE timed out.\n",
1077 		    sc->dev.dv_xname);
1078 
1079 	*datap = bus_space_read_2(sc->iot, sc->ioh, PORT_CODEC_REG);
1080 	return 0;
1081 }
1082 
1083 int
1084 maestro_write_codec(self, regno, data)
1085 	void *self;
1086 	u_int8_t regno;
1087 	u_int16_t data;
1088 {
1089 	struct maestro_softc *sc = (struct maestro_softc *)self;
1090 	int t;
1091 
1092 	/* We have to wait for a SAFE time to write addr/data */
1093 	for (t = 0; t < 20; t++) {
1094 		if ((bus_space_read_1(sc->iot, sc->ioh, PORT_CODEC_STAT)
1095 		    & CODEC_STAT_MASK) != CODEC_STAT_PROGLESS)
1096 			break;
1097 		DELAY(2);	/* 20.8us / 13 */
1098 	}
1099 	if (t == 20) {
1100 		/* Timed out. Abort writing. */
1101 		printf("%s: maestro_write_codec() PROGLESS timed out.\n",
1102 		    sc->dev.dv_xname);
1103 		return 1;
1104 	}
1105 
1106 	bus_space_write_2(sc->iot, sc->ioh, PORT_CODEC_REG, data);
1107 	bus_space_write_1(sc->iot, sc->ioh, PORT_CODEC_CMD,
1108 	    CODEC_CMD_WRITE | regno);
1109 
1110 	return 0;
1111 }
1112 
1113 int
1114 maestro_attach_codec(self, cif)
1115 	void *self;
1116 	struct ac97_codec_if *cif;
1117 {
1118 	struct maestro_softc *sc = (struct maestro_softc *)self;
1119 
1120 	sc->codec_if = cif;
1121 	return 0;
1122 }
1123 
1124 void
1125 maestro_reset_codec(self)
1126 	void *self UNUSED;
1127 {
1128 }
1129 
1130 void
1131 maestro_initcodec(self)
1132 	void *self;
1133 {
1134 	struct maestro_softc *sc = (struct maestro_softc *)self;
1135 	u_int16_t data;
1136 
1137 	if (bus_space_read_4(sc->iot, sc->ioh, PORT_RINGBUS_CTRL)
1138 	    & RINGBUS_CTRL_ACLINK_ENABLED) {
1139 		bus_space_write_4(sc->iot, sc->ioh, PORT_RINGBUS_CTRL, 0);
1140 		DELAY(104);	/* 20.8us * (4 + 1) */
1141 	}
1142 	/* XXX - 2nd codec should be looked at. */
1143 	bus_space_write_4(sc->iot, sc->ioh,
1144 	    PORT_RINGBUS_CTRL, RINGBUS_CTRL_AC97_SWRESET);
1145 	DELAY(2);
1146 	bus_space_write_4(sc->iot, sc->ioh,
1147 	    PORT_RINGBUS_CTRL, RINGBUS_CTRL_ACLINK_ENABLED);
1148 	DELAY(21);
1149 
1150 	maestro_read_codec(sc, 0, &data);
1151 	if ((bus_space_read_1(sc->iot, sc->ioh, PORT_CODEC_STAT)
1152 	    & CODEC_STAT_MASK) != 0) {
1153 		bus_space_write_4(sc->iot, sc->ioh,
1154 		    PORT_RINGBUS_CTRL, 0);
1155 		DELAY(21);
1156 
1157 		/* Try cold reset. */
1158 		printf("%s: resetting codec\n", sc->dev.dv_xname);
1159 
1160 		data = bus_space_read_2(sc->iot, sc->ioh, PORT_GPIO_DIR);
1161 		if (pci_conf_read(sc->pc, sc->pt, 0x58) & 1)
1162 			data |= 0x10;
1163 		data |= 0x009 &
1164 		    ~bus_space_read_2(sc->iot, sc->ioh, PORT_GPIO_DATA);
1165 		bus_space_write_2(sc->iot, sc->ioh,
1166 		    PORT_GPIO_MASK, 0xff6);
1167 		bus_space_write_2(sc->iot, sc->ioh,
1168 		    PORT_GPIO_DIR, data | 0x009);
1169 		bus_space_write_2(sc->iot, sc->ioh,
1170 		    PORT_GPIO_DATA, 0x000);
1171 		DELAY(2);
1172 		bus_space_write_2(sc->iot, sc->ioh,
1173 		    PORT_GPIO_DATA, 0x001);
1174 		DELAY(1);
1175 		bus_space_write_2(sc->iot, sc->ioh,
1176 		    PORT_GPIO_DATA, 0x009);
1177 		DELAY(500000);
1178 		bus_space_write_2(sc->iot, sc->ioh,
1179 		    PORT_GPIO_DIR, data);
1180 		DELAY(84);	/* 20.8us * 4 */
1181 		bus_space_write_4(sc->iot, sc->ioh,
1182 		    PORT_RINGBUS_CTRL, RINGBUS_CTRL_ACLINK_ENABLED);
1183 		DELAY(21);
1184 	}
1185 
1186 	/* Check the codec to see is still busy */
1187 	if ((bus_space_read_1(sc->iot, sc->ioh, PORT_CODEC_STAT) &
1188 	    CODEC_STAT_MASK) != 0) {
1189 		printf("%s: codec failure\n", sc->dev.dv_xname);
1190 	}
1191 }
1192 
1193 /* -----------------------------
1194  * Power management interface
1195  */
1196 
1197 void
1198 maestro_powerhook(why, self)
1199 	int why;
1200 	void *self;
1201 {
1202 	struct maestro_softc *sc = (struct maestro_softc *)self;
1203 
1204 	if (why != PWR_RESUME) {
1205 		/* Power down device on shutdown. */
1206 		DPRINTF(("maestro: power down\n"));
1207 		sc->suspend = why;
1208 		if (sc->record.mode & MAESTRO_RUNNING) {
1209 		    	sc->record.current = wp_apu_read(sc, sc->record.num, APUREG_CURPTR);
1210 			maestro_channel_stop(&sc->record);
1211 		}
1212 		if (sc->play.mode & MAESTRO_RUNNING) {
1213 		    	sc->play.current = wp_apu_read(sc, sc->play.num, APUREG_CURPTR);
1214 			maestro_channel_stop(&sc->play);
1215 		}
1216 
1217 		wp_stoptimer(sc);
1218 
1219 		/* Power down everything except clock. */
1220 		bus_space_write_2(sc->iot, sc->ioh, PORT_HOSTINT_CTRL, 0);
1221 		maestro_write_codec(sc, AC97_REG_POWER, 0xdf00);
1222 		DELAY(20);
1223 		bus_space_write_4(sc->iot, sc->ioh, PORT_RINGBUS_CTRL, 0);
1224 		DELAY(1);
1225 		maestro_power(sc, PPMI_D3);
1226 	} else {
1227 		/* Power up device on resume. */
1228 		DPRINTF(("maestro: power resume\n"));
1229 		if (sc->suspend == PWR_RESUME) {
1230 			printf("%s: resume without suspend?\n");
1231 			sc->suspend = why;
1232 			return;
1233 		}
1234 		sc->suspend = why;
1235 		maestro_power(sc, PPMI_D0);
1236 		DELAY(100000);
1237 		maestro_init(sc);
1238 		/* Restore codec settings */
1239 		if (sc->codec_if)
1240 			sc->codec_if->vtbl->restore_ports(sc->codec_if);
1241 		if (sc->play.mode & MAESTRO_RUNNING)
1242 			maestro_channel_start(&sc->play);
1243 		if (sc->record.mode & MAESTRO_RUNNING)
1244 			maestro_channel_start(&sc->record);
1245 		maestro_update_timer(sc);
1246 	}
1247 }
1248 
1249 void
1250 maestro_power(sc, status)
1251 	struct maestro_softc *sc;
1252 	int status;
1253 {
1254 	int data;
1255 
1256 	/* Set the power state of the device. */
1257 	data = pci_conf_read(sc->pc, sc->pt, CONF_PM_PTR);
1258 	data = pci_conf_read(sc->pc, sc->pt, data);
1259 	if (data == PPMI_CID)
1260 		pci_conf_write(sc->pc, sc->pt, data + PM_CTRL, status);
1261 }
1262 
1263 void
1264 maestro_channel_advance_dma(ch)
1265 	struct maestro_channel *ch;
1266 {
1267 	wpreg_t pos;
1268 #ifdef AUDIO_DEBUG
1269 	maestrointr_called++;
1270 #endif
1271 	for (;;) {
1272 		pos = wp_apu_read(ch->sc, ch->num, APUREG_CURPTR);
1273 		/* Are we still processing the current dma block ? */
1274 		if (pos >= ch->threshold &&
1275 		    pos < ch->threshold + ch->blocksize/2)
1276 			break;
1277 		ch->threshold += ch->blocksize/2;
1278 		if (ch->threshold >= ch->end)
1279 			ch->threshold = ch->start;
1280 		(*ch->intr)(ch->intr_arg);
1281 #ifdef AUDIO_DEBUG
1282 		maestrodma_effective++;
1283 #endif
1284 	}
1285 
1286 #ifdef AUDIO_DEBUG
1287 	if (maestrodebug && maestrointr_called % 64 == 0)
1288 		printf("maestro: dma advanced %lu for %lu calls\n",
1289 			maestrodma_effective, maestrointr_called);
1290 #endif
1291 }
1292 
1293 /* -----------------------------
1294  * Interrupt handler interface
1295  */
1296 int
1297 maestro_intr(arg)
1298 	void *arg;
1299 {
1300 	struct maestro_softc *sc = (struct maestro_softc *)arg;
1301 	u_int16_t status;
1302 
1303 	status = bus_space_read_1(sc->iot, sc->ioh, PORT_HOSTINT_STAT);
1304 	if (status == 0)
1305 		return 0;	/* Not for us? */
1306 
1307 	/* Acknowledge all. */
1308 	bus_space_write_2(sc->iot, sc->ioh, PORT_INT_STAT, 1);
1309 	bus_space_write_1(sc->iot, sc->ioh, PORT_HOSTINT_STAT, status);
1310 
1311 	/* Hardware volume support */
1312 	if (status & HOSTINT_STAT_HWVOL && sc->codec_if != NULL) {
1313 		int n, i, delta, v;
1314 		mixer_ctrl_t hwvol;
1315 
1316 		n = bus_space_read_1(sc->iot, sc->ioh, PORT_HWVOL_MASTER);
1317 		/* Special case: Mute key */
1318 		if (n & 0x11) {
1319 			hwvol.type = AUDIO_MIXER_ENUM;
1320 			hwvol.dev =
1321 			    sc->codec_if->vtbl->get_portnum_by_name(sc->codec_if,
1322 				AudioCoutputs, AudioNmaster, AudioNmute);
1323 			sc->codec_if->vtbl->mixer_get_port(sc->codec_if, &hwvol);
1324 			hwvol.un.ord = !hwvol.un.ord;
1325 		} else {
1326 			hwvol.type = AUDIO_MIXER_VALUE;
1327 			hwvol.un.value.num_channels = 2;
1328 			hwvol.dev =
1329 			    sc->codec_if->vtbl->get_portnum_by_name(
1330 			    	sc->codec_if, AudioCoutputs, AudioNmaster,
1331 				    NULL);
1332 			sc->codec_if->vtbl->mixer_get_port(sc->codec_if, &hwvol);
1333 			/* XXX AC'97 yields five bits for master volume. */
1334 			delta = (n - MIDDLE_VOLUME)/STEP_VOLUME * 8;
1335 			for (i = 0; i < hwvol.un.value.num_channels; i++) {
1336 				v = ((int)hwvol.un.value.level[i]) + delta;
1337 				if (v < 0)
1338 					v = 0;
1339 				else if (v > 255)
1340 					v = 255;
1341 				hwvol.un.value.level[i] = v;
1342 			}
1343 		}
1344 		sc->codec_if->vtbl->mixer_set_port(sc->codec_if, &hwvol);
1345 		/* Reset to compute next diffs */
1346 		bus_space_write_1(sc->iot, sc->ioh, PORT_HWVOL_MASTER,
1347 		    MIDDLE_VOLUME);
1348 	}
1349 
1350 	if (sc->play.mode & MAESTRO_RUNNING)
1351 		maestro_channel_advance_dma(&sc->play);
1352 	/* XXX suppress jitter for stereo play? */
1353 
1354 	if (sc->record.mode & MAESTRO_RUNNING)
1355 		maestro_channel_advance_dma(&sc->record);
1356 
1357 	return 1;
1358 }
1359 
1360 /* -----------------------------
1361  * Hardware interface
1362  */
1363 
1364 /* Codec/Ringbus */
1365 
1366 void
1367 ringbus_setdest(struct maestro_softc *sc, int src, int dest)
1368 {
1369 	u_int32_t	data;
1370 
1371 	data = bus_space_read_4(sc->iot, sc->ioh, PORT_RINGBUS_CTRL);
1372 	data &= ~(0xfU << src);
1373 	data |= (0xfU & dest) << src;
1374 	bus_space_write_4(sc->iot, sc->ioh, PORT_RINGBUS_CTRL, data);
1375 }
1376 
1377 /* Wave Processor */
1378 
1379 wpreg_t
1380 wp_reg_read(struct maestro_softc *sc, int reg)
1381 {
1382 	bus_space_write_2(sc->iot, sc->ioh, PORT_DSP_INDEX, reg);
1383 	return bus_space_read_2(sc->iot, sc->ioh, PORT_DSP_DATA);
1384 }
1385 
1386 void
1387 wp_reg_write(struct maestro_softc *sc, int reg, wpreg_t data)
1388 {
1389 	bus_space_write_2(sc->iot, sc->ioh, PORT_DSP_INDEX, reg);
1390 	bus_space_write_2(sc->iot, sc->ioh, PORT_DSP_DATA, data);
1391 }
1392 
1393 static void
1394 apu_setindex(struct maestro_softc *sc, int reg)
1395 {
1396 	int t;
1397 
1398 	wp_reg_write(sc, WPREG_CRAM_PTR, reg);
1399 	/* Sometimes WP fails to set apu register index. */
1400 	for (t = 0; t < 1000; t++) {
1401 		if (bus_space_read_2(sc->iot, sc->ioh,
1402 		    PORT_DSP_DATA) == reg)
1403 			break;
1404 		bus_space_write_2(sc->iot, sc->ioh, PORT_DSP_DATA, reg);
1405 	}
1406 	if (t == 1000)
1407 		printf("%s: apu_setindex() timeout\n", sc->dev.dv_xname);
1408 }
1409 
1410 wpreg_t
1411 wp_apu_read(struct maestro_softc *sc, int ch, int reg)
1412 {
1413 	wpreg_t ret;
1414 
1415 	apu_setindex(sc, ((unsigned)ch << 4) + reg);
1416 	ret = wp_reg_read(sc, WPREG_DATA_PORT);
1417 	return ret;
1418 }
1419 
1420 void
1421 wp_apu_write(struct maestro_softc *sc, int ch, int reg, wpreg_t data)
1422 {
1423 	int t;
1424 
1425 	apu_setindex(sc, ((unsigned)ch << 4) + reg);
1426 	wp_reg_write(sc, WPREG_DATA_PORT, data);
1427 	for (t = 0; t < 1000; t++) {
1428 		if (bus_space_read_2(sc->iot, sc->ioh, PORT_DSP_DATA) == data)
1429 			break;
1430 		bus_space_write_2(sc->iot, sc->ioh, PORT_DSP_DATA, data);
1431 	}
1432 	if (t == 1000)
1433 		printf("%s: wp_apu_write() timeout\n", sc->dev.dv_xname);
1434 }
1435 
1436 void
1437 wp_settimer(struct maestro_softc *sc, u_int freq)
1438 {
1439 	u_int clock = 48000 << 2;
1440 	u_int prescale = 0, divide = (freq != 0) ? (clock / freq) : ~0;
1441 
1442 	if (divide < 4)
1443 		divide = 4;
1444 	else if (divide > 32 << 8)
1445 		divide = 32 << 8;
1446 
1447 	for (; divide > 32 << 1; divide >>= 1)
1448 		prescale++;
1449 	divide = (divide + 1) >> 1;
1450 
1451 	for (; prescale < 7 && divide > 2 && !(divide & 1); divide >>= 1)
1452 		prescale++;
1453 
1454 	wp_reg_write(sc, WPREG_TIMER_ENABLE, 0);
1455 	wp_reg_write(sc, WPREG_TIMER_FREQ,
1456 	    (prescale << WP_TIMER_FREQ_PRESCALE_SHIFT) | (divide - 1));
1457 	wp_reg_write(sc, WPREG_TIMER_ENABLE, 1);
1458 }
1459 
1460 void
1461 wp_starttimer(struct maestro_softc *sc)
1462 {
1463 	wp_reg_write(sc, WPREG_TIMER_START, 1);
1464 }
1465 
1466 void
1467 wp_stoptimer(struct maestro_softc *sc)
1468 {
1469 	wp_reg_write(sc, WPREG_TIMER_START, 0);
1470 	bus_space_write_2(sc->iot, sc->ioh, PORT_INT_STAT, 1);
1471 }
1472 
1473 /* WaveCache */
1474 
1475 wcreg_t
1476 wc_reg_read(struct maestro_softc *sc, int reg)
1477 {
1478 	bus_space_write_2(sc->iot, sc->ioh, PORT_WAVCACHE_INDEX, reg);
1479 	return bus_space_read_2(sc->iot, sc->ioh, PORT_WAVCACHE_DATA);
1480 }
1481 
1482 void
1483 wc_reg_write(struct maestro_softc *sc, int reg, wcreg_t data)
1484 {
1485 	bus_space_write_2(sc->iot, sc->ioh, PORT_WAVCACHE_INDEX, reg);
1486 	bus_space_write_2(sc->iot, sc->ioh, PORT_WAVCACHE_DATA, data);
1487 }
1488 
1489 u_int16_t
1490 wc_ctrl_read(struct maestro_softc *sc, int ch)
1491 {
1492 	return wc_reg_read(sc, ch << 3);
1493 }
1494 
1495 void
1496 wc_ctrl_write(struct maestro_softc *sc, int ch, wcreg_t data)
1497 {
1498 	wc_reg_write(sc, ch << 3, data);
1499 }
1500 
1501 /* -----------------------------
1502  * Simple zone allocator.
1503  * (All memory allocated in advance)
1504  */
1505 
1506 salloc_t
1507 salloc_new(addr, size, nzones)
1508 	caddr_t addr;
1509 	size_t size;
1510 	int nzones;
1511 {
1512 	struct salloc_pool *pool;
1513 	struct salloc_zone *space;
1514 	int i;
1515 
1516 	MALLOC(pool, salloc_t, sizeof *pool + nzones * sizeof pool->zones[0],
1517 	    M_TEMP, M_WAITOK);
1518 	if (pool == NULL)
1519 		return NULL;
1520 	SLIST_INIT(&pool->free);
1521 	SLIST_INIT(&pool->used);
1522 	SLIST_INIT(&pool->spare);
1523 	/* Espie says the following line is obvious */
1524 	pool->zones = (struct salloc_zone *)(pool + 1);
1525 	for (i = 1; i < nzones; i++)
1526 		SLIST_INSERT_HEAD(&pool->spare, &pool->zones[i], link);
1527 	space = &pool->zones[0];
1528 	space->addr = addr;
1529 	space->size = size;
1530 	SLIST_INSERT_HEAD(&pool->free, space, link);
1531 	return pool;
1532 }
1533 
1534 void
1535 salloc_destroy(pool)
1536 	salloc_t pool;
1537 {
1538 	FREE(pool, M_TEMP);
1539 }
1540 
1541 void
1542 salloc_insert(pool, head, zone, merge)
1543 	salloc_t pool;
1544 	struct salloc_head *head;
1545 	struct salloc_zone *zone;
1546 	int merge;
1547 {
1548 	struct salloc_zone *prev, *next;
1549 
1550 	/*
1551 	 * Insert a zone into an ordered list of zones, possibly
1552 	 * merging adjacent zones.
1553 	 */
1554 	prev = NULL;
1555 	SLIST_FOREACH(next, head, link) {
1556 		if (next->addr > zone->addr)
1557 			break;
1558 		prev = next;
1559 	}
1560 
1561 	if (merge && prev && prev->addr + prev->size == zone->addr) {
1562 		prev->size += zone->size;
1563 		SLIST_INSERT_HEAD(&pool->spare, zone, link);
1564 		zone = prev;
1565 	} else if (prev)
1566 		SLIST_INSERT_AFTER(prev, zone, link);
1567 	else
1568 		SLIST_INSERT_HEAD(head, zone, link);
1569 	if (merge && next && zone->addr + zone->size == next->addr) {
1570 		zone->size += next->size;
1571 		SLIST_REMOVE(head, next, salloc_zone, link);
1572 		SLIST_INSERT_HEAD(&pool->spare, next, link);
1573 	}
1574 }
1575 
1576 caddr_t
1577 salloc_alloc(pool, size)
1578 	salloc_t pool;
1579 	size_t size;
1580 {
1581 	struct salloc_zone *zone, *uzone;
1582 
1583 	SLIST_FOREACH(zone, &pool->free, link)
1584 		if (zone->size >= size)
1585 			break;
1586 	if (zone == SLIST_END(&pool->free))
1587 		return NULL;
1588 	if (zone->size == size) {
1589 		SLIST_REMOVE(&pool->free, zone, salloc_zone, link);
1590 		uzone = zone;
1591 	} else {
1592 		uzone = SLIST_FIRST(&pool->spare);
1593 		if (uzone == NULL)
1594 			return NULL;		/* XXX */
1595 		SLIST_REMOVE_HEAD(&pool->spare, link);
1596 		uzone->size = size;
1597 		uzone->addr = zone->addr;
1598 		zone->size -= size;
1599 		zone->addr += size;
1600 	}
1601 	salloc_insert(pool, &pool->used, uzone, 0);
1602 	return uzone->addr;
1603 }
1604 
1605 void
1606 salloc_free(pool, addr)
1607 	salloc_t pool;
1608 	caddr_t addr;
1609 {
1610 	struct salloc_zone *zone;
1611 
1612 	SLIST_FOREACH(zone, &pool->used, link)
1613 		if (zone->addr == addr)
1614 			break;
1615 #ifdef DIAGNOSTIC
1616 	if (zone == SLIST_END(&pool->used))
1617 		panic("salloc_free: freeing unallocated memory");
1618 #endif
1619 	SLIST_REMOVE(&pool->used, zone, salloc_zone, link);
1620 	salloc_insert(pool, &pool->free, zone, 1);
1621 }
1622