xref: /openbsd-src/sys/dev/pci/fms.c (revision 0b7734b3d77bb9b21afec6f4621cae6c805dbd45)
1 /*	$OpenBSD: fms.c,v 1.27 2015/05/11 06:46:22 ratchov Exp $ */
2 /*	$NetBSD: fms.c,v 1.5.4.1 2000/06/30 16:27:50 simonb Exp $	*/
3 
4 /*-
5  * Copyright (c) 1999 The NetBSD Foundation, Inc.
6  * All rights reserved.
7  *
8  * This code is derived from software contributed to The NetBSD Foundation
9  * by Witold J. Wnuk.
10  *
11  * Redistribution and use in source and binary forms, with or without
12  * modification, are permitted provided that the following conditions
13  * are met:
14  * 1. Redistributions of source code must retain the above copyright
15  *    notice, this list of conditions and the following disclaimer.
16  * 2. Redistributions in binary form must reproduce the above copyright
17  *    notice, this list of conditions and the following disclaimer in the
18  *    documentation and/or other materials provided with the distribution.
19  *
20  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
21  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
22  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
23  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
24  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
25  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
26  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
27  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
28  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
29  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
30  * POSSIBILITY OF SUCH DAMAGE.
31  */
32 
33 /*
34  * Forte Media FM801 Audio Device Driver
35  */
36 
37 #include "radio.h"
38 
39 #include <sys/param.h>
40 #include <sys/systm.h>
41 #include <sys/kernel.h>
42 #include <sys/malloc.h>
43 #include <sys/device.h>
44 #include <sys/audioio.h>
45 
46 #include <machine/bus.h>
47 #include <machine/cpu.h>
48 
49 #include <dev/pci/pcidevs.h>
50 #include <dev/pci/pcivar.h>
51 
52 #include <dev/audio_if.h>
53 #include <dev/ic/ac97.h>
54 #if 0
55 #include <dev/ic/mpuvar.h>
56 #endif
57 
58 #include <dev/pci/fmsreg.h>
59 #include <dev/pci/fmsvar.h>
60 
61 
62 struct fms_dma {
63 	struct fms_dma *next;
64 	caddr_t addr;
65 	size_t size;
66 	bus_dmamap_t map;
67 	bus_dma_segment_t seg;
68 };
69 
70 
71 
72 int	fms_match(struct device *, void *, void *);
73 void	fms_attach(struct device *, struct device *, void *);
74 int	fms_intr(void *);
75 
76 int	fms_open(void *, int);
77 void	fms_close(void *);
78 int	fms_query_encoding(void *, struct audio_encoding *);
79 int	fms_set_params(void *, int, int, struct audio_params *,
80 			    struct audio_params *);
81 void	fms_get_default_params(void *, int, struct audio_params *);
82 int	fms_round_blocksize(void *, int);
83 int	fms_halt_output(void *);
84 int	fms_halt_input(void *);
85 int	fms_getdev(void *, struct audio_device *);
86 int	fms_set_port(void *, mixer_ctrl_t *);
87 int	fms_get_port(void *, mixer_ctrl_t *);
88 int	fms_query_devinfo(void *, mixer_devinfo_t *);
89 void	*fms_malloc(void *, int, size_t, int, int);
90 void	fms_free(void *, void *, int);
91 paddr_t	fms_mappage(void *, void *, off_t, int);
92 int	fms_get_props(void *);
93 int	fms_trigger_output(void *, void *, void *, int, void (*)(void *),
94 			   void *, struct audio_params *);
95 int	fms_trigger_input(void *, void *, void *, int, void (*)(void *),
96 			  void *, struct audio_params *);
97 
98 struct  cfdriver fms_cd = {
99 	NULL, "fms", DV_DULL
100 };
101 
102 struct cfattach fms_ca = {
103 	sizeof (struct fms_softc), fms_match, fms_attach
104 };
105 
106 struct audio_device fms_device = {
107 	"Forte Media 801",
108 	"1.0",
109 	"fms"
110 };
111 
112 
113 struct audio_hw_if fms_hw_if = {
114 	fms_open,
115 	fms_close,
116 	NULL,
117 	fms_query_encoding,
118 	fms_set_params,
119 	fms_round_blocksize,
120 	NULL,
121 	NULL,
122 	NULL,
123 	NULL,
124 	NULL,
125 	fms_halt_output,
126 	fms_halt_input,
127 	NULL,
128 	fms_getdev,
129 	NULL,
130 	fms_set_port,
131 	fms_get_port,
132 	fms_query_devinfo,
133 	fms_malloc,
134 	fms_free,
135 	NULL,
136 	fms_mappage,
137 	fms_get_props,
138 	fms_trigger_output,
139 	fms_trigger_input,
140 	fms_get_default_params
141 };
142 
143 int	fms_attach_codec(void *, struct ac97_codec_if *);
144 int	fms_read_codec(void *, u_int8_t, u_int16_t *);
145 int	fms_write_codec(void *, u_int8_t, u_int16_t);
146 void	fms_reset_codec(void *);
147 
148 int	fms_allocmem(struct fms_softc *, size_t, size_t,
149 			  struct fms_dma *);
150 int	fms_freemem(struct fms_softc *, struct fms_dma *);
151 
152 int
153 fms_match(struct device *parent, void *match, void *aux)
154 {
155 	struct pci_attach_args *pa = (struct pci_attach_args *) aux;
156 
157 	if (PCI_VENDOR(pa->pa_id) == PCI_VENDOR_FORTEMEDIA &&
158 	    PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_FORTEMEDIA_FM801)
159 		return (1);
160 	return (0);
161 }
162 
163 void
164 fms_attach(struct device *parent, struct device *self, void *aux)
165 {
166 	struct pci_attach_args *pa = aux;
167 	struct fms_softc *sc = (struct fms_softc *) self;
168 	struct audio_attach_args aa;
169 	pci_chipset_tag_t pc = pa->pa_pc;
170 	pcitag_t pt = pa->pa_tag;
171 	pci_intr_handle_t ih;
172 	bus_size_t iosize;
173 	const char *intrstr;
174 	u_int16_t k1;
175 	int i;
176 
177 	if (pci_mapreg_map(pa, 0x10, PCI_MAPREG_TYPE_IO, 0, &sc->sc_iot,
178 	    &sc->sc_ioh, NULL, &iosize, 0)) {
179 		printf(": can't map i/o space\n");
180 		return;
181 	}
182 
183 	if (bus_space_subregion(sc->sc_iot, sc->sc_ioh, 0x30, 2,
184 	    &sc->sc_mpu_ioh)) {
185 		printf(": can't get mpu subregion handle\n");
186 		bus_space_unmap(sc->sc_iot, sc->sc_ioh, iosize);
187 		return;
188 	}
189 
190 	if (bus_space_subregion(sc->sc_iot, sc->sc_ioh, 0x68, 4,
191 	    &sc->sc_opl_ioh)) {
192 		printf(": can't get opl subregion handle\n");
193 		bus_space_unmap(sc->sc_iot, sc->sc_ioh, iosize);
194 		return;
195 	}
196 
197 	if (pci_intr_map(pa, &ih)) {
198 		printf(": couldn't map interrupt\n");
199 		bus_space_unmap(sc->sc_iot, sc->sc_ioh, iosize);
200 		return;
201 	}
202 	intrstr = pci_intr_string(pc, ih);
203 
204 	sc->sc_ih = pci_intr_establish(pc, ih, IPL_AUDIO | IPL_MPSAFE,
205 	    fms_intr, sc, sc->sc_dev.dv_xname);
206 	if (sc->sc_ih == NULL) {
207 		printf(": couldn't establish interrupt");
208 		if (intrstr != NULL)
209 			printf(" at %s", intrstr);
210 		printf("\n");
211 		bus_space_unmap(sc->sc_iot, sc->sc_ioh, iosize);
212 		return;
213 	}
214 
215 	printf(": %s\n", intrstr);
216 
217 	sc->sc_dmat = pa->pa_dmat;
218 
219 	/* Disable legacy audio (SBPro compatibility) */
220 	pci_conf_write(pc, pt, 0x40, 0);
221 
222 	/* Reset codec and AC'97 */
223 	bus_space_write_2(sc->sc_iot, sc->sc_ioh, FM_CODEC_CTL, 0x0020);
224 	delay(2);		/* > 1us according to AC'97 documentation */
225 	bus_space_write_2(sc->sc_iot, sc->sc_ioh, FM_CODEC_CTL, 0x0000);
226 	delay(1);		/* > 168.2ns according to AC'97 documentation */
227 
228 	/* Set up volume */
229 	bus_space_write_2(sc->sc_iot, sc->sc_ioh, FM_PCM_VOLUME, 0x0808);
230 	bus_space_write_2(sc->sc_iot, sc->sc_ioh, FM_FM_VOLUME, 0x0808);
231 	bus_space_write_2(sc->sc_iot, sc->sc_ioh, FM_I2S_VOLUME, 0x0808);
232 
233 	bus_space_write_2(sc->sc_iot, sc->sc_ioh, FM_RECORD_SOURCE, 0x0000);
234 
235 	/* Unmask playback, record and mpu interrupts, mask the rest */
236 	k1 = bus_space_read_2(sc->sc_iot, sc->sc_ioh, FM_INTMASK);
237 	bus_space_write_2(sc->sc_iot, sc->sc_ioh, FM_INTMASK,
238 	    (k1 & ~(FM_INTMASK_PLAY | FM_INTMASK_REC | FM_INTMASK_MPU)) |
239 	     FM_INTMASK_VOL);
240 	bus_space_write_2(sc->sc_iot, sc->sc_ioh, FM_INTSTATUS,
241 	    FM_INTSTATUS_PLAY | FM_INTSTATUS_REC | FM_INTSTATUS_MPU |
242 	    FM_INTSTATUS_VOL);
243 
244 #if NRADIO > 0
245 	fmsradio_attach(sc);
246 #endif /* NRADIO > 0 */
247 
248 	sc->host_if.arg = sc;
249 	sc->host_if.attach = fms_attach_codec;
250 	sc->host_if.read = fms_read_codec;
251 	sc->host_if.write = fms_write_codec;
252 	sc->host_if.reset = fms_reset_codec;
253 
254 	if (ac97_attach(&sc->host_if) != 0)
255 		return;
256 
257 	/* Turn mute off */
258 	for (i = 0; i < 3; i++) {
259 		static struct {
260 			char *class, *device;
261 		} d[] = {
262 			{ AudioCoutputs, AudioNmaster },
263 			{ AudioCinputs, AudioNdac },
264 			{ AudioCrecord, AudioNvolume }
265 		};
266 		struct mixer_ctrl ctl;
267 
268 		ctl.type = AUDIO_MIXER_ENUM;
269 		ctl.un.ord = 0;
270 		ctl.dev = sc->codec_if->vtbl->get_portnum_by_name(sc->codec_if,
271 			d[i].class, d[i].device, AudioNmute);
272 		fms_set_port(sc, &ctl);
273 	}
274 
275 	audio_attach_mi(&fms_hw_if, sc, &sc->sc_dev);
276 
277 	aa.type = AUDIODEV_TYPE_OPL;
278 	aa.hwif = NULL;
279 	aa.hdl = NULL;
280 	config_found(&sc->sc_dev, &aa, audioprint);
281 
282 	aa.type = AUDIODEV_TYPE_MPU;
283 	aa.hwif = NULL;
284 	aa.hdl = NULL;
285 	sc->sc_mpu_dev = config_found(&sc->sc_dev, &aa, audioprint);
286 }
287 
288 /*
289  * Each AC-link frame takes 20.8us, data should be ready in next frame,
290  * we allow more than two.
291  */
292 #define TIMO 50
293 int
294 fms_read_codec(void *addr, u_int8_t reg, u_int16_t *val)
295 {
296 	struct fms_softc *sc = addr;
297 	int i;
298 
299 	/* Poll until codec is ready */
300 	for (i = 0; i < TIMO && bus_space_read_2(sc->sc_iot, sc->sc_ioh,
301 		 FM_CODEC_CMD) & FM_CODEC_CMD_BUSY; i++)
302 		delay(1);
303 	if (i >= TIMO) {
304 		printf("fms: codec busy\n");
305 		return 1;
306 	}
307 
308 	/* Write register index, read access */
309 	bus_space_write_2(sc->sc_iot, sc->sc_ioh, FM_CODEC_CMD,
310 			  reg | FM_CODEC_CMD_READ);
311 
312 	/* Poll until we have valid data */
313 	for (i = 0; i < TIMO && !(bus_space_read_2(sc->sc_iot, sc->sc_ioh,
314 		 FM_CODEC_CMD) & FM_CODEC_CMD_VALID); i++)
315 		delay(1);
316 	if (i >= TIMO) {
317 		printf("fms: no data from codec\n");
318 		return 1;
319 	}
320 
321 	/* Read data */
322 	*val = bus_space_read_2(sc->sc_iot, sc->sc_ioh, FM_CODEC_DATA);
323 	return 0;
324 }
325 
326 int
327 fms_write_codec(void *addr, u_int8_t reg, u_int16_t val)
328 {
329 	struct fms_softc *sc = addr;
330 	int i;
331 
332 	/* Poll until codec is ready */
333 	for (i = 0; i < TIMO && bus_space_read_2(sc->sc_iot, sc->sc_ioh,
334 		 FM_CODEC_CMD) & FM_CODEC_CMD_BUSY; i++)
335 		delay(1);
336 	if (i >= TIMO) {
337 		printf("fms: codec busy\n");
338 		return 1;
339 	}
340 
341 	/* Write data */
342 	bus_space_write_2(sc->sc_iot, sc->sc_ioh, FM_CODEC_DATA, val);
343 	/* Write index register, write access */
344 	bus_space_write_2(sc->sc_iot, sc->sc_ioh, FM_CODEC_CMD, reg);
345 	return 0;
346 }
347 #undef TIMO
348 
349 int
350 fms_attach_codec(void *addr, struct ac97_codec_if *cif)
351 {
352 	struct fms_softc *sc = addr;
353 
354 	sc->codec_if = cif;
355 	return 0;
356 }
357 
358 /* Cold Reset */
359 void
360 fms_reset_codec(void *addr)
361 {
362 	struct fms_softc *sc = addr;
363 	bus_space_write_2(sc->sc_iot, sc->sc_ioh, FM_CODEC_CTL, 0x0020);
364 	delay(2);
365 	bus_space_write_2(sc->sc_iot, sc->sc_ioh, FM_CODEC_CTL, 0x0000);
366 	delay(1);
367 }
368 
369 int
370 fms_intr(void *arg)
371 {
372 	struct fms_softc *sc = arg;
373 	u_int16_t istat;
374 
375 	mtx_enter(&audio_lock);
376 	istat = bus_space_read_2(sc->sc_iot, sc->sc_ioh, FM_INTSTATUS);
377 
378 	if (istat & FM_INTSTATUS_PLAY) {
379 		if ((sc->sc_play_nextblk += sc->sc_play_blksize) >=
380 		     sc->sc_play_end)
381 			sc->sc_play_nextblk = sc->sc_play_start;
382 
383 		bus_space_write_4(sc->sc_iot, sc->sc_ioh,
384 		    sc->sc_play_flip++ & 1 ?
385 		    FM_PLAY_DMABUF2 : FM_PLAY_DMABUF1, sc->sc_play_nextblk);
386 
387 		if (sc->sc_pintr)
388 			sc->sc_pintr(sc->sc_parg);
389 		else
390 			printf("unexpected play intr\n");
391 	}
392 
393 	if (istat & FM_INTSTATUS_REC) {
394 		if ((sc->sc_rec_nextblk += sc->sc_rec_blksize) >=
395 		     sc->sc_rec_end)
396 			sc->sc_rec_nextblk = sc->sc_rec_start;
397 
398 		bus_space_write_4(sc->sc_iot, sc->sc_ioh,
399 		    sc->sc_rec_flip++ & 1 ?
400 		    FM_REC_DMABUF2 : FM_REC_DMABUF1, sc->sc_rec_nextblk);
401 
402 		if (sc->sc_rintr)
403 			sc->sc_rintr(sc->sc_rarg);
404 		else
405 			printf("unexpected rec intr\n");
406 	}
407 
408 #if 0
409 	if (istat & FM_INTSTATUS_MPU)
410 		mpu_intr(sc->sc_mpu_dev);
411 #endif
412 
413 	bus_space_write_2(sc->sc_iot, sc->sc_ioh, FM_INTSTATUS,
414 			  istat & (FM_INTSTATUS_PLAY | FM_INTSTATUS_REC));
415 	mtx_leave(&audio_lock);
416 	return 1;
417 }
418 
419 int
420 fms_open(void *addr, int flags)
421 {
422 	/* UNUSED struct fms_softc *sc = addr;*/
423 
424 	return 0;
425 }
426 
427 void
428 fms_close(void *addr)
429 {
430 	/* UNUSED struct fms_softc *sc = addr;*/
431 }
432 
433 int
434 fms_query_encoding(void *addr, struct audio_encoding *fp)
435 {
436 
437 	switch (fp->index) {
438 	case 0:
439 		strlcpy(fp->name, AudioEslinear_le, sizeof fp->name);
440 		fp->encoding = AUDIO_ENCODING_SLINEAR_LE;
441 		fp->precision = 16;
442 		fp->flags = 0;
443 		break;
444 	case 1:
445 		strlcpy(fp->name, AudioEulinear, sizeof fp->name);
446 		fp->encoding = AUDIO_ENCODING_ULINEAR;
447 		fp->precision = 8;
448 		fp->flags = 0;
449 		break;
450 	default:
451 		return EINVAL;
452 	}
453 	fp->bps = AUDIO_BPS(fp->precision);
454 	fp->msb = 1;
455 
456 	return 0;
457 }
458 
459 void
460 fms_get_default_params(void *addr, int mode, struct audio_params *params)
461 {
462 	ac97_get_default_params(params);
463 }
464 
465 /*
466  * Range below -limit- is set to -rate-
467  * What a pity FM801 does not have 24000
468  * 24000 -> 22050 sounds rather poor
469  */
470 struct {
471 	int limit;
472 	int rate;
473 } fms_rates[11] = {
474 	{  6600,  5500 },
475 	{  8750,  8000 },
476 	{ 10250,  9600 },
477 	{ 13200, 11025 },
478 	{ 17500, 16000 },
479 	{ 20500, 19200 },
480 	{ 26500, 22050 },
481 	{ 35000, 32000 },
482 	{ 41000, 38400 },
483 	{ 46000, 44100 },
484 	{ 48000, 48000 },
485 	/* anything above -> 48000 */
486 };
487 
488 int
489 fms_set_params(void *addr, int setmode, int usemode, struct audio_params *play,
490     struct audio_params *rec)
491 {
492 	struct fms_softc *sc = addr;
493 	int i;
494 
495 	if (setmode & AUMODE_PLAY) {
496 		switch(play->encoding) {
497 		case AUDIO_ENCODING_SLINEAR_LE:
498 			if (play->precision != 16)
499 				return EINVAL;
500 			break;
501 		case AUDIO_ENCODING_ULINEAR_LE:
502 		case AUDIO_ENCODING_ULINEAR_BE:
503 			if (play->precision != 8)
504 				return EINVAL;
505 			break;
506 		default:
507 			return EINVAL;
508 		}
509 		play->bps = AUDIO_BPS(play->precision);
510 		play->msb = 1;
511 
512 		for (i = 0; i < 10 && play->sample_rate > fms_rates[i].limit;
513 		     i++)
514 			;
515 		play->sample_rate = fms_rates[i].rate;
516 		sc->sc_play_reg = (play->channels == 2 ? FM_PLAY_STEREO : 0) |
517 		    (play->precision == 16 ? FM_PLAY_16BIT : 0) |
518 		    (i << 8);
519 	}
520 
521 	if (setmode & AUMODE_RECORD) {
522 
523 		switch(rec->encoding) {
524 		case AUDIO_ENCODING_SLINEAR_LE:
525 			if (rec->precision != 16)
526 				return EINVAL;
527 			break;
528 		case AUDIO_ENCODING_ULINEAR_LE:
529 		case AUDIO_ENCODING_ULINEAR_BE:
530 			if (rec->precision != 8)
531 				return EINVAL;
532 			break;
533 		default:
534 			return EINVAL;
535 		}
536 		rec->bps = AUDIO_BPS(rec->precision);
537 		rec->msb = 1;
538 
539 		for (i = 0; i < 10 && rec->sample_rate > fms_rates[i].limit;
540 		     i++)
541 			;
542 		rec->sample_rate = fms_rates[i].rate;
543 		sc->sc_rec_reg =
544 		    (rec->channels == 2 ? FM_REC_STEREO : 0) |
545 		    (rec->precision == 16 ? FM_REC_16BIT : 0) |
546 		    (i << 8);
547 	}
548 
549 	return 0;
550 }
551 
552 int
553 fms_round_blocksize(void *addr, int blk)
554 {
555 	return (blk + 0xf) & ~0xf;
556 }
557 
558 int
559 fms_halt_output(void *addr)
560 {
561 	struct fms_softc *sc = addr;
562 	u_int16_t k1;
563 
564 	mtx_enter(&audio_lock);
565 	k1 = bus_space_read_2(sc->sc_iot, sc->sc_ioh, FM_PLAY_CTL);
566 	bus_space_write_2(sc->sc_iot, sc->sc_ioh, FM_PLAY_CTL,
567 			  (k1 & ~(FM_PLAY_STOPNOW | FM_PLAY_START)) |
568 			  FM_PLAY_BUF1_LAST | FM_PLAY_BUF2_LAST);
569 	mtx_leave(&audio_lock);
570 	return 0;
571 }
572 
573 int
574 fms_halt_input(void *addr)
575 {
576 	struct fms_softc *sc = addr;
577 	u_int16_t k1;
578 
579 	mtx_enter(&audio_lock);
580 	k1 = bus_space_read_2(sc->sc_iot, sc->sc_ioh, FM_REC_CTL);
581 	bus_space_write_2(sc->sc_iot, sc->sc_ioh, FM_REC_CTL,
582 			  (k1 & ~(FM_REC_STOPNOW | FM_REC_START)) |
583 			  FM_REC_BUF1_LAST | FM_REC_BUF2_LAST);
584 	mtx_leave(&audio_lock);
585 	return 0;
586 }
587 
588 int
589 fms_getdev(void *addr, struct audio_device *retp)
590 {
591 	*retp = fms_device;
592 	return 0;
593 }
594 
595 int
596 fms_set_port(void *addr, mixer_ctrl_t *cp)
597 {
598 	struct fms_softc *sc = addr;
599 
600 	return (sc->codec_if->vtbl->mixer_set_port(sc->codec_if, cp));
601 }
602 
603 int
604 fms_get_port(void *addr, mixer_ctrl_t *cp)
605 {
606 	struct fms_softc *sc = addr;
607 
608 	return (sc->codec_if->vtbl->mixer_get_port(sc->codec_if, cp));
609 }
610 
611 void *
612 fms_malloc(void *addr, int direction, size_t size, int pool, int flags)
613 {
614 	struct fms_softc *sc = addr;
615 	struct fms_dma *p;
616 	int error;
617 	int rseg;
618 
619 	p = malloc(sizeof(*p), pool, flags);
620 	if (!p)
621 		return 0;
622 
623 	p->size = size;
624 	if ((error = bus_dmamem_alloc(sc->sc_dmat, size, NBPG, 0, &p->seg, 1,
625 				      &rseg, BUS_DMA_NOWAIT)) != 0) {
626 		printf("%s: unable to allocate dma, error = %d\n",
627 		       sc->sc_dev.dv_xname, error);
628 		goto fail_alloc;
629 	}
630 
631 	if ((error = bus_dmamem_map(sc->sc_dmat, &p->seg, rseg, size, &p->addr,
632 				    BUS_DMA_NOWAIT | BUS_DMA_COHERENT)) != 0) {
633 		printf("%s: unable to map dma, error = %d\n",
634 		       sc->sc_dev.dv_xname, error);
635 		goto fail_map;
636 	}
637 
638 	if ((error = bus_dmamap_create(sc->sc_dmat, size, 1, size, 0,
639 				       BUS_DMA_NOWAIT, &p->map)) != 0) {
640 		printf("%s: unable to create dma map, error = %d\n",
641 		       sc->sc_dev.dv_xname, error);
642 		goto fail_create;
643 	}
644 
645 	if ((error = bus_dmamap_load(sc->sc_dmat, p->map, p->addr, size, NULL,
646 				     BUS_DMA_NOWAIT)) != 0) {
647 		printf("%s: unable to load dma map, error = %d\n",
648 		       sc->sc_dev.dv_xname, error);
649 		goto fail_load;
650 	}
651 
652 	p->next = sc->sc_dmas;
653 	sc->sc_dmas = p;
654 
655 	return p->addr;
656 
657 
658 fail_load:
659 	bus_dmamap_destroy(sc->sc_dmat, p->map);
660 fail_create:
661 	bus_dmamem_unmap(sc->sc_dmat, p->addr, size);
662 fail_map:
663 	bus_dmamem_free(sc->sc_dmat, &p->seg, 1);
664 fail_alloc:
665 	free(p, pool, 0);
666 	return 0;
667 }
668 
669 void
670 fms_free(void *addr, void *ptr, int pool)
671 {
672 	struct fms_softc *sc = addr;
673 	struct fms_dma **pp, *p;
674 
675 	for (pp = &(sc->sc_dmas); (p = *pp) != NULL; pp = &p->next)
676 		if (p->addr == ptr) {
677 			bus_dmamap_unload(sc->sc_dmat, p->map);
678 			bus_dmamap_destroy(sc->sc_dmat, p->map);
679 			bus_dmamem_unmap(sc->sc_dmat, p->addr, p->size);
680 			bus_dmamem_free(sc->sc_dmat, &p->seg, 1);
681 
682 			*pp = p->next;
683 			free(p, pool, 0);
684 			return;
685 		}
686 
687 	panic("fms_free: trying to free unallocated memory");
688 }
689 
690 paddr_t
691 fms_mappage(void *addr, void *mem, off_t off, int prot)
692 {
693 	struct fms_softc *sc = addr;
694 	struct fms_dma *p;
695 
696 	if (off < 0)
697 		return -1;
698 
699 	for (p = sc->sc_dmas; p && p->addr != mem; p = p->next)
700 		;
701 	if (!p)
702 		return -1;
703 
704 	return bus_dmamem_mmap(sc->sc_dmat, &p->seg, 1, off, prot,
705 			       BUS_DMA_WAITOK);
706 }
707 
708 int
709 fms_get_props(void *addr)
710 {
711 	return AUDIO_PROP_MMAP | AUDIO_PROP_INDEPENDENT |
712 	       AUDIO_PROP_FULLDUPLEX;
713 }
714 
715 int
716 fms_query_devinfo(void *addr, mixer_devinfo_t *dip)
717 {
718 	struct fms_softc *sc = addr;
719 
720 	return (sc->codec_if->vtbl->query_devinfo(sc->codec_if, dip));
721 }
722 
723 int
724 fms_trigger_output(void *addr, void *start, void *end, int blksize,
725     void (*intr)(void *), void *arg, struct audio_params *param)
726 {
727 	struct fms_softc *sc = addr;
728 	struct fms_dma *p;
729 
730 	sc->sc_pintr = intr;
731 	sc->sc_parg = arg;
732 
733 	for (p = sc->sc_dmas; p && p->addr != start; p = p->next)
734 		;
735 
736 	if (!p)
737 		panic("fms_trigger_output: request with bad start "
738 		      "address (%p)", start);
739 
740 	sc->sc_play_start = p->map->dm_segs[0].ds_addr;
741 	sc->sc_play_end = sc->sc_play_start + ((char *)end - (char *)start);
742 	sc->sc_play_blksize = blksize;
743 	sc->sc_play_nextblk = sc->sc_play_start + sc->sc_play_blksize;
744 	sc->sc_play_flip = 0;
745 	mtx_enter(&audio_lock);
746 	bus_space_write_2(sc->sc_iot, sc->sc_ioh, FM_PLAY_DMALEN, blksize - 1);
747 	bus_space_write_4(sc->sc_iot, sc->sc_ioh, FM_PLAY_DMABUF1,
748 			  sc->sc_play_start);
749 	bus_space_write_4(sc->sc_iot, sc->sc_ioh, FM_PLAY_DMABUF2,
750 			  sc->sc_play_nextblk);
751 	bus_space_write_2(sc->sc_iot, sc->sc_ioh, FM_PLAY_CTL,
752 			  FM_PLAY_START | FM_PLAY_STOPNOW | sc->sc_play_reg);
753 	mtx_leave(&audio_lock);
754 	return 0;
755 }
756 
757 
758 int
759 fms_trigger_input(void *addr, void *start, void *end, int blksize,
760     void (*intr)(void *), void *arg, struct audio_params *param)
761 {
762 	struct fms_softc *sc = addr;
763 	struct fms_dma *p;
764 
765 	sc->sc_rintr = intr;
766 	sc->sc_rarg = arg;
767 
768 	for (p = sc->sc_dmas; p && p->addr != start; p = p->next)
769 		;
770 
771 	if (!p)
772 		panic("fms_trigger_input: request with bad start "
773 		      "address (%p)", start);
774 
775 	sc->sc_rec_start = p->map->dm_segs[0].ds_addr;
776 	sc->sc_rec_end = sc->sc_rec_start + ((char *)end - (char *)start);
777 	sc->sc_rec_blksize = blksize;
778 	sc->sc_rec_nextblk = sc->sc_rec_start + sc->sc_rec_blksize;
779 	sc->sc_rec_flip = 0;
780 	mtx_enter(&audio_lock);
781 	bus_space_write_2(sc->sc_iot, sc->sc_ioh, FM_REC_DMALEN, blksize - 1);
782 	bus_space_write_4(sc->sc_iot, sc->sc_ioh, FM_REC_DMABUF1,
783 			  sc->sc_rec_start);
784 	bus_space_write_4(sc->sc_iot, sc->sc_ioh, FM_REC_DMABUF2,
785 			  sc->sc_rec_nextblk);
786 	bus_space_write_2(sc->sc_iot, sc->sc_ioh, FM_REC_CTL,
787 			  FM_REC_START | FM_REC_STOPNOW | sc->sc_rec_reg);
788 	mtx_leave(&audio_lock);
789 	return 0;
790 }
791