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