xref: /openbsd-src/sys/dev/pci/cmpci.c (revision db3296cf5c1dd9058ceecc3a29fe4aaa0bd26000)
1 /*	$OpenBSD: cmpci.c,v 1.11 2003/06/05 23:53:54 fgsch Exp $	*/
2 
3 /*
4  * Copyright (c) 2000 Takuya SHIOZAKI
5  * All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  * 1. Redistributions of source code must retain the above copyright
11  *    notice, this list of conditions and the following disclaimer.
12  * 2. Redistributions in binary form must reproduce the above copyright
13  *    notice, this list of conditions and the following disclaimer in the
14  *    documentation and/or other materials provided with the distribution.
15  *
16  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
17  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
20  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26  * SUCH DAMAGE.
27  *
28  */
29 
30 /*
31  * C-Media CMI8x38 Audio Chip Support.
32  *
33  * TODO:
34  *   - Legacy MPU, OPL and Joystick support (but, I have no interest...)
35  *   - SPDIF support
36  *
37  */
38 
39 #undef CMPCI_SPDIF_SUPPORT  /* XXX: not working */
40 
41 #if defined(AUDIO_DEBUG) || defined(DEBUG)
42 #define DPRINTF(x) printf x
43 #else
44 #define DPRINTF(x)
45 #endif
46 
47 #include <sys/param.h>
48 #include <sys/systm.h>
49 #include <sys/kernel.h>
50 #include <sys/malloc.h>
51 #include <sys/device.h>
52 #include <sys/proc.h>
53 
54 #include <dev/pci/pcidevs.h>
55 #include <dev/pci/pcivar.h>
56 
57 #include <sys/audioio.h>
58 #include <dev/audio_if.h>
59 #include <dev/mulaw.h>
60 #include <dev/auconv.h>
61 
62 #include <dev/pci/cmpcireg.h>
63 #include <dev/pci/cmpcivar.h>
64 
65 #include <machine/bus.h>
66 #include <machine/intr.h>
67 
68 /*
69  * Low-level HW interface
70  */
71 static __inline uint8_t cmpci_mixerreg_read(struct cmpci_softc *,
72                                                  uint8_t);
73 static __inline void cmpci_mixerreg_write(struct cmpci_softc *,
74                                                uint8_t, uint8_t);
75 static __inline void cmpci_reg_partial_write_4(struct cmpci_softc *,
76                                                     int, int,
77                                                     uint32_t, uint32_t);
78 static __inline void cmpci_reg_set_4(struct cmpci_softc *,
79                                           int, uint32_t);
80 static __inline void cmpci_reg_clear_4(struct cmpci_softc *,
81                                             int, uint32_t);
82 static int cmpci_rate_to_index(int);
83 static __inline int cmpci_index_to_rate(int);
84 static __inline int cmpci_index_to_divider(int);
85 
86 static int cmpci_adjust(int, int);
87 static void cmpci_set_mixer_gain(struct cmpci_softc *, int);
88 static int cmpci_set_in_ports(struct cmpci_softc *, int);
89 
90 
91 /*
92  * autoconf interface
93  */
94 int cmpci_match(struct device *, void *, void *);
95 void cmpci_attach(struct device *, struct device *, void *);
96 
97 struct cfdriver cmpci_cd = {
98 	NULL, "cmpci", DV_DULL
99 };
100 
101 struct cfattach cmpci_ca = {
102 	sizeof (struct cmpci_softc), cmpci_match, cmpci_attach
103 };
104 
105 struct audio_device cmpci_device = {
106 	"CMI PCI Audio",
107 	"",
108 	"cmpci"
109 };
110 
111 /* interrupt */
112 int cmpci_intr(void *);
113 
114 
115 /*
116  * DMA stuff
117  */
118 int cmpci_alloc_dmamem(struct cmpci_softc *,
119                             size_t, int, int, caddr_t *);
120 int cmpci_free_dmamem(struct cmpci_softc *, caddr_t, int);
121 struct cmpci_dmanode * cmpci_find_dmamem(struct cmpci_softc *,
122                                                      caddr_t);
123 
124 /*
125  * Interface to machine independent layer
126  */
127 int cmpci_open(void *, int);
128 void cmpci_close(void *);
129 int cmpci_query_encoding(void *, struct audio_encoding *);
130 int cmpci_set_params(void *, int, int,
131                           struct audio_params *,
132                           struct audio_params *);
133 int cmpci_round_blocksize(void *, int);
134 int cmpci_halt_output(void *);
135 int cmpci_halt_input(void *);
136 int cmpci_getdev(void *, struct audio_device *);
137 int cmpci_set_port(void *, mixer_ctrl_t *);
138 int cmpci_get_port(void *, mixer_ctrl_t *);
139 int cmpci_query_devinfo(void *, mixer_devinfo_t *);
140 void *cmpci_malloc(void *, int, size_t, int, int);
141 void cmpci_free(void *, void *, int);
142 size_t cmpci_round_buffersize(void *, int, size_t);
143 paddr_t cmpci_mappage(void *, void *, off_t, int);
144 int cmpci_get_props(void *);
145 int cmpci_trigger_output(void *, void *, void *, int,
146                          void (*)(void *), void *,
147                          struct audio_params *);
148 int cmpci_trigger_input(void *, void *, void *, int,
149                         void (*)(void *), void *,
150                         struct audio_params *);
151 
152 struct audio_hw_if cmpci_hw_if = {
153 	cmpci_open,			/* open */
154 	cmpci_close,			/* close */
155 	NULL,				/* drain */
156 	cmpci_query_encoding,		/* query_encoding */
157 	cmpci_set_params,		/* set_params */
158 	cmpci_round_blocksize,		/* round_blocksize */
159 	NULL,				/* commit_settings */
160 	NULL,				/* init_output */
161 	NULL,				/* init_input */
162 	NULL,				/* start_output */
163 	NULL,				/* start_input */
164 	cmpci_halt_output,		/* halt_output */
165 	cmpci_halt_input,		/* halt_input */
166 	NULL,				/* speaker_ctl */
167 	cmpci_getdev,			/* getdev */
168 	NULL,				/* setfd */
169 	cmpci_set_port,			/* set_port */
170 	cmpci_get_port,			/* get_port */
171 	cmpci_query_devinfo,		/* query_devinfo */
172 	cmpci_malloc,			/* malloc */
173 	cmpci_free,			/* free */
174 	cmpci_round_buffersize,		/* round_buffersize */
175 	cmpci_mappage,			/* mappage */
176 	cmpci_get_props,		/* get_props */
177 	cmpci_trigger_output,		/* trigger_output */
178 	cmpci_trigger_input		/* trigger_input */
179 };
180 
181 
182 /*
183  * Low-level HW interface
184  */
185 
186 /* mixer register read/write */
187 static __inline uint8_t
188 cmpci_mixerreg_read(sc, no)
189 	struct cmpci_softc *sc;
190 	uint8_t no;
191 {
192 	uint8_t ret;
193 	bus_space_write_1(sc->sc_iot, sc->sc_ioh, CMPCI_REG_SBADDR, no);
194 	delay(10);
195 	ret = bus_space_read_1(sc->sc_iot, sc->sc_ioh, CMPCI_REG_SBDATA);
196 	delay(10);
197 	return ret;
198 }
199 
200 static __inline void
201 cmpci_mixerreg_write(sc, no, val)
202 	struct cmpci_softc *sc;
203 	uint8_t no, val;
204 {
205 	bus_space_write_1(sc->sc_iot, sc->sc_ioh, CMPCI_REG_SBADDR, no);
206 	delay(10);
207 	bus_space_write_1(sc->sc_iot, sc->sc_ioh, CMPCI_REG_SBDATA, val);
208 	delay(10);
209 }
210 
211 /* register partial write */
212 static __inline void
213 cmpci_reg_partial_write_4(sc, no, shift, mask, val)
214 	struct cmpci_softc *sc;
215 	int no, shift;
216 	uint32_t mask, val;
217 {
218 	bus_space_write_4(sc->sc_iot, sc->sc_ioh, no,
219 	    (val<<shift) |
220 	    (bus_space_read_4(sc->sc_iot, sc->sc_ioh, no) & ~(mask<<shift)));
221 	delay(10);
222 }
223 
224 /* register set/clear bit */
225 static __inline void
226 cmpci_reg_set_4(sc, no, mask)
227 	struct cmpci_softc *sc;
228 	int no;
229 	uint32_t mask;
230 {
231 	bus_space_write_4(sc->sc_iot, sc->sc_ioh, no,
232 	    (bus_space_read_4(sc->sc_iot, sc->sc_ioh, no) | mask));
233 	delay(10);
234 }
235 
236 static __inline void
237 cmpci_reg_clear_4(sc, no, mask)
238 	struct cmpci_softc *sc;
239 	int no;
240 	uint32_t mask;
241 {
242 	bus_space_write_4(sc->sc_iot, sc->sc_ioh, no,
243 	    (bus_space_read_4(sc->sc_iot, sc->sc_ioh, no) & ~mask));
244 	delay(10);
245 }
246 
247 
248 /* rate */
249 struct {
250       int rate;
251       int divider;
252 } cmpci_rate_table[CMPCI_REG_NUMRATE] = {
253 #define _RATE(n) { n, CMPCI_REG_RATE_ ## n }
254 	_RATE(5512),
255 	_RATE(8000),
256 	_RATE(11025),
257 	_RATE(16000),
258 	_RATE(22050),
259 	_RATE(32000),
260 	_RATE(44100),
261 	_RATE(48000)
262 #undef  _RATE
263 };
264 
265 int
266 cmpci_rate_to_index(rate)
267 	int rate;
268 {
269 	int i;
270 	for (i=0; i<CMPCI_REG_NUMRATE-2; i++)
271 		if (rate <=
272 		    (cmpci_rate_table[i].rate + cmpci_rate_table[i+1].rate) / 2)
273 			return i;
274 	return i;  /* 48000 */
275 }
276 
277 static __inline int
278 cmpci_index_to_rate(index)
279 	int index;
280 {
281 
282 	return cmpci_rate_table[index].rate;
283 }
284 
285 static __inline int
286 cmpci_index_to_divider(index)
287 	int index;
288 {
289 	return cmpci_rate_table[index].divider;
290 }
291 
292 const struct pci_matchid cmpci_devices[] = {
293 	{ PCI_VENDOR_CMI, PCI_PRODUCT_CMI_CMI8338A },
294 	{ PCI_VENDOR_CMI, PCI_PRODUCT_CMI_CMI8338B },
295 	{ PCI_VENDOR_CMI, PCI_PRODUCT_CMI_CMI8738 },
296 };
297 
298 /*
299  * interface to configure the device.
300  */
301 int
302 cmpci_match(parent, match, aux)
303 	struct device *parent;
304 	void *match;
305 	void *aux;
306 {
307 	return (pci_matchbyid((struct pci_attach_args *)aux, cmpci_devices,
308 	    sizeof(cmpci_devices)/sizeof(cmpci_devices[0])));
309 }
310 
311 void
312 cmpci_attach(parent, self, aux)
313 	struct device *parent, *self;
314 	void *aux;
315 {
316 	struct cmpci_softc *sc = (struct cmpci_softc *)self;
317 	struct pci_attach_args *pa = (struct pci_attach_args *)aux;
318 	pci_intr_handle_t ih;
319 	char const *intrstr;
320 	int i, v;
321 
322 	/* map I/O space */
323 	if (pci_mapreg_map(pa, CMPCI_PCI_IOBASEREG, PCI_MAPREG_TYPE_IO, 0,
324 			   &sc->sc_iot, &sc->sc_ioh, NULL, NULL, 0)) {
325 		printf("\n%s: failed to map I/O space\n", sc->sc_dev.dv_xname);
326 		return;
327 	}
328 
329 	/* interrupt */
330 	if (pci_intr_map(pa, &ih)) {
331 		printf("\n%s: failed to map interrupt\n", sc->sc_dev.dv_xname);
332 		return;
333 	}
334 	intrstr = pci_intr_string(pa->pa_pc, ih);
335 	sc->sc_ih = pci_intr_establish(pa->pa_pc, ih, IPL_AUDIO, cmpci_intr,
336 				       sc, sc->sc_dev.dv_xname);
337 
338 	if (sc->sc_ih == NULL) {
339 		printf("\n%s: couldn't establish interrupt",
340 		    sc->sc_dev.dv_xname);
341 		if (intrstr)
342 			printf(" at %s", intrstr);
343 		printf("\n");
344 		return;
345 	}
346 	printf(": %s\n", intrstr);
347 
348 	sc->sc_dmat = pa->pa_dmat;
349 
350 	audio_attach_mi(&cmpci_hw_if, sc, &sc->sc_dev);
351 
352 	cmpci_mixerreg_write(sc, CMPCI_SB16_MIXER_RESET, 0);
353 	cmpci_mixerreg_write(sc, CMPCI_SB16_MIXER_ADCMIX_L, 0);
354 	cmpci_mixerreg_write(sc, CMPCI_SB16_MIXER_ADCMIX_R, 0);
355 	cmpci_mixerreg_write(sc, CMPCI_SB16_MIXER_OUTMIX,
356 			     CMPCI_SB16_SW_CD|CMPCI_SB16_SW_MIC|
357 			     CMPCI_SB16_SW_LINE);
358 	for (i = 0; i < CMPCI_NDEVS; i++) {
359 		switch(i) {
360 		case CMPCI_MIC_VOL:
361 		case CMPCI_LINE_IN_VOL:
362 			v = 0;
363 			break;
364 		case CMPCI_BASS:
365 		case CMPCI_TREBLE:
366 			v = CMPCI_ADJUST_GAIN(sc, AUDIO_MAX_GAIN / 2);
367 			break;
368 		case CMPCI_CD_IN_MUTE:
369 		case CMPCI_MIC_IN_MUTE:
370 		case CMPCI_LINE_IN_MUTE:
371 		case CMPCI_FM_IN_MUTE:
372 		case CMPCI_CD_SWAP:
373 		case CMPCI_MIC_SWAP:
374 		case CMPCI_LINE_SWAP:
375 		case CMPCI_FM_SWAP:
376 			v = 0;
377 			break;
378 		case CMPCI_CD_OUT_MUTE:
379 		case CMPCI_MIC_OUT_MUTE:
380 		case CMPCI_LINE_OUT_MUTE:
381 			v = 1;
382 			break;
383 		default:
384 			v = CMPCI_ADJUST_GAIN(sc, AUDIO_MAX_GAIN / 2);
385 		}
386 		sc->gain[i][CMPCI_LEFT] = sc->gain[i][CMPCI_RIGHT] = v;
387 		cmpci_set_mixer_gain(sc, i);
388 	}
389 }
390 
391 int
392 cmpci_intr(handle)
393 	void *handle;
394 {
395 	struct cmpci_softc *sc = handle;
396 	uint32_t intrstat;
397 	int s;
398 
399 	intrstat = bus_space_read_4(sc->sc_iot, sc->sc_ioh,
400 	    CMPCI_REG_INTR_STATUS);
401 	delay(10);
402 
403 	if (!(intrstat & CMPCI_REG_ANY_INTR))
404 		return 0;
405 
406 	/* disable and reset intr */
407 	s = splaudio();
408 	if (intrstat & CMPCI_REG_CH0_INTR)
409 		cmpci_reg_clear_4(sc, CMPCI_REG_INTR_CTRL,
410 		    CMPCI_REG_CH0_INTR_ENABLE);
411 	if (intrstat&CMPCI_REG_CH1_INTR)
412 		cmpci_reg_clear_4(sc, CMPCI_REG_INTR_CTRL,
413 		    CMPCI_REG_CH1_INTR_ENABLE);
414 	splx(s);
415 
416 	if (intrstat & CMPCI_REG_CH0_INTR) {
417 		if (sc->sc_play.intr)
418 			(*sc->sc_play.intr)(sc->sc_play.intr_arg);
419 	}
420 	if (intrstat & CMPCI_REG_CH1_INTR) {
421 	    if (sc->sc_rec.intr)
422 		    (*sc->sc_rec.intr)(sc->sc_rec.intr_arg);
423 	}
424 
425 	/* enable intr */
426 	s = splaudio();
427 	if ( intrstat & CMPCI_REG_CH0_INTR )
428 		cmpci_reg_set_4(sc, CMPCI_REG_INTR_CTRL,
429 		    CMPCI_REG_CH0_INTR_ENABLE);
430 	if (intrstat & CMPCI_REG_CH1_INTR)
431 		cmpci_reg_set_4(sc, CMPCI_REG_INTR_CTRL,
432 		    CMPCI_REG_CH1_INTR_ENABLE);
433 	splx(s);
434 
435 	return 1;
436 }
437 
438 /* open/close */
439 int
440 cmpci_open(handle, flags)
441 	void *handle;
442 	int flags;
443 {
444 	struct cmpci_softc *sc = handle;
445 	(void)sc;
446 	(void)flags;
447 
448 	return 0;
449 }
450 
451 void
452 cmpci_close(handle)
453 	void *handle;
454 {
455 	(void)handle;
456 }
457 
458 int
459 cmpci_query_encoding(handle, fp)
460 	void *handle;
461 	struct audio_encoding *fp;
462 {
463 	struct cmpci_softc *sc = handle;
464 	(void)sc;
465 
466 	switch (fp->index) {
467 	case 0:
468 		strlcpy(fp->name, AudioEulinear, sizeof fp->name);
469 		fp->encoding = AUDIO_ENCODING_ULINEAR;
470 		fp->precision = 8;
471 		fp->flags = AUDIO_ENCODINGFLAG_EMULATED;
472 		break;
473 	case 1:
474 		strlcpy(fp->name, AudioEmulaw, sizeof fp->name);
475 		fp->encoding = AUDIO_ENCODING_ULAW;
476 		fp->precision = 8;
477 		fp->flags = AUDIO_ENCODINGFLAG_EMULATED;
478 		break;
479 	case 2:
480 		strlcpy(fp->name, AudioEalaw, sizeof fp->name);
481 		fp->encoding = AUDIO_ENCODING_ALAW;
482 		fp->precision = 8;
483 		fp->flags = AUDIO_ENCODINGFLAG_EMULATED;
484 		break;
485 	case 3:
486 		strlcpy(fp->name, AudioEslinear, sizeof fp->name);
487 		fp->encoding = AUDIO_ENCODING_SLINEAR;
488 		fp->precision = 8;
489 		fp->flags = 0;
490 		break;
491 	case 4:
492 		strlcpy(fp->name, AudioEslinear_le, sizeof fp->name);
493 		fp->encoding = AUDIO_ENCODING_SLINEAR_LE;
494 		fp->precision = 16;
495 		fp->flags = 0;
496 		break;
497 	case 5:
498 		strlcpy(fp->name, AudioEulinear_le, sizeof fp->name);
499 		fp->encoding = AUDIO_ENCODING_ULINEAR_LE;
500 		fp->precision = 16;
501 		fp->flags = AUDIO_ENCODINGFLAG_EMULATED;
502 		break;
503 	case 6:
504 		strlcpy(fp->name, AudioEslinear_be, sizeof fp->name);
505 		fp->encoding = AUDIO_ENCODING_SLINEAR_BE;
506 		fp->precision = 16;
507 		fp->flags = AUDIO_ENCODINGFLAG_EMULATED;
508 		break;
509 	case 7:
510 		strlcpy(fp->name, AudioEulinear_be, sizeof fp->name);
511 		fp->encoding = AUDIO_ENCODING_ULINEAR_BE;
512 		fp->precision = 16;
513 		fp->flags = AUDIO_ENCODINGFLAG_EMULATED;
514 		break;
515 	default:
516 		return EINVAL;
517 	}
518 	return 0;
519 }
520 
521 
522 int
523 cmpci_set_params(handle, setmode, usemode, play, rec)
524 	void *handle;
525 	int setmode, usemode;
526 	struct audio_params *play, *rec;
527 {
528 	int i;
529 	struct cmpci_softc *sc = handle;
530 
531 	for (i=0; i<2; i++) {
532 		int md_format;
533 		int md_divide;
534 		int md_index;
535 		int mode;
536 		struct audio_params *p;
537 
538 		switch (i) {
539 		case 0:
540 			mode = AUMODE_PLAY;
541 			p = play;
542 			break;
543 		case 1:
544 			mode = AUMODE_RECORD;
545 			p = rec;
546 			break;
547 		}
548 
549 		if (!(setmode & mode))
550 			continue;
551 
552 		/* format */
553 		p->sw_code = NULL;
554 		switch (p->channels) {
555 		case 1:
556 			md_format = CMPCI_REG_FORMAT_MONO;
557 			break;
558 		case 2:
559 			md_format = CMPCI_REG_FORMAT_STEREO;
560 			break;
561 		default:
562 			return (EINVAL);
563 		}
564 		switch (p->encoding) {
565 		case AUDIO_ENCODING_ULAW:
566 			if (p->precision != 8)
567 				return (EINVAL);
568 			if (mode & AUMODE_PLAY) {
569 				p->factor = 2;
570 				p->sw_code = mulaw_to_slinear16;
571 				md_format |= CMPCI_REG_FORMAT_16BIT;
572 			} else
573 				p->sw_code = ulinear8_to_mulaw;
574 			md_format |= CMPCI_REG_FORMAT_8BIT;
575 			break;
576 		case AUDIO_ENCODING_ALAW:
577 			if (p->precision != 8)
578 				return (EINVAL);
579 			if (mode & AUMODE_PLAY) {
580 				p->factor = 2;
581 				p->sw_code = alaw_to_slinear16;
582 				md_format |= CMPCI_REG_FORMAT_16BIT;
583 			} else
584 				p->sw_code = ulinear8_to_alaw;
585 			md_format |= CMPCI_REG_FORMAT_8BIT;
586 			break;
587 		case AUDIO_ENCODING_SLINEAR_LE:
588 			switch (p->precision) {
589 			case 8:
590 				p->sw_code = change_sign8;
591 				md_format |= CMPCI_REG_FORMAT_8BIT;
592 				break;
593 			case 16:
594 				md_format |= CMPCI_REG_FORMAT_16BIT;
595 				break;
596 			default:
597 				return (EINVAL);
598 			}
599 			break;
600 		case AUDIO_ENCODING_SLINEAR_BE:
601 			switch (p->precision) {
602 			case 8:
603 				md_format |= CMPCI_REG_FORMAT_8BIT;
604 				p->sw_code = change_sign8;
605 				break;
606 			case 16:
607 				md_format |= CMPCI_REG_FORMAT_16BIT;
608 				p->sw_code = swap_bytes;
609 				break;
610 			default:
611 				return (EINVAL);
612 			}
613 			break;
614 		case AUDIO_ENCODING_ULINEAR_LE:
615 			switch ( p->precision ) {
616 			case 8:
617 				md_format |= CMPCI_REG_FORMAT_8BIT;
618 				break;
619 			case 16:
620 				md_format |= CMPCI_REG_FORMAT_16BIT;
621 				p->sw_code = change_sign16;
622 				break;
623 			default:
624 				return (EINVAL);
625 			}
626 			break;
627 		case AUDIO_ENCODING_ULINEAR_BE:
628 			switch (p->precision) {
629 			case 8:
630 				md_format |= CMPCI_REG_FORMAT_8BIT;
631 				break;
632 			case 16:
633 				md_format |= CMPCI_REG_FORMAT_16BIT;
634 				if ( mode&AUMODE_PLAY )
635 					p->sw_code = swap_bytes_change_sign16;
636 				else
637 					p->sw_code = change_sign16_swap_bytes;
638 				break;
639 			default:
640 				return (EINVAL);
641 			}
642 			break;
643 		default:
644 			return (EINVAL);
645 		}
646 		if (mode & AUMODE_PLAY)
647 			cmpci_reg_partial_write_4(sc,
648 						  CMPCI_REG_CHANNEL_FORMAT,
649 						  CMPCI_REG_CH0_FORMAT_SHIFT,
650 						  CMPCI_REG_CH0_FORMAT_MASK,
651 						  md_format);
652 		else
653 			cmpci_reg_partial_write_4(sc,
654 						  CMPCI_REG_CHANNEL_FORMAT,
655 						  CMPCI_REG_CH1_FORMAT_SHIFT,
656 						  CMPCI_REG_CH1_FORMAT_MASK,
657 						  md_format);
658 		/* sample rate */
659 		md_index = cmpci_rate_to_index(p->sample_rate);
660 		md_divide = cmpci_index_to_divider(md_index);
661 		p->sample_rate = cmpci_index_to_rate(md_index);
662 #if 0
663 		DPRINTF(("%s: sample:%d, divider=%d\n",
664 			 sc->sc_dev.dv_xname, (int)p->sample_rate, md_divide));
665 #endif
666 		if (mode & AUMODE_PLAY) {
667 			cmpci_reg_partial_write_4(sc,
668 						  CMPCI_REG_FUNC_1,
669 						  CMPCI_REG_DAC_FS_SHIFT,
670 						  CMPCI_REG_DAC_FS_MASK,
671 						  md_divide);
672 #ifdef CMPCI_SPDIF_SUPPORT
673 			switch (md_divide) {
674 			case CMPCI_REG_RATE_44100:
675 				cmpci_reg_clear_4(sc, CMPCI_REG_MISC,
676 						  CMPCI_REG_SPDIF_48K);
677 				cmpci_reg_clear_4(sc, CMPCI_REG_FUNC_1,
678 						  CMPCI_REG_SPDIF_LOOP);
679 				cmpci_reg_set_4(sc, CMPCI_REG_FUNC_1,
680 						CMPCI_REG_SPDIF0_ENABLE);
681 				break;
682 			case CMPCI_REG_RATE_48000:
683 				cmpci_reg_set_4(sc, CMPCI_REG_MISC,
684 						CMPCI_REG_SPDIF_48K);
685 				cmpci_reg_clear_4(sc, CMPCI_REG_FUNC_1,
686 						  CMPCI_REG_SPDIF_LOOP);
687 				cmpci_reg_set_4(sc, CMPCI_REG_FUNC_1,
688 						CMPCI_REG_SPDIF0_ENABLE);
689 				break;
690 			default:
691 				cmpci_reg_clear_4(sc, CMPCI_REG_FUNC_1,
692 						  CMPCI_REG_SPDIF0_ENABLE);
693 			    cmpci_reg_set_4(sc, CMPCI_REG_FUNC_1,
694 					    CMPCI_REG_SPDIF_LOOP);
695 			}
696 #endif
697 		} else {
698 			cmpci_reg_partial_write_4(sc,
699 						  CMPCI_REG_FUNC_1,
700 						  CMPCI_REG_ADC_FS_SHIFT,
701 						  CMPCI_REG_ADC_FS_MASK,
702 						  md_divide);
703 #ifdef CMPCI_SPDIF_SUPPORT
704 			if ( sc->in_mask&CMPCI_SPDIF_IN) {
705 				switch (md_divide) {
706 				case CMPCI_REG_RATE_44100:
707 					cmpci_reg_set_4(sc, CMPCI_REG_FUNC_1,
708 							CMPCI_REG_SPDIF1_ENABLE);
709 					break;
710 				default:
711 					return EINVAL;
712 				}
713 			} else
714 				cmpci_reg_clear_4(sc, CMPCI_REG_FUNC_1,
715 						  CMPCI_REG_SPDIF1_ENABLE);
716 #endif
717 		}
718 	}
719 	return 0;
720 }
721 
722 /* ARGSUSED */
723 int
724 cmpci_round_blocksize(handle, block)
725 	void *handle;
726 	int block;
727 {
728 	return (block & -4);
729 }
730 
731 int
732 cmpci_halt_output(handle)
733 	void *handle;
734 {
735 	struct cmpci_softc *sc = handle;
736 	int s;
737 
738 	s = splaudio();
739 	sc->sc_play.intr = NULL;
740 	cmpci_reg_clear_4(sc, CMPCI_REG_INTR_CTRL, CMPCI_REG_CH0_INTR_ENABLE);
741 	cmpci_reg_clear_4(sc, CMPCI_REG_FUNC_0, CMPCI_REG_CH0_ENABLE);
742 	/* wait for reset DMA */
743 	cmpci_reg_set_4(sc, CMPCI_REG_FUNC_0, CMPCI_REG_CH0_RESET);
744 	delay(10);
745 	cmpci_reg_clear_4(sc, CMPCI_REG_FUNC_0, CMPCI_REG_CH0_RESET);
746 	splx(s);
747 
748 	return 0;
749 }
750 
751 int
752 cmpci_halt_input(handle)
753 	void *handle;
754 {
755 	struct cmpci_softc *sc = handle;
756 	int s;
757 
758 	s = splaudio();
759 	sc->sc_rec.intr = NULL;
760 	cmpci_reg_clear_4(sc, CMPCI_REG_INTR_CTRL, CMPCI_REG_CH1_INTR_ENABLE);
761 	cmpci_reg_clear_4(sc, CMPCI_REG_FUNC_0, CMPCI_REG_CH1_ENABLE);
762 	/* wait for reset DMA */
763 	cmpci_reg_set_4(sc, CMPCI_REG_FUNC_0, CMPCI_REG_CH1_RESET);
764 	delay(10);
765 	cmpci_reg_clear_4(sc, CMPCI_REG_FUNC_0, CMPCI_REG_CH1_RESET);
766 	splx(s);
767 
768 	return 0;
769 }
770 
771 int
772 cmpci_getdev(handle, retp)
773         void *handle;
774         struct audio_device *retp;
775 {
776 	*retp = cmpci_device;
777 	return 0;
778 }
779 
780 
781 /* mixer device information */
782 int
783 cmpci_query_devinfo(handle, dip)
784 	void *handle;
785 	mixer_devinfo_t *dip;
786 {
787 	struct cmpci_softc *sc = handle;
788 	(void)sc;
789 
790 	switch (dip->index) {
791 	case CMPCI_MASTER_VOL:
792 		dip->type = AUDIO_MIXER_VALUE;
793 		dip->mixer_class = CMPCI_OUTPUT_CLASS;
794 		dip->prev = dip->next = AUDIO_MIXER_LAST;
795 		strlcpy(dip->label.name, AudioNmaster, sizeof dip->label.name);
796 		dip->un.v.num_channels = 2;
797 		strlcpy(dip->un.v.units.name, AudioNvolume,
798 		    sizeof dip->un.v.units.name);
799 		return 0;
800 	case CMPCI_FM_VOL:
801 		dip->type = AUDIO_MIXER_VALUE;
802 		dip->mixer_class = CMPCI_INPUT_CLASS;
803 		dip->prev = AUDIO_MIXER_LAST;
804 		dip->next = CMPCI_FM_IN_MUTE;
805 		strlcpy(dip->label.name, AudioNfmsynth,
806 		    sizeof dip->label.name);
807 		dip->un.v.num_channels = 2;
808 		strlcpy(dip->un.v.units.name, AudioNvolume,
809 		    sizeof dip->un.v.units.name);
810 		return 0;
811 	case CMPCI_CD_VOL:
812 		dip->type = AUDIO_MIXER_VALUE;
813 		dip->mixer_class = CMPCI_INPUT_CLASS;
814 		dip->prev = AUDIO_MIXER_LAST;
815 		dip->next = CMPCI_CD_IN_MUTE;
816 		strlcpy(dip->label.name, AudioNcd, sizeof dip->label.name);
817 		dip->un.v.num_channels = 2;
818 		strlcpy(dip->un.v.units.name, AudioNvolume,
819 		    sizeof dip->un.v.units.name);
820 		return 0;
821 	case CMPCI_VOICE_VOL:
822 		dip->type = AUDIO_MIXER_VALUE;
823 		dip->mixer_class = CMPCI_OUTPUT_CLASS;
824 		dip->prev = AUDIO_MIXER_LAST;
825 		dip->next = AUDIO_MIXER_LAST;
826 		strlcpy(dip->label.name, AudioNdac, sizeof dip->label.name);
827 		dip->un.v.num_channels = 2;
828 		strlcpy(dip->un.v.units.name, AudioNvolume,
829 		    sizeof dip->un.v.units.name);
830 		return 0;
831 	case CMPCI_OUTPUT_CLASS:
832 		dip->type = AUDIO_MIXER_CLASS;
833 		dip->mixer_class = CMPCI_OUTPUT_CLASS;
834 		dip->next = dip->prev = AUDIO_MIXER_LAST;
835 		strlcpy(dip->label.name, AudioCoutputs,
836 		    sizeof dip->label.name);
837 		return 0;
838 	case CMPCI_MIC_VOL:
839 		dip->type = AUDIO_MIXER_VALUE;
840 		dip->mixer_class = CMPCI_INPUT_CLASS;
841 		dip->prev = AUDIO_MIXER_LAST;
842 		dip->next = CMPCI_MIC_IN_MUTE;
843 		strlcpy(dip->label.name, AudioNmicrophone,
844 		    sizeof dip->label.name);
845 		dip->un.v.num_channels = 1;
846 		strlcpy(dip->un.v.units.name, AudioNvolume,
847 		    sizeof dip->un.v.units.name);
848 		return 0;
849 	case CMPCI_LINE_IN_VOL:
850 		dip->type = AUDIO_MIXER_VALUE;
851 		dip->mixer_class = CMPCI_INPUT_CLASS;
852 		dip->prev = AUDIO_MIXER_LAST;
853 		dip->next = CMPCI_LINE_IN_MUTE;
854 		strlcpy(dip->label.name, AudioNline, sizeof dip->label.name);
855 		dip->un.v.num_channels = 2;
856 		strlcpy(dip->un.v.units.name, AudioNvolume,
857 		    sizeof dip->un.v.units.name);
858 		return 0;
859 	case CMPCI_RECORD_SOURCE:
860 		dip->mixer_class = CMPCI_RECORD_CLASS;
861 		dip->prev = dip->next = AUDIO_MIXER_LAST;
862 		strlcpy(dip->label.name, AudioNsource, sizeof dip->label.name);
863 		dip->type = AUDIO_MIXER_SET;
864 #ifdef CMPCI_SPDIF_SUPPORT
865 		dip->un.s.num_mem = 5;
866 #else
867 		dip->un.s.num_mem = 4;
868 #endif
869 		strlcpy(dip->un.s.member[0].label.name, AudioNmicrophone,
870 		    sizeof dip->un.s.member[0].label.name);
871 		dip->un.s.member[0].mask = 1 << CMPCI_MIC_VOL;
872 		strlcpy(dip->un.s.member[1].label.name, AudioNcd,
873 		    sizeof dip->un.s.member[1].label.name);
874 		dip->un.s.member[1].mask = 1 << CMPCI_CD_VOL;
875 		strlcpy(dip->un.s.member[2].label.name, AudioNline,
876 		    sizeof dip->un.s.member[2].label.name);
877 		dip->un.s.member[2].mask = 1 << CMPCI_LINE_IN_VOL;
878 		strlcpy(dip->un.s.member[3].label.name, AudioNfmsynth,
879 		    sizeof dip->un.s.member[3].label.name);
880 		dip->un.s.member[3].mask = 1 << CMPCI_FM_VOL;
881 #ifdef CMPCI_SPDIF_SUPPORT
882 		strlcpy(dip->un.s.member[4].label.name, CmpciNspdif,
883 		    sizeof dip->un.s.member[4].label.name);
884 		dip->un.s.member[4].mask = 1 << CMPCI_SPDIF_IN;
885 #endif
886 		return 0;
887 	case CMPCI_BASS:
888 		dip->prev = dip->next = AUDIO_MIXER_LAST;
889 		strlcpy(dip->label.name, AudioNbass, sizeof dip->label.name);
890 		dip->type = AUDIO_MIXER_VALUE;
891 		dip->mixer_class = CMPCI_EQUALIZATION_CLASS;
892 		dip->un.v.num_channels = 2;
893 		strlcpy(dip->un.v.units.name, AudioNbass,
894 		    sizeof dip->un.v.units.name);
895 		return 0;
896 	case CMPCI_TREBLE:
897 		dip->prev = dip->next = AUDIO_MIXER_LAST;
898 		strlcpy(dip->label.name, AudioNtreble, sizeof dip->label.name);
899 		dip->type = AUDIO_MIXER_VALUE;
900 		dip->mixer_class = CMPCI_EQUALIZATION_CLASS;
901 		dip->un.v.num_channels = 2;
902 		strlcpy(dip->un.v.units.name, AudioNtreble,
903 		    sizeof dip->un.v.units.name);
904 		return 0;
905 	case CMPCI_RECORD_CLASS:
906 		dip->type = AUDIO_MIXER_CLASS;
907 		dip->mixer_class = CMPCI_RECORD_CLASS;
908 		dip->next = dip->prev = AUDIO_MIXER_LAST;
909 		strlcpy(dip->label.name, AudioCrecord,
910 		    sizeof dip->label.name);
911 		return 0;
912 	case CMPCI_INPUT_CLASS:
913 		dip->type = AUDIO_MIXER_CLASS;
914 		dip->mixer_class = CMPCI_INPUT_CLASS;
915 		dip->next = dip->prev = AUDIO_MIXER_LAST;
916 		strlcpy(dip->label.name, AudioCinputs,
917 		    sizeof dip->label.name);
918 		return 0;
919 	case CMPCI_PCSPEAKER:
920 		dip->type = AUDIO_MIXER_VALUE;
921 		dip->mixer_class = CMPCI_INPUT_CLASS;
922 		dip->prev = dip->next = AUDIO_MIXER_LAST;
923 		strlcpy(dip->label.name, "pc_speaker", sizeof dip->label.name);
924 		dip->un.v.num_channels = 1;
925 		strlcpy(dip->un.v.units.name, AudioNvolume,
926 		    sizeof dip->un.v.units.name);
927 		return 0;
928 	case CMPCI_INPUT_GAIN:
929 		dip->type = AUDIO_MIXER_VALUE;
930 		dip->mixer_class = CMPCI_INPUT_CLASS;
931 		dip->prev = dip->next = AUDIO_MIXER_LAST;
932 		strlcpy(dip->label.name, AudioNinput,
933 		    sizeof dip->label.name);
934 		dip->un.v.num_channels = 2;
935 		strlcpy(dip->un.v.units.name, AudioNvolume,
936 		    sizeof dip->un.v.units.name);
937 		return 0;
938 	case CMPCI_OUTPUT_GAIN:
939 		dip->type = AUDIO_MIXER_VALUE;
940 		dip->mixer_class = CMPCI_OUTPUT_CLASS;
941 		dip->prev = dip->next = AUDIO_MIXER_LAST;
942 		strlcpy(dip->label.name, AudioNoutput, sizeof dip->label.name);
943 		dip->un.v.num_channels = 2;
944 		strlcpy(dip->un.v.units.name, AudioNvolume,
945 		    sizeof dip->un.v.units.name);
946 		return 0;
947 	case CMPCI_AGC:
948 		dip->type = AUDIO_MIXER_ENUM;
949 		dip->mixer_class = CMPCI_INPUT_CLASS;
950 		dip->prev = dip->next = AUDIO_MIXER_LAST;
951 		strlcpy(dip->label.name, "agc", sizeof dip->label.name);
952 		dip->un.e.num_mem = 2;
953 		strlcpy(dip->un.e.member[0].label.name, AudioNoff,
954 		    sizeof dip->un.e.member[0].label.name);
955 		dip->un.e.member[0].ord = 0;
956 		strlcpy(dip->un.e.member[1].label.name, AudioNon,
957 		    sizeof dip->un.e.member[1].label.name);
958 		dip->un.e.member[1].ord = 1;
959 		return 0;
960 	case CMPCI_EQUALIZATION_CLASS:
961 		dip->type = AUDIO_MIXER_CLASS;
962 		dip->mixer_class = CMPCI_EQUALIZATION_CLASS;
963 		dip->next = dip->prev = AUDIO_MIXER_LAST;
964 		strlcpy(dip->label.name, AudioCequalization,
965 		    sizeof dip->label.name);
966 		return 0;
967 	case CMPCI_CD_IN_MUTE:
968 		dip->prev = CMPCI_CD_VOL;
969 		dip->next = CMPCI_CD_SWAP;
970 		dip->mixer_class = CMPCI_INPUT_CLASS;
971 		goto mute;
972 	case CMPCI_MIC_IN_MUTE:
973 		dip->prev = CMPCI_MIC_VOL;
974 		dip->next = CMPCI_MIC_SWAP;
975 		dip->mixer_class = CMPCI_INPUT_CLASS;
976 		goto mute;
977 	case CMPCI_LINE_IN_MUTE:
978 		dip->prev = CMPCI_LINE_IN_VOL;
979 		dip->next = CMPCI_LINE_SWAP;
980 		dip->mixer_class = CMPCI_INPUT_CLASS;
981 		goto mute;
982 	case CMPCI_FM_IN_MUTE:
983 		dip->prev = CMPCI_FM_VOL;
984 		dip->next = CMPCI_FM_SWAP;
985 		dip->mixer_class = CMPCI_INPUT_CLASS;
986 		goto mute;
987 	case CMPCI_CD_SWAP:
988 		dip->prev = CMPCI_CD_IN_MUTE;
989 		dip->next = CMPCI_CD_OUT_MUTE;
990 		goto swap;
991 	case CMPCI_MIC_SWAP:
992 		dip->prev = CMPCI_MIC_IN_MUTE;
993 		dip->next = CMPCI_MIC_OUT_MUTE;
994 		goto swap;
995 	case CMPCI_LINE_SWAP:
996 		dip->prev = CMPCI_LINE_IN_MUTE;
997 		dip->next = CMPCI_LINE_OUT_MUTE;
998 		goto swap;
999 	case CMPCI_FM_SWAP:
1000 		dip->prev = CMPCI_FM_IN_MUTE;
1001 		dip->next = AUDIO_MIXER_LAST;
1002 	swap:
1003 		dip->mixer_class = CMPCI_INPUT_CLASS;
1004 		strlcpy(dip->label.name, AudioNswap, sizeof dip->label.name);
1005 		goto mute1;
1006 	case CMPCI_CD_OUT_MUTE:
1007 		dip->prev = CMPCI_CD_SWAP;
1008 		dip->next = AUDIO_MIXER_LAST;
1009 		dip->mixer_class = CMPCI_OUTPUT_CLASS;
1010 		goto mute;
1011 	case CMPCI_MIC_OUT_MUTE:
1012 		dip->prev = CMPCI_MIC_SWAP;
1013 		dip->next = AUDIO_MIXER_LAST;
1014 		dip->mixer_class = CMPCI_OUTPUT_CLASS;
1015 		goto mute;
1016 	case CMPCI_LINE_OUT_MUTE:
1017 		dip->prev = CMPCI_LINE_SWAP;
1018 		dip->next = AUDIO_MIXER_LAST;
1019 		dip->mixer_class = CMPCI_OUTPUT_CLASS;
1020 	mute:
1021 		strlcpy(dip->label.name, AudioNmute, sizeof dip->label.name);
1022 	mute1:
1023 		dip->type = AUDIO_MIXER_ENUM;
1024 		dip->un.e.num_mem = 2;
1025 		strlcpy(dip->un.e.member[0].label.name, AudioNoff,
1026 		    sizeof dip->un.e.member[0].label.name);
1027 		dip->un.e.member[0].ord = 0;
1028 		strlcpy(dip->un.e.member[1].label.name, AudioNon,
1029 		    sizeof dip->un.e.member[1].label.name);
1030 		dip->un.e.member[1].ord = 1;
1031 		return 0;
1032 	}
1033 
1034 	return ENXIO;
1035 }
1036 
1037 int
1038 cmpci_alloc_dmamem(sc, size, type, flags, r_addr)
1039 	struct cmpci_softc *sc;
1040 	size_t size;
1041 	int type, flags;
1042 	caddr_t *r_addr;
1043 {
1044 	int ret = 0;
1045 	struct cmpci_dmanode *n;
1046 	int w;
1047 
1048 	if ( NULL == (n=malloc(sizeof(struct cmpci_dmanode), type, flags)) ) {
1049 		ret = ENOMEM;
1050 		goto quit;
1051 	}
1052 
1053 	w = (flags & M_NOWAIT) ? BUS_DMA_NOWAIT : BUS_DMA_WAITOK;
1054 #define CMPCI_DMABUF_ALIGN    0x4
1055 #define CMPCI_DMABUF_BOUNDARY 0x0
1056 	n->cd_tag = sc->sc_dmat;
1057 	n->cd_size = size;
1058 	if ( (ret=bus_dmamem_alloc(n->cd_tag, n->cd_size,
1059 				   CMPCI_DMABUF_ALIGN, CMPCI_DMABUF_BOUNDARY,
1060 				   n->cd_segs,
1061 				   sizeof(n->cd_segs)/sizeof(n->cd_segs[0]),
1062 				   &n->cd_nsegs, w)) )
1063 		goto mfree;
1064 	if ( (ret=bus_dmamem_map(n->cd_tag, n->cd_segs, n->cd_nsegs, n->cd_size,
1065 				 &n->cd_addr, w | BUS_DMA_COHERENT)) )
1066 		goto dmafree;
1067 	if ( (ret=bus_dmamap_create(n->cd_tag, n->cd_size, 1, n->cd_size, 0,
1068 				    w, &n->cd_map)) )
1069 		goto unmap;
1070 	if ( (ret=bus_dmamap_load(n->cd_tag, n->cd_map, n->cd_addr, n->cd_size,
1071 				  NULL, w)) )
1072 		goto destroy;
1073 
1074 	n->cd_next = sc->sc_dmap;
1075 	sc->sc_dmap = n;
1076 	*r_addr = KVADDR(n);
1077 	return 0;
1078 
1079 destroy:
1080 	bus_dmamap_destroy(n->cd_tag, n->cd_map);
1081 unmap:
1082 	bus_dmamem_unmap(n->cd_tag, n->cd_addr, n->cd_size);
1083 dmafree:
1084 	bus_dmamem_free(n->cd_tag,
1085 			n->cd_segs, sizeof(n->cd_segs)/sizeof(n->cd_segs[0]));
1086 mfree:
1087 	free(n, type);
1088 quit:
1089 	return ret;
1090 }
1091 
1092 int
1093 cmpci_free_dmamem(sc, addr, type)
1094 	struct cmpci_softc *sc;
1095 	caddr_t addr;
1096 	int type;
1097 {
1098     struct cmpci_dmanode **nnp;
1099 
1100 	for (nnp = &sc->sc_dmap; *nnp; nnp = &(*nnp)->cd_next) {
1101 		if ((*nnp)->cd_addr == addr) {
1102 			struct cmpci_dmanode *n = *nnp;
1103 
1104 			bus_dmamap_unload(n->cd_tag, n->cd_map);
1105 			bus_dmamap_destroy(n->cd_tag, n->cd_map);
1106 			bus_dmamem_unmap(n->cd_tag, n->cd_addr, n->cd_size);
1107 			bus_dmamem_free(n->cd_tag, n->cd_segs,
1108 			    sizeof(n->cd_segs)/sizeof(n->cd_segs[0]));
1109 			free(n, type);
1110 			return 0;
1111 		}
1112 	}
1113 	return -1;
1114 }
1115 
1116 struct cmpci_dmanode *
1117 cmpci_find_dmamem(sc, addr)
1118 	struct cmpci_softc *sc;
1119 	caddr_t addr;
1120 {
1121 	struct cmpci_dmanode *p;
1122 	for (p = sc->sc_dmap; p; p = p->cd_next) {
1123 		if (KVADDR(p) == (void *)addr)
1124 			break;
1125 	}
1126 	return p;
1127 }
1128 
1129 #if 0
1130 void
1131 cmpci_print_dmamem(struct cmpci_dmanode *p);
1132 void
1133 cmpci_print_dmamem(p)
1134 	struct cmpci_dmanode *p;
1135 {
1136 	DPRINTF(("DMA at virt:%p, dmaseg:%p, mapseg:%p, size:%p\n",
1137 		 (void *)p->cd_addr, (void *)p->cd_segs[0].ds_addr,
1138 		 (void *)DMAADDR(p), (void *)p->cd_size));
1139 }
1140 #endif /* DEBUG */
1141 
1142 void *
1143 cmpci_malloc(handle, direction, size, type, flags)
1144 	void  *handle;
1145 	int direction;
1146 	size_t size;
1147 	int    type, flags;
1148 {
1149 	struct cmpci_softc *sc = handle;
1150 	caddr_t addr;
1151 
1152 	if ( cmpci_alloc_dmamem(sc, size, type, flags, &addr) )
1153 		return NULL;
1154 	return addr;
1155 }
1156 
1157 void
1158 cmpci_free(handle, addr, type)
1159 	void    *handle;
1160 	void    *addr;
1161 	int     type;
1162 {
1163 	struct cmpci_softc *sc = handle;
1164 
1165 	cmpci_free_dmamem(sc, addr, type);
1166 }
1167 
1168 #define MAXVAL 256
1169 int
1170 cmpci_adjust(val, mask)
1171     int val, mask;
1172 {
1173 	val += (MAXVAL - mask) >> 1;
1174 	if (val >= MAXVAL)
1175 		val = MAXVAL-1;
1176 	return val & mask;
1177 }
1178 
1179 void
1180 cmpci_set_mixer_gain(sc, port)
1181 	struct cmpci_softc *sc;
1182 	int port;
1183 {
1184 	int src;
1185 
1186 	switch (port) {
1187 	case CMPCI_MIC_VOL:
1188 		src = CMPCI_SB16_MIXER_MIC;
1189 		break;
1190 	case CMPCI_MASTER_VOL:
1191 		src = CMPCI_SB16_MIXER_MASTER_L;
1192 		break;
1193 	case CMPCI_LINE_IN_VOL:
1194 		src = CMPCI_SB16_MIXER_LINE_L;
1195 		break;
1196 	case CMPCI_VOICE_VOL:
1197 		src = CMPCI_SB16_MIXER_VOICE_L;
1198 		break;
1199 	case CMPCI_FM_VOL:
1200 		src = CMPCI_SB16_MIXER_FM_L;
1201 		break;
1202 	case CMPCI_CD_VOL:
1203 		src = CMPCI_SB16_MIXER_CDDA_L;
1204 		break;
1205 	case CMPCI_INPUT_GAIN:
1206 		src = CMPCI_SB16_MIXER_INGAIN_L;
1207 		break;
1208 	case CMPCI_OUTPUT_GAIN:
1209 		src = CMPCI_SB16_MIXER_OUTGAIN_L;
1210 		break;
1211 	case CMPCI_TREBLE:
1212 		src = CMPCI_SB16_MIXER_TREBLE_L;
1213 		break;
1214 	case CMPCI_BASS:
1215 		src = CMPCI_SB16_MIXER_BASS_L;
1216 		break;
1217 	case CMPCI_PCSPEAKER:
1218 		cmpci_mixerreg_write(sc, CMPCI_SB16_MIXER_SPEAKER,
1219 				     sc->gain[port][CMPCI_LEFT]);
1220 		return;
1221 	default:
1222 		return;
1223 	}
1224 	cmpci_mixerreg_write(sc, src, sc->gain[port][CMPCI_LEFT]);
1225 	cmpci_mixerreg_write(sc, CMPCI_SB16_MIXER_L_TO_R(src),
1226 			     sc->gain[port][CMPCI_RIGHT]);
1227 }
1228 
1229 int
1230 cmpci_set_in_ports(sc, mask)
1231 	struct cmpci_softc *sc;
1232 	int mask;
1233 {
1234 	int bitsl, bitsr;
1235 
1236 	if (mask & ~((1<<CMPCI_FM_VOL) | (1<<CMPCI_LINE_IN_VOL) |
1237 		     (1<<CMPCI_CD_VOL) | (1<<CMPCI_MIC_VOL)
1238 #ifdef CMPCI_SPDIF_SUPPORT
1239 		     | (1<<CMPCI_SPDIF_IN)
1240 #endif
1241 		     ))
1242 		return EINVAL;
1243 	bitsr = 0;
1244 	if (mask & (1<<CMPCI_FM_VOL))
1245 		bitsr |= CMPCI_SB16_MIXER_FM_SRC_R;
1246 	if (mask & (1<<CMPCI_LINE_IN_VOL))
1247 		bitsr |= CMPCI_SB16_MIXER_LINE_SRC_R;
1248 	if (mask & (1<<CMPCI_CD_VOL))
1249 		bitsr |= CMPCI_SB16_MIXER_CD_SRC_R;
1250 	bitsl = CMPCI_SB16_MIXER_SRC_R_TO_L(bitsr);
1251 	if (mask & (1<<CMPCI_MIC_VOL)) {
1252 		bitsl |= CMPCI_SB16_MIXER_MIC_SRC;
1253 		bitsr |= CMPCI_SB16_MIXER_MIC_SRC;
1254 	}
1255 	cmpci_mixerreg_write(sc, CMPCI_SB16_MIXER_ADCMIX_L, bitsl);
1256 	cmpci_mixerreg_write(sc, CMPCI_SB16_MIXER_ADCMIX_R, bitsr);
1257 
1258 	sc->in_mask = mask;
1259 
1260 	return 0;
1261 }
1262 
1263 int
1264 cmpci_set_port(handle, cp)
1265 	void *handle;
1266 	mixer_ctrl_t *cp;
1267 {
1268 	struct cmpci_softc *sc = handle;
1269 	int lgain, rgain;
1270 	int mask, bits;
1271 	int lmask, rmask, lbits, rbits;
1272 	int mute, swap;
1273 
1274 	switch (cp->dev) {
1275 	case CMPCI_TREBLE:
1276 	case CMPCI_BASS:
1277 	case CMPCI_PCSPEAKER:
1278 	case CMPCI_INPUT_GAIN:
1279 	case CMPCI_OUTPUT_GAIN:
1280 	case CMPCI_MIC_VOL:
1281 	case CMPCI_LINE_IN_VOL:
1282 	case CMPCI_VOICE_VOL:
1283 	case CMPCI_FM_VOL:
1284 	case CMPCI_CD_VOL:
1285 	case CMPCI_MASTER_VOL:
1286 		if (cp->type != AUDIO_MIXER_VALUE)
1287 			return EINVAL;
1288 		switch (cp->dev) {
1289 		case CMPCI_MIC_VOL:
1290 			if (cp->un.value.num_channels != 1)
1291 				return EINVAL;
1292 
1293 			lgain = rgain = CMPCI_ADJUST_MIC_GAIN(sc,
1294 			    cp->un.value.level[AUDIO_MIXER_LEVEL_MONO]);
1295 			break;
1296 		case CMPCI_PCSPEAKER:
1297 			if (cp->un.value.num_channels != 1)
1298 			    return EINVAL;
1299 			/* FALLTHROUGH */
1300 		case CMPCI_INPUT_GAIN:
1301 		case CMPCI_OUTPUT_GAIN:
1302 			lgain = rgain = CMPCI_ADJUST_2_GAIN(sc,
1303 			    cp->un.value.level[AUDIO_MIXER_LEVEL_MONO]);
1304 			break;
1305 		default:
1306 			switch (cp->un.value.num_channels) {
1307 			case 1:
1308 				lgain = rgain = CMPCI_ADJUST_GAIN(sc,
1309 				    cp->un.value.level[AUDIO_MIXER_LEVEL_MONO]);
1310 				break;
1311 			case 2:
1312 				lgain = CMPCI_ADJUST_GAIN(sc,
1313 				    cp->un.value.level[AUDIO_MIXER_LEVEL_LEFT]);
1314 				rgain = CMPCI_ADJUST_GAIN(sc,
1315 				    cp->un.value.level[AUDIO_MIXER_LEVEL_RIGHT]);
1316 				break;
1317 			default:
1318 				return EINVAL;
1319 			}
1320 			break;
1321 		}
1322 		sc->gain[cp->dev][CMPCI_LEFT]  = lgain;
1323 		sc->gain[cp->dev][CMPCI_RIGHT] = rgain;
1324 
1325 		cmpci_set_mixer_gain(sc, cp->dev);
1326 		break;
1327 
1328 	case CMPCI_RECORD_SOURCE:
1329 		if (cp->type != AUDIO_MIXER_SET)
1330 			return EINVAL;
1331 #ifdef CMPCI_SPDIF_SUPPORT
1332 		if ( cp->un.mask&(1<<CMPCI_SPDIF_IN) )
1333 			cp->un.mask = 1<<CMPCI_SPDIF_IN;
1334 #endif
1335 		return cmpci_set_in_ports(sc, cp->un.mask);
1336 
1337 	case CMPCI_AGC:
1338 		cmpci_mixerreg_write(sc, CMPCI_SB16_MIXER_AGC, cp->un.ord & 1);
1339 		break;
1340 	case CMPCI_CD_OUT_MUTE:
1341 		mask = CMPCI_SB16_SW_CD;
1342 		goto omute;
1343 	case CMPCI_MIC_OUT_MUTE:
1344 		mask = CMPCI_SB16_SW_MIC;
1345 		goto omute;
1346 	case CMPCI_LINE_OUT_MUTE:
1347 		mask = CMPCI_SB16_SW_LINE;
1348 	omute:
1349 		if (cp->type != AUDIO_MIXER_ENUM)
1350 			return EINVAL;
1351 		bits = cmpci_mixerreg_read(sc, CMPCI_SB16_MIXER_OUTMIX);
1352 		sc->gain[cp->dev][CMPCI_LR] = cp->un.ord != 0;
1353 		if (cp->un.ord)
1354 			bits = bits & ~mask;
1355 		else
1356 			bits = bits | mask;
1357 		cmpci_mixerreg_write(sc, CMPCI_SB16_MIXER_OUTMIX, bits);
1358 		break;
1359 
1360 	case CMPCI_MIC_IN_MUTE:
1361 	case CMPCI_MIC_SWAP:
1362 		lmask = rmask = CMPCI_SB16_SW_MIC;
1363 		goto imute;
1364 	case CMPCI_CD_IN_MUTE:
1365 	case CMPCI_CD_SWAP:
1366 		lmask = CMPCI_SB16_SW_CD_L;
1367 		rmask = CMPCI_SB16_SW_CD_R;
1368 		goto imute;
1369 	case CMPCI_LINE_IN_MUTE:
1370 	case CMPCI_LINE_SWAP:
1371 		lmask = CMPCI_SB16_SW_LINE_L;
1372 		rmask = CMPCI_SB16_SW_LINE_R;
1373 		goto imute;
1374 	case CMPCI_FM_IN_MUTE:
1375 	case CMPCI_FM_SWAP:
1376 		lmask = CMPCI_SB16_SW_FM_L;
1377 		rmask = CMPCI_SB16_SW_FM_R;
1378 	imute:
1379 		if (cp->type != AUDIO_MIXER_ENUM)
1380 			return EINVAL;
1381 		mask = lmask | rmask;
1382 		lbits = cmpci_mixerreg_read(sc, CMPCI_SB16_MIXER_ADCMIX_L)
1383 		    & ~mask;
1384 		rbits = cmpci_mixerreg_read(sc, CMPCI_SB16_MIXER_ADCMIX_R)
1385 		    & ~mask;
1386 		sc->gain[cp->dev][CMPCI_LR] = cp->un.ord != 0;
1387 		if (CMPCI_IS_IN_MUTE(cp->dev)) {
1388 			mute = cp->dev;
1389 			swap = mute - CMPCI_CD_IN_MUTE + CMPCI_CD_SWAP;
1390 		} else {
1391 			swap = cp->dev;
1392 			mute = swap + CMPCI_CD_IN_MUTE - CMPCI_CD_SWAP;
1393 		}
1394 		if (sc->gain[swap][CMPCI_LR]) {
1395 			mask = lmask;
1396 			lmask = rmask;
1397 			rmask = mask;
1398 		}
1399 		if (!sc->gain[mute][CMPCI_LR]) {
1400 			lbits = lbits | lmask;
1401 			rbits = rbits | rmask;
1402 		}
1403 		cmpci_mixerreg_write(sc, CMPCI_SB16_MIXER_ADCMIX_L, lbits);
1404 		cmpci_mixerreg_write(sc, CMPCI_SB16_MIXER_ADCMIX_R, rbits);
1405 		break;
1406 
1407 	default:
1408 		return EINVAL;
1409 	}
1410 
1411 	return 0;
1412 }
1413 
1414 int
1415 cmpci_get_port(handle, cp)
1416 	void *handle;
1417 	mixer_ctrl_t *cp;
1418 {
1419 	struct cmpci_softc *sc = handle;
1420 
1421 	switch (cp->dev) {
1422 	case CMPCI_MIC_VOL:
1423 	case CMPCI_LINE_IN_VOL:
1424 		if (cp->un.value.num_channels != 1)
1425 		    return EINVAL;
1426 		/* FALLTHROUGH */
1427 	case CMPCI_TREBLE:
1428 	case CMPCI_BASS:
1429 	case CMPCI_PCSPEAKER:
1430 	case CMPCI_INPUT_GAIN:
1431 	case CMPCI_OUTPUT_GAIN:
1432 	case CMPCI_VOICE_VOL:
1433 	case CMPCI_FM_VOL:
1434 	case CMPCI_CD_VOL:
1435 	case CMPCI_MASTER_VOL:
1436 		switch (cp->un.value.num_channels) {
1437 		case 1:
1438 			cp->un.value.level[AUDIO_MIXER_LEVEL_MONO] =
1439 			    sc->gain[cp->dev][CMPCI_LEFT];
1440 			break;
1441 		case 2:
1442 			cp->un.value.level[AUDIO_MIXER_LEVEL_LEFT] =
1443 			    sc->gain[cp->dev][CMPCI_LEFT];
1444 			cp->un.value.level[AUDIO_MIXER_LEVEL_RIGHT] =
1445 			    sc->gain[cp->dev][CMPCI_RIGHT];
1446 			break;
1447 		default:
1448 			return EINVAL;
1449 		}
1450 		break;
1451 
1452 	case CMPCI_RECORD_SOURCE:
1453 		cp->un.mask = sc->in_mask;
1454 		break;
1455 
1456 	case CMPCI_AGC:
1457 		cp->un.ord = cmpci_mixerreg_read(sc, CMPCI_SB16_MIXER_AGC);
1458 		break;
1459 
1460 	case CMPCI_CD_IN_MUTE:
1461 	case CMPCI_MIC_IN_MUTE:
1462 	case CMPCI_LINE_IN_MUTE:
1463 	case CMPCI_FM_IN_MUTE:
1464 	case CMPCI_CD_SWAP:
1465 	case CMPCI_MIC_SWAP:
1466 	case CMPCI_LINE_SWAP:
1467 	case CMPCI_FM_SWAP:
1468 	case CMPCI_CD_OUT_MUTE:
1469 	case CMPCI_MIC_OUT_MUTE:
1470 	case CMPCI_LINE_OUT_MUTE:
1471 		cp->un.ord = sc->gain[cp->dev][CMPCI_LR];
1472 		break;
1473 
1474 	default:
1475 		return EINVAL;
1476 	}
1477 
1478 	return 0;
1479 }
1480 
1481 /* ARGSUSED */
1482 size_t
1483 cmpci_round_buffersize(handle, direction, bufsize)
1484 	void *handle;
1485 	int direction;
1486 	size_t bufsize;
1487 {
1488 	if (bufsize > 0x10000)
1489 	    bufsize = 0x10000;
1490 
1491 	return bufsize;
1492 }
1493 
1494 paddr_t
1495 cmpci_mappage(handle, addr, offset, prot)
1496 	void *handle;
1497 	void *addr;
1498 	off_t offset;
1499 	int   prot;
1500 {
1501 	struct cmpci_softc *sc = handle;
1502 	struct cmpci_dmanode *p;
1503 
1504 	if ( offset < 0 || (p = cmpci_find_dmamem(sc, addr)) == NULL)
1505 		return -1;
1506 
1507 	return bus_dmamem_mmap(p->cd_tag, p->cd_segs,
1508 			       sizeof(p->cd_segs)/sizeof(p->cd_segs[0]),
1509 			       offset, prot, BUS_DMA_WAITOK);
1510 }
1511 
1512 /* ARGSUSED */
1513 int
1514 cmpci_get_props(handle)
1515 	void *handle;
1516 {
1517 	return AUDIO_PROP_MMAP | AUDIO_PROP_INDEPENDENT | AUDIO_PROP_FULLDUPLEX;
1518 }
1519 
1520 
1521 int
1522 cmpci_trigger_output(handle, start, end, blksize, intr, arg, param)
1523         void *handle;
1524         void *start, *end;
1525         int blksize;
1526         void (*intr)(void *);
1527         void *arg;
1528         struct audio_params *param;
1529 {
1530 	struct cmpci_softc *sc = handle;
1531 	struct cmpci_dmanode *p;
1532 	int bps;
1533 
1534 	sc->sc_play.intr = intr;
1535 	sc->sc_play.intr_arg = arg;
1536 	bps = param->channels * param->precision * param->factor / 8;
1537 	if (!bps)
1538 		return EINVAL;
1539 
1540 	/* set DMA frame */
1541 	if (!(p = cmpci_find_dmamem(sc, start)))
1542 		return EINVAL;
1543 	bus_space_write_4(sc->sc_iot, sc->sc_ioh, CMPCI_REG_DMA0_BASE,
1544 			  DMAADDR(p));
1545 	delay(10);
1546 	bus_space_write_2(sc->sc_iot, sc->sc_ioh, CMPCI_REG_DMA0_BYTES,
1547 			  ((caddr_t)end-(caddr_t)start+1)/bps-1);
1548 	delay(10);
1549 
1550 	/* set interrupt count */
1551 	bus_space_write_2(sc->sc_iot, sc->sc_ioh, CMPCI_REG_DMA0_SAMPLES,
1552 			  (blksize+bps-1)/bps-1);
1553 	delay(10);
1554 
1555 	/* start DMA */
1556 	cmpci_reg_clear_4(sc, CMPCI_REG_FUNC_0, CMPCI_REG_CH0_DIR); /* PLAY */
1557 	cmpci_reg_set_4(sc, CMPCI_REG_INTR_CTRL, CMPCI_REG_CH0_INTR_ENABLE);
1558 	cmpci_reg_set_4(sc, CMPCI_REG_FUNC_0, CMPCI_REG_CH0_ENABLE);
1559 
1560 	return 0;
1561 }
1562 
1563 int
1564 cmpci_trigger_input(handle, start, end, blksize, intr, arg, param)
1565         void *handle;
1566         void *start, *end;
1567         int blksize;
1568         void (*intr)(void *);
1569         void *arg;
1570         struct audio_params *param;
1571 {
1572 	struct cmpci_softc *sc = handle;
1573 	struct cmpci_dmanode *p;
1574 	int bps;
1575 
1576 	sc->sc_rec.intr = intr;
1577 	sc->sc_rec.intr_arg = arg;
1578 	bps = param->channels*param->precision*param->factor/8;
1579 	if (!bps)
1580 		return EINVAL;
1581 
1582 	/* set DMA frame */
1583 	if (!(p = cmpci_find_dmamem(sc, start)))
1584 		return EINVAL;
1585 	bus_space_write_4(sc->sc_iot, sc->sc_ioh, CMPCI_REG_DMA1_BASE,
1586 			  DMAADDR(p));
1587 	delay(10);
1588 	bus_space_write_2(sc->sc_iot, sc->sc_ioh, CMPCI_REG_DMA1_BYTES,
1589 			  ((caddr_t)end-(caddr_t)start+1)/bps-1);
1590 	delay(10);
1591 
1592 	/* set interrupt count */
1593 	bus_space_write_2(sc->sc_iot, sc->sc_ioh, CMPCI_REG_DMA1_SAMPLES,
1594 			  (blksize+bps-1)/bps-1);
1595 	delay(10);
1596 
1597 	/* start DMA */
1598 	cmpci_reg_set_4(sc, CMPCI_REG_FUNC_0, CMPCI_REG_CH1_DIR); /* REC */
1599 	cmpci_reg_set_4(sc, CMPCI_REG_INTR_CTRL, CMPCI_REG_CH1_INTR_ENABLE);
1600 	cmpci_reg_set_4(sc, CMPCI_REG_FUNC_0, CMPCI_REG_CH1_ENABLE);
1601 
1602 	return 0;
1603 }
1604