xref: /openbsd-src/sys/dev/pci/cmpci.c (revision 3a3fbb3f2e2521ab7c4a56b7ff7462ebd9095ec5)
1 /*	$OpenBSD: cmpci.c,v 1.5 2001/10/31 11:00:24 art 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 __P((struct cmpci_softc *,
72                                                  uint8_t));
73 static __inline void cmpci_mixerreg_write __P((struct cmpci_softc *,
74                                                uint8_t, uint8_t));
75 static __inline void cmpci_reg_partial_write_4 __P((struct cmpci_softc *,
76                                                     int, int,
77                                                     uint32_t, uint32_t));
78 static __inline void cmpci_reg_set_4 __P((struct cmpci_softc *,
79                                           int, uint32_t));
80 static __inline void cmpci_reg_clear_4 __P((struct cmpci_softc *,
81                                             int, uint32_t));
82 static int cmpci_rate_to_index __P((int));
83 static __inline int cmpci_index_to_rate __P((int));
84 static __inline int cmpci_index_to_divider __P((int));
85 
86 static int cmpci_adjust __P((int, int));
87 static void cmpci_set_mixer_gain __P((struct cmpci_softc *, int));
88 static int cmpci_set_in_ports __P((struct cmpci_softc *, int));
89 
90 
91 /*
92  * autoconf interface
93  */
94 int cmpci_match __P((struct device *, void *, void *));
95 void cmpci_attach __P((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 __P((void *));
113 
114 
115 /*
116  * DMA stuff
117  */
118 int cmpci_alloc_dmamem __P((struct cmpci_softc *,
119                             size_t, int, int, caddr_t *));
120 int cmpci_free_dmamem __P((struct cmpci_softc *, caddr_t, int));
121 struct cmpci_dmanode * cmpci_find_dmamem __P((struct cmpci_softc *,
122                                                      caddr_t));
123 
124 /*
125  * Interface to machine independent layer
126  */
127 int cmpci_open __P((void *, int));
128 void cmpci_close __P((void *));
129 int cmpci_query_encoding __P((void *, struct audio_encoding *));
130 int cmpci_set_params __P((void *, int, int,
131                           struct audio_params *,
132                           struct audio_params *));
133 int cmpci_round_blocksize __P((void *, int));
134 int cmpci_halt_output __P((void *));
135 int cmpci_halt_input __P((void *));
136 int cmpci_getdev __P((void *, struct audio_device *));
137 int cmpci_set_port __P((void *, mixer_ctrl_t *));
138 int cmpci_get_port __P((void *, mixer_ctrl_t *));
139 int cmpci_query_devinfo __P((void *, mixer_devinfo_t *));
140 void *cmpci_malloc __P((void *, u_long, int, int));
141 void cmpci_free __P((void *, void *, int));
142 u_long cmpci_round_buffersize __P((void *, u_long));
143 paddr_t cmpci_mappage __P((void *, void *, off_t, int));
144 int cmpci_get_props __P((void *));
145 int cmpci_trigger_output __P((void *, void *, void *, int,
146                               void (*)(void *), void *,
147                               struct audio_params *));
148 int cmpci_trigger_input __P((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 
293 /*
294  * interface to configure the device.
295  */
296 int
297 cmpci_match(parent, match, aux)
298 	struct device *parent;
299 	void *match;
300 	void *aux;
301 {
302 	struct pci_attach_args *pa = (struct pci_attach_args *)aux;
303 
304 	if (PCI_VENDOR(pa->pa_id) == PCI_VENDOR_CMI &&
305 	    (PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_CMI_CMI8338A ||
306 	     PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_CMI_CMI8338B ||
307 	     PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_CMI_CMI8738))
308 		return 1;
309 
310 	return 0;
311 }
312 
313 void
314 cmpci_attach(parent, self, aux)
315 	struct device *parent, *self;
316 	void *aux;
317 {
318 	struct cmpci_softc *sc = (struct cmpci_softc *)self;
319 	struct pci_attach_args *pa = (struct pci_attach_args *)aux;
320 	pci_intr_handle_t ih;
321 	char const *intrstr;
322 	int i, v;
323 
324 	/* map I/O space */
325 	if (pci_mapreg_map(pa, CMPCI_PCI_IOBASEREG, PCI_MAPREG_TYPE_IO, 0,
326 			   &sc->sc_iot, &sc->sc_ioh, NULL, NULL, 0)) {
327 		printf("\n%s: failed to map I/O space\n", sc->sc_dev.dv_xname);
328 		return;
329 	}
330 
331 	/* interrupt */
332 	if (pci_intr_map(pa, &ih)) {
333 		printf("\n%s: failed to map interrupt\n", sc->sc_dev.dv_xname);
334 		return;
335 	}
336 	intrstr = pci_intr_string(pa->pa_pc, ih);
337 	sc->sc_ih = pci_intr_establish(pa->pa_pc, ih, IPL_AUDIO, cmpci_intr,
338 				       sc, sc->sc_dev.dv_xname);
339 
340 	if (sc->sc_ih == NULL) {
341 		printf("\n%s: couldn't establish interrupt",
342 		    sc->sc_dev.dv_xname);
343 		if (intrstr)
344 			printf(" at %s", intrstr);
345 		printf("\n");
346 		return;
347 	}
348 	printf(": %s\n", intrstr);
349 
350 	sc->sc_dmat = pa->pa_dmat;
351 
352 	audio_attach_mi(&cmpci_hw_if, sc, &sc->sc_dev);
353 
354 	cmpci_mixerreg_write(sc, CMPCI_SB16_MIXER_RESET, 0);
355 	cmpci_mixerreg_write(sc, CMPCI_SB16_MIXER_ADCMIX_L, 0);
356 	cmpci_mixerreg_write(sc, CMPCI_SB16_MIXER_ADCMIX_R, 0);
357 	cmpci_mixerreg_write(sc, CMPCI_SB16_MIXER_OUTMIX,
358 			     CMPCI_SB16_SW_CD|CMPCI_SB16_SW_MIC|
359 			     CMPCI_SB16_SW_LINE);
360 	for (i = 0; i < CMPCI_NDEVS; i++) {
361 		switch(i) {
362 		case CMPCI_MIC_VOL:
363 		case CMPCI_LINE_IN_VOL:
364 			v = 0;
365 			break;
366 		case CMPCI_BASS:
367 		case CMPCI_TREBLE:
368 			v = CMPCI_ADJUST_GAIN(sc, AUDIO_MAX_GAIN / 2);
369 			break;
370 		case CMPCI_CD_IN_MUTE:
371 		case CMPCI_MIC_IN_MUTE:
372 		case CMPCI_LINE_IN_MUTE:
373 		case CMPCI_FM_IN_MUTE:
374 		case CMPCI_CD_SWAP:
375 		case CMPCI_MIC_SWAP:
376 		case CMPCI_LINE_SWAP:
377 		case CMPCI_FM_SWAP:
378 			v = 0;
379 			break;
380 		case CMPCI_CD_OUT_MUTE:
381 		case CMPCI_MIC_OUT_MUTE:
382 		case CMPCI_LINE_OUT_MUTE:
383 			v = 1;
384 			break;
385 		default:
386 			v = CMPCI_ADJUST_GAIN(sc, AUDIO_MAX_GAIN / 2);
387 		}
388 		sc->gain[i][CMPCI_LEFT] = sc->gain[i][CMPCI_RIGHT] = v;
389 		cmpci_set_mixer_gain(sc, i);
390 	}
391 }
392 
393 int
394 cmpci_intr(handle)
395 	void *handle;
396 {
397 	struct cmpci_softc *sc = handle;
398 	uint32_t intrstat;
399 	int s;
400 
401 	intrstat = bus_space_read_4(sc->sc_iot, sc->sc_ioh,
402 	    CMPCI_REG_INTR_STATUS);
403 	delay(10);
404 
405 	if (!(intrstat & CMPCI_REG_ANY_INTR))
406 		return 0;
407 
408 	/* disable and reset intr */
409 	s = splaudio();
410 	if (intrstat & CMPCI_REG_CH0_INTR)
411 		cmpci_reg_clear_4(sc, CMPCI_REG_INTR_CTRL,
412 		    CMPCI_REG_CH0_INTR_ENABLE);
413 	if (intrstat&CMPCI_REG_CH1_INTR)
414 		cmpci_reg_clear_4(sc, CMPCI_REG_INTR_CTRL,
415 		    CMPCI_REG_CH1_INTR_ENABLE);
416 	splx(s);
417 
418 	if (intrstat & CMPCI_REG_CH0_INTR) {
419 		if (sc->sc_play.intr)
420 			(*sc->sc_play.intr)(sc->sc_play.intr_arg);
421 	}
422 	if (intrstat & CMPCI_REG_CH1_INTR) {
423 	    if (sc->sc_rec.intr)
424 		    (*sc->sc_rec.intr)(sc->sc_rec.intr_arg);
425 	}
426 
427 	/* enable intr */
428 	s = splaudio();
429 	if ( intrstat & CMPCI_REG_CH0_INTR )
430 		cmpci_reg_set_4(sc, CMPCI_REG_INTR_CTRL,
431 		    CMPCI_REG_CH0_INTR_ENABLE);
432 	if (intrstat & CMPCI_REG_CH1_INTR)
433 		cmpci_reg_set_4(sc, CMPCI_REG_INTR_CTRL,
434 		    CMPCI_REG_CH1_INTR_ENABLE);
435 	splx(s);
436 
437 	return 1;
438 }
439 
440 /* open/close */
441 int
442 cmpci_open(handle, flags)
443 	void *handle;
444 	int flags;
445 {
446 	struct cmpci_softc *sc = handle;
447 	(void)sc;
448 	(void)flags;
449 
450 	return 0;
451 }
452 
453 void
454 cmpci_close(handle)
455 	void *handle;
456 {
457 	(void)handle;
458 }
459 
460 int
461 cmpci_query_encoding(handle, fp)
462 	void *handle;
463 	struct audio_encoding *fp;
464 {
465 	struct cmpci_softc *sc = handle;
466 	(void)sc;
467 
468 	switch (fp->index) {
469 	case 0:
470 		strcpy(fp->name, AudioEulinear);
471 		fp->encoding = AUDIO_ENCODING_ULINEAR;
472 		fp->precision = 8;
473 		fp->flags = AUDIO_ENCODINGFLAG_EMULATED;
474 		break;
475 	case 1:
476 		strcpy(fp->name, AudioEmulaw);
477 		fp->encoding = AUDIO_ENCODING_ULAW;
478 		fp->precision = 8;
479 		fp->flags = AUDIO_ENCODINGFLAG_EMULATED;
480 		break;
481 	case 2:
482 		strcpy(fp->name, AudioEalaw);
483 		fp->encoding = AUDIO_ENCODING_ALAW;
484 		fp->precision = 8;
485 		fp->flags = AUDIO_ENCODINGFLAG_EMULATED;
486 		break;
487 	case 3:
488 		strcpy(fp->name, AudioEslinear);
489 		fp->encoding = AUDIO_ENCODING_SLINEAR;
490 		fp->precision = 8;
491 		fp->flags = 0;
492 		break;
493 	case 4:
494 		strcpy(fp->name, AudioEslinear_le);
495 		fp->encoding = AUDIO_ENCODING_SLINEAR_LE;
496 		fp->precision = 16;
497 		fp->flags = 0;
498 		break;
499 	case 5:
500 		strcpy(fp->name, AudioEulinear_le);
501 		fp->encoding = AUDIO_ENCODING_ULINEAR_LE;
502 		fp->precision = 16;
503 		fp->flags = AUDIO_ENCODINGFLAG_EMULATED;
504 		break;
505 	case 6:
506 		strcpy(fp->name, AudioEslinear_be);
507 		fp->encoding = AUDIO_ENCODING_SLINEAR_BE;
508 		fp->precision = 16;
509 		fp->flags = AUDIO_ENCODINGFLAG_EMULATED;
510 		break;
511 	case 7:
512 		strcpy(fp->name, AudioEulinear_be);
513 		fp->encoding = AUDIO_ENCODING_ULINEAR_BE;
514 		fp->precision = 16;
515 		fp->flags = AUDIO_ENCODINGFLAG_EMULATED;
516 		break;
517 	default:
518 		return EINVAL;
519 	}
520 	return 0;
521 }
522 
523 
524 int
525 cmpci_set_params(handle, setmode, usemode, play, rec)
526 	void *handle;
527 	int setmode, usemode;
528 	struct audio_params *play, *rec;
529 {
530 	int i;
531 	struct cmpci_softc *sc = handle;
532 
533 	for (i=0; i<2; i++) {
534 		int md_format;
535 		int md_divide;
536 		int md_index;
537 		int mode;
538 		struct audio_params *p;
539 
540 		switch (i) {
541 		case 0:
542 			mode = AUMODE_PLAY;
543 			p = play;
544 			break;
545 		case 1:
546 			mode = AUMODE_RECORD;
547 			p = rec;
548 			break;
549 		}
550 
551 		if (!(setmode & mode))
552 			continue;
553 
554 		/* format */
555 		p->sw_code = NULL;
556 		switch (p->channels) {
557 		case 1:
558 			md_format = CMPCI_REG_FORMAT_MONO;
559 			break;
560 		case 2:
561 			md_format = CMPCI_REG_FORMAT_STEREO;
562 			break;
563 		default:
564 			return (EINVAL);
565 		}
566 		switch (p->encoding) {
567 		case AUDIO_ENCODING_ULAW:
568 			if (p->precision != 8)
569 				return (EINVAL);
570 			if (mode & AUMODE_PLAY) {
571 				p->factor = 2;
572 				p->sw_code = mulaw_to_slinear16;
573 				md_format |= CMPCI_REG_FORMAT_16BIT;
574 			} else
575 				p->sw_code = ulinear8_to_mulaw;
576 			md_format |= CMPCI_REG_FORMAT_8BIT;
577 			break;
578 		case AUDIO_ENCODING_ALAW:
579 			if (p->precision != 8)
580 				return (EINVAL);
581 			if (mode & AUMODE_PLAY) {
582 				p->factor = 2;
583 				p->sw_code = alaw_to_slinear16;
584 				md_format |= CMPCI_REG_FORMAT_16BIT;
585 			} else
586 				p->sw_code = ulinear8_to_alaw;
587 			md_format |= CMPCI_REG_FORMAT_8BIT;
588 			break;
589 		case AUDIO_ENCODING_SLINEAR_LE:
590 			switch (p->precision) {
591 			case 8:
592 				p->sw_code = change_sign8;
593 				md_format |= CMPCI_REG_FORMAT_8BIT;
594 				break;
595 			case 16:
596 				md_format |= CMPCI_REG_FORMAT_16BIT;
597 				break;
598 			default:
599 				return (EINVAL);
600 			}
601 			break;
602 		case AUDIO_ENCODING_SLINEAR_BE:
603 			switch (p->precision) {
604 			case 8:
605 				md_format |= CMPCI_REG_FORMAT_8BIT;
606 				p->sw_code = change_sign8;
607 				break;
608 			case 16:
609 				md_format |= CMPCI_REG_FORMAT_16BIT;
610 				p->sw_code = swap_bytes;
611 				break;
612 			default:
613 				return (EINVAL);
614 			}
615 			break;
616 		case AUDIO_ENCODING_ULINEAR_LE:
617 			switch ( p->precision ) {
618 			case 8:
619 				md_format |= CMPCI_REG_FORMAT_8BIT;
620 				break;
621 			case 16:
622 				md_format |= CMPCI_REG_FORMAT_16BIT;
623 				p->sw_code = change_sign16;
624 				break;
625 			default:
626 				return (EINVAL);
627 			}
628 			break;
629 		case AUDIO_ENCODING_ULINEAR_BE:
630 			switch (p->precision) {
631 			case 8:
632 				md_format |= CMPCI_REG_FORMAT_8BIT;
633 				break;
634 			case 16:
635 				md_format |= CMPCI_REG_FORMAT_16BIT;
636 				if ( mode&AUMODE_PLAY )
637 					p->sw_code = swap_bytes_change_sign16;
638 				else
639 					p->sw_code = change_sign16_swap_bytes;
640 				break;
641 			default:
642 				return (EINVAL);
643 			}
644 			break;
645 		default:
646 			return (EINVAL);
647 		}
648 		if (mode & AUMODE_PLAY)
649 			cmpci_reg_partial_write_4(sc,
650 						  CMPCI_REG_CHANNEL_FORMAT,
651 						  CMPCI_REG_CH0_FORMAT_SHIFT,
652 						  CMPCI_REG_CH0_FORMAT_MASK,
653 						  md_format);
654 		else
655 			cmpci_reg_partial_write_4(sc,
656 						  CMPCI_REG_CHANNEL_FORMAT,
657 						  CMPCI_REG_CH1_FORMAT_SHIFT,
658 						  CMPCI_REG_CH1_FORMAT_MASK,
659 						  md_format);
660 		/* sample rate */
661 		md_index = cmpci_rate_to_index(p->sample_rate);
662 		md_divide = cmpci_index_to_divider(md_index);
663 		p->sample_rate = cmpci_index_to_rate(md_index);
664 #if 0
665 		DPRINTF(("%s: sample:%d, divider=%d\n",
666 			 sc->sc_dev.dv_xname, (int)p->sample_rate, md_divide));
667 #endif
668 		if (mode & AUMODE_PLAY) {
669 			cmpci_reg_partial_write_4(sc,
670 						  CMPCI_REG_FUNC_1,
671 						  CMPCI_REG_DAC_FS_SHIFT,
672 						  CMPCI_REG_DAC_FS_MASK,
673 						  md_divide);
674 #ifdef CMPCI_SPDIF_SUPPORT
675 			switch (md_divide) {
676 			case CMPCI_REG_RATE_44100:
677 				cmpci_reg_clear_4(sc, CMPCI_REG_MISC,
678 						  CMPCI_REG_SPDIF_48K);
679 				cmpci_reg_clear_4(sc, CMPCI_REG_FUNC_1,
680 						  CMPCI_REG_SPDIF_LOOP);
681 				cmpci_reg_set_4(sc, CMPCI_REG_FUNC_1,
682 						CMPCI_REG_SPDIF0_ENABLE);
683 				break;
684 			case CMPCI_REG_RATE_48000:
685 				cmpci_reg_set_4(sc, CMPCI_REG_MISC,
686 						CMPCI_REG_SPDIF_48K);
687 				cmpci_reg_clear_4(sc, CMPCI_REG_FUNC_1,
688 						  CMPCI_REG_SPDIF_LOOP);
689 				cmpci_reg_set_4(sc, CMPCI_REG_FUNC_1,
690 						CMPCI_REG_SPDIF0_ENABLE);
691 				break;
692 			default:
693 				cmpci_reg_clear_4(sc, CMPCI_REG_FUNC_1,
694 						  CMPCI_REG_SPDIF0_ENABLE);
695 			    cmpci_reg_set_4(sc, CMPCI_REG_FUNC_1,
696 					    CMPCI_REG_SPDIF_LOOP);
697 			}
698 #endif
699 		} else {
700 			cmpci_reg_partial_write_4(sc,
701 						  CMPCI_REG_FUNC_1,
702 						  CMPCI_REG_ADC_FS_SHIFT,
703 						  CMPCI_REG_ADC_FS_MASK,
704 						  md_divide);
705 #ifdef CMPCI_SPDIF_SUPPORT
706 			if ( sc->in_mask&CMPCI_SPDIF_IN) {
707 				switch (md_divide) {
708 				case CMPCI_REG_RATE_44100:
709 					cmpci_reg_set_4(sc, CMPCI_REG_FUNC_1,
710 							CMPCI_REG_SPDIF1_ENABLE);
711 					break;
712 				default:
713 					return EINVAL;
714 				}
715 			} else
716 				cmpci_reg_clear_4(sc, CMPCI_REG_FUNC_1,
717 						  CMPCI_REG_SPDIF1_ENABLE);
718 #endif
719 		}
720 	}
721 	return 0;
722 }
723 
724 /* ARGSUSED */
725 int
726 cmpci_round_blocksize(handle, block)
727 	void *handle;
728 	int block;
729 {
730 	return (block & -4);
731 }
732 
733 int
734 cmpci_halt_output(handle)
735 	void *handle;
736 {
737 	struct cmpci_softc *sc = handle;
738 	int s;
739 
740 	s = splaudio();
741 	sc->sc_play.intr = NULL;
742 	cmpci_reg_clear_4(sc, CMPCI_REG_INTR_CTRL, CMPCI_REG_CH0_INTR_ENABLE);
743 	cmpci_reg_clear_4(sc, CMPCI_REG_FUNC_0, CMPCI_REG_CH0_ENABLE);
744 	/* wait for reset DMA */
745 	cmpci_reg_set_4(sc, CMPCI_REG_FUNC_0, CMPCI_REG_CH0_RESET);
746 	delay(10);
747 	cmpci_reg_clear_4(sc, CMPCI_REG_FUNC_0, CMPCI_REG_CH0_RESET);
748 	splx(s);
749 
750 	return 0;
751 }
752 
753 int
754 cmpci_halt_input(handle)
755 	void *handle;
756 {
757 	struct cmpci_softc *sc = handle;
758 	int s;
759 
760 	s = splaudio();
761 	sc->sc_rec.intr = NULL;
762 	cmpci_reg_clear_4(sc, CMPCI_REG_INTR_CTRL, CMPCI_REG_CH1_INTR_ENABLE);
763 	cmpci_reg_clear_4(sc, CMPCI_REG_FUNC_0, CMPCI_REG_CH1_ENABLE);
764 	/* wait for reset DMA */
765 	cmpci_reg_set_4(sc, CMPCI_REG_FUNC_0, CMPCI_REG_CH1_RESET);
766 	delay(10);
767 	cmpci_reg_clear_4(sc, CMPCI_REG_FUNC_0, CMPCI_REG_CH1_RESET);
768 	splx(s);
769 
770 	return 0;
771 }
772 
773 int
774 cmpci_getdev(handle, retp)
775         void *handle;
776         struct audio_device *retp;
777 {
778 	*retp = cmpci_device;
779 	return 0;
780 }
781 
782 
783 /* mixer device information */
784 int
785 cmpci_query_devinfo(handle, dip)
786 	void *handle;
787 	mixer_devinfo_t *dip;
788 {
789 	struct cmpci_softc *sc = handle;
790 	(void)sc;
791 
792 	switch (dip->index) {
793 	case CMPCI_MASTER_VOL:
794 		dip->type = AUDIO_MIXER_VALUE;
795 		dip->mixer_class = CMPCI_OUTPUT_CLASS;
796 		dip->prev = dip->next = AUDIO_MIXER_LAST;
797 		strcpy(dip->label.name, AudioNmaster);
798 		dip->un.v.num_channels = 2;
799 		strcpy(dip->un.v.units.name, AudioNvolume);
800 		return 0;
801 	case CMPCI_FM_VOL:
802 		dip->type = AUDIO_MIXER_VALUE;
803 		dip->mixer_class = CMPCI_INPUT_CLASS;
804 		dip->prev = AUDIO_MIXER_LAST;
805 		dip->next = CMPCI_FM_IN_MUTE;
806 		strcpy(dip->label.name, AudioNfmsynth);
807 		dip->un.v.num_channels = 2;
808 		strcpy(dip->un.v.units.name, AudioNvolume);
809 		return 0;
810 	case CMPCI_CD_VOL:
811 		dip->type = AUDIO_MIXER_VALUE;
812 		dip->mixer_class = CMPCI_INPUT_CLASS;
813 		dip->prev = AUDIO_MIXER_LAST;
814 		dip->next = CMPCI_CD_IN_MUTE;
815 		strcpy(dip->label.name, AudioNcd);
816 		dip->un.v.num_channels = 2;
817 		strcpy(dip->un.v.units.name, AudioNvolume);
818 		return 0;
819 	case CMPCI_VOICE_VOL:
820 		dip->type = AUDIO_MIXER_VALUE;
821 		dip->mixer_class = CMPCI_OUTPUT_CLASS;
822 		dip->prev = AUDIO_MIXER_LAST;
823 		dip->next = AUDIO_MIXER_LAST;
824 		strcpy(dip->label.name, AudioNdac);
825 		dip->un.v.num_channels = 2;
826 		strcpy(dip->un.v.units.name, AudioNvolume);
827 		return 0;
828 	case CMPCI_OUTPUT_CLASS:
829 		dip->type = AUDIO_MIXER_CLASS;
830 		dip->mixer_class = CMPCI_INPUT_CLASS;
831 		dip->next = dip->prev = AUDIO_MIXER_LAST;
832 		strcpy(dip->label.name, AudioCoutputs);
833 		return 0;
834 	case CMPCI_MIC_VOL:
835 		dip->type = AUDIO_MIXER_VALUE;
836 		dip->mixer_class = CMPCI_INPUT_CLASS;
837 		dip->prev = AUDIO_MIXER_LAST;
838 		dip->next = CMPCI_MIC_IN_MUTE;
839 		strcpy(dip->label.name, AudioNmicrophone);
840 		dip->un.v.num_channels = 1;
841 		strcpy(dip->un.v.units.name, AudioNvolume);
842 		return 0;
843 	case CMPCI_LINE_IN_VOL:
844 		dip->type = AUDIO_MIXER_VALUE;
845 		dip->mixer_class = CMPCI_INPUT_CLASS;
846 		dip->prev = AUDIO_MIXER_LAST;
847 		dip->next = CMPCI_LINE_IN_MUTE;
848 		strcpy(dip->label.name, AudioNline);
849 		dip->un.v.num_channels = 2;
850 		strcpy(dip->un.v.units.name, AudioNvolume);
851 		return 0;
852 	case CMPCI_RECORD_SOURCE:
853 		dip->mixer_class = CMPCI_RECORD_CLASS;
854 		dip->prev = dip->next = AUDIO_MIXER_LAST;
855 		strcpy(dip->label.name, AudioNsource);
856 		dip->type = AUDIO_MIXER_SET;
857 #ifdef CMPCI_SPDIF_SUPPORT
858 		dip->un.s.num_mem = 5;
859 #else
860 		dip->un.s.num_mem = 4;
861 #endif
862 		strcpy(dip->un.s.member[0].label.name, AudioNmicrophone);
863 		dip->un.s.member[0].mask = 1 << CMPCI_MIC_VOL;
864 		strcpy(dip->un.s.member[1].label.name, AudioNcd);
865 		dip->un.s.member[1].mask = 1 << CMPCI_CD_VOL;
866 		strcpy(dip->un.s.member[2].label.name, AudioNline);
867 		dip->un.s.member[2].mask = 1 << CMPCI_LINE_IN_VOL;
868 		strcpy(dip->un.s.member[3].label.name, AudioNfmsynth);
869 		dip->un.s.member[3].mask = 1 << CMPCI_FM_VOL;
870 #ifdef CMPCI_SPDIF_SUPPORT
871 		strcpy(dip->un.s.member[4].label.name, CmpciNspdif);
872 		dip->un.s.member[4].mask = 1 << CMPCI_SPDIF_IN;
873 #endif
874 		return 0;
875 	case CMPCI_BASS:
876 		dip->prev = dip->next = AUDIO_MIXER_LAST;
877 		strcpy(dip->label.name, AudioNbass);
878 		dip->type = AUDIO_MIXER_VALUE;
879 		dip->mixer_class = CMPCI_EQUALIZATION_CLASS;
880 		dip->un.v.num_channels = 2;
881 		strcpy(dip->un.v.units.name, AudioNbass);
882 		return 0;
883 	case CMPCI_TREBLE:
884 		dip->prev = dip->next = AUDIO_MIXER_LAST;
885 		strcpy(dip->label.name, AudioNtreble);
886 		dip->type = AUDIO_MIXER_VALUE;
887 		dip->mixer_class = CMPCI_EQUALIZATION_CLASS;
888 		dip->un.v.num_channels = 2;
889 		strcpy(dip->un.v.units.name, AudioNtreble);
890 		return 0;
891 	case CMPCI_RECORD_CLASS:
892 		dip->type = AUDIO_MIXER_CLASS;
893 		dip->mixer_class = CMPCI_RECORD_CLASS;
894 		dip->next = dip->prev = AUDIO_MIXER_LAST;
895 		strcpy(dip->label.name, AudioCrecord);
896 		return 0;
897 	case CMPCI_INPUT_CLASS:
898 		dip->type = AUDIO_MIXER_CLASS;
899 		dip->mixer_class = CMPCI_INPUT_CLASS;
900 		dip->next = dip->prev = AUDIO_MIXER_LAST;
901 		strcpy(dip->label.name, AudioCinputs);
902 		return 0;
903 	case CMPCI_PCSPEAKER:
904 		dip->type = AUDIO_MIXER_VALUE;
905 		dip->mixer_class = CMPCI_INPUT_CLASS;
906 		dip->prev = dip->next = AUDIO_MIXER_LAST;
907 		strcpy(dip->label.name, "pc_speaker");
908 		dip->un.v.num_channels = 1;
909 		strcpy(dip->un.v.units.name, AudioNvolume);
910 		return 0;
911 	case CMPCI_INPUT_GAIN:
912 		dip->type = AUDIO_MIXER_VALUE;
913 		dip->mixer_class = CMPCI_INPUT_CLASS;
914 		dip->prev = dip->next = AUDIO_MIXER_LAST;
915 		strcpy(dip->label.name, AudioNinput);
916 		dip->un.v.num_channels = 2;
917 		strcpy(dip->un.v.units.name, AudioNvolume);
918 		return 0;
919 	case CMPCI_OUTPUT_GAIN:
920 		dip->type = AUDIO_MIXER_VALUE;
921 		dip->mixer_class = CMPCI_OUTPUT_CLASS;
922 		dip->prev = dip->next = AUDIO_MIXER_LAST;
923 		strcpy(dip->label.name, AudioNoutput);
924 		dip->un.v.num_channels = 2;
925 		strcpy(dip->un.v.units.name, AudioNvolume);
926 		return 0;
927 	case CMPCI_AGC:
928 		dip->type = AUDIO_MIXER_ENUM;
929 		dip->mixer_class = CMPCI_INPUT_CLASS;
930 		dip->prev = dip->next = AUDIO_MIXER_LAST;
931 		strcpy(dip->label.name, "agc");
932 		dip->un.e.num_mem = 2;
933 		strcpy(dip->un.e.member[0].label.name, AudioNoff);
934 		dip->un.e.member[0].ord = 0;
935 		strcpy(dip->un.e.member[1].label.name, AudioNon);
936 		dip->un.e.member[1].ord = 1;
937 		return 0;
938 	case CMPCI_EQUALIZATION_CLASS:
939 		dip->type = AUDIO_MIXER_CLASS;
940 		dip->mixer_class = CMPCI_EQUALIZATION_CLASS;
941 		dip->next = dip->prev = AUDIO_MIXER_LAST;
942 		strcpy(dip->label.name, AudioCequalization);
943 		return 0;
944 	case CMPCI_CD_IN_MUTE:
945 		dip->prev = CMPCI_CD_VOL;
946 		dip->next = CMPCI_CD_SWAP;
947 		dip->mixer_class = CMPCI_INPUT_CLASS;
948 		goto mute;
949 	case CMPCI_MIC_IN_MUTE:
950 		dip->prev = CMPCI_MIC_VOL;
951 		dip->next = CMPCI_MIC_SWAP;
952 		dip->mixer_class = CMPCI_INPUT_CLASS;
953 		goto mute;
954 	case CMPCI_LINE_IN_MUTE:
955 		dip->prev = CMPCI_LINE_IN_VOL;
956 		dip->next = CMPCI_LINE_SWAP;
957 		dip->mixer_class = CMPCI_INPUT_CLASS;
958 		goto mute;
959 	case CMPCI_FM_IN_MUTE:
960 		dip->prev = CMPCI_FM_VOL;
961 		dip->next = CMPCI_FM_SWAP;
962 		dip->mixer_class = CMPCI_INPUT_CLASS;
963 		goto mute;
964 	case CMPCI_CD_SWAP:
965 		dip->prev = CMPCI_CD_IN_MUTE;
966 		dip->next = CMPCI_CD_OUT_MUTE;
967 		goto swap;
968 	case CMPCI_MIC_SWAP:
969 		dip->prev = CMPCI_MIC_IN_MUTE;
970 		dip->next = CMPCI_MIC_OUT_MUTE;
971 		goto swap;
972 	case CMPCI_LINE_SWAP:
973 		dip->prev = CMPCI_LINE_IN_MUTE;
974 		dip->next = CMPCI_LINE_OUT_MUTE;
975 		goto swap;
976 	case CMPCI_FM_SWAP:
977 		dip->prev = CMPCI_FM_IN_MUTE;
978 		dip->next = AUDIO_MIXER_LAST;
979 	swap:
980 		dip->mixer_class = CMPCI_INPUT_CLASS;
981 		strcpy(dip->label.name, AudioNswap);
982 		goto mute1;
983 	case CMPCI_CD_OUT_MUTE:
984 		dip->prev = CMPCI_CD_SWAP;
985 		dip->next = AUDIO_MIXER_LAST;
986 		dip->mixer_class = CMPCI_OUTPUT_CLASS;
987 		goto mute;
988 	case CMPCI_MIC_OUT_MUTE:
989 		dip->prev = CMPCI_MIC_SWAP;
990 		dip->next = AUDIO_MIXER_LAST;
991 		dip->mixer_class = CMPCI_OUTPUT_CLASS;
992 		goto mute;
993 	case CMPCI_LINE_OUT_MUTE:
994 		dip->prev = CMPCI_LINE_SWAP;
995 		dip->next = AUDIO_MIXER_LAST;
996 		dip->mixer_class = CMPCI_OUTPUT_CLASS;
997 	mute:
998 		strcpy(dip->label.name, AudioNmute);
999 	mute1:
1000 		dip->type = AUDIO_MIXER_ENUM;
1001 		dip->un.e.num_mem = 2;
1002 		strcpy(dip->un.e.member[0].label.name, AudioNoff);
1003 		dip->un.e.member[0].ord = 0;
1004 		strcpy(dip->un.e.member[1].label.name, AudioNon);
1005 		dip->un.e.member[1].ord = 1;
1006 		return 0;
1007 	}
1008 
1009 	return ENXIO;
1010 }
1011 
1012 int
1013 cmpci_alloc_dmamem(sc, size, type, flags, r_addr)
1014 	struct cmpci_softc *sc;
1015 	size_t size;
1016 	int type, flags;
1017 	caddr_t *r_addr;
1018 {
1019 	int ret = 0;
1020 	struct cmpci_dmanode *n;
1021 	int w;
1022 
1023 	if ( NULL == (n=malloc(sizeof(struct cmpci_dmanode), type, flags)) ) {
1024 		ret = ENOMEM;
1025 		goto quit;
1026 	}
1027 
1028 	w = (flags & M_NOWAIT) ? BUS_DMA_NOWAIT : BUS_DMA_WAITOK;
1029 #define CMPCI_DMABUF_ALIGN    0x4
1030 #define CMPCI_DMABUF_BOUNDARY 0x0
1031 	n->cd_tag = sc->sc_dmat;
1032 	n->cd_size = size;
1033 	if ( (ret=bus_dmamem_alloc(n->cd_tag, n->cd_size,
1034 				   CMPCI_DMABUF_ALIGN, CMPCI_DMABUF_BOUNDARY,
1035 				   n->cd_segs,
1036 				   sizeof(n->cd_segs)/sizeof(n->cd_segs[0]),
1037 				   &n->cd_nsegs, w)) )
1038 		goto mfree;
1039 	if ( (ret=bus_dmamem_map(n->cd_tag, n->cd_segs, n->cd_nsegs, n->cd_size,
1040 				 &n->cd_addr, w | BUS_DMA_COHERENT)) )
1041 		goto dmafree;
1042 	if ( (ret=bus_dmamap_create(n->cd_tag, n->cd_size, 1, n->cd_size, 0,
1043 				    w, &n->cd_map)) )
1044 		goto unmap;
1045 	if ( (ret=bus_dmamap_load(n->cd_tag, n->cd_map, n->cd_addr, n->cd_size,
1046 				  NULL, w)) )
1047 		goto destroy;
1048 
1049 	n->cd_next = sc->sc_dmap;
1050 	sc->sc_dmap = n;
1051 	*r_addr = KVADDR(n);
1052 	return 0;
1053 
1054 destroy:
1055 	bus_dmamap_destroy(n->cd_tag, n->cd_map);
1056 unmap:
1057 	bus_dmamem_unmap(n->cd_tag, n->cd_addr, n->cd_size);
1058 dmafree:
1059 	bus_dmamem_free(n->cd_tag,
1060 			n->cd_segs, sizeof(n->cd_segs)/sizeof(n->cd_segs[0]));
1061 mfree:
1062 	free(n, type);
1063 quit:
1064 	return ret;
1065 }
1066 
1067 int
1068 cmpci_free_dmamem(sc, addr, type)
1069 	struct cmpci_softc *sc;
1070 	caddr_t addr;
1071 	int type;
1072 {
1073     struct cmpci_dmanode **nnp;
1074 
1075 	for (nnp = &sc->sc_dmap; *nnp; nnp = &(*nnp)->cd_next) {
1076 		if ((*nnp)->cd_addr == addr) {
1077 			struct cmpci_dmanode *n = *nnp;
1078 
1079 			bus_dmamap_unload(n->cd_tag, n->cd_map);
1080 			bus_dmamap_destroy(n->cd_tag, n->cd_map);
1081 			bus_dmamem_unmap(n->cd_tag, n->cd_addr, n->cd_size);
1082 			bus_dmamem_free(n->cd_tag, n->cd_segs,
1083 			    sizeof(n->cd_segs)/sizeof(n->cd_segs[0]));
1084 			free(n, type);
1085 			return 0;
1086 		}
1087 	}
1088 	return -1;
1089 }
1090 
1091 struct cmpci_dmanode *
1092 cmpci_find_dmamem(sc, addr)
1093 	struct cmpci_softc *sc;
1094 	caddr_t addr;
1095 {
1096 	struct cmpci_dmanode *p;
1097 	for (p = sc->sc_dmap; p; p = p->cd_next) {
1098 		if (KVADDR(p) == (void *)addr)
1099 			break;
1100 	}
1101 	return p;
1102 }
1103 
1104 #if 0
1105 void
1106 cmpci_print_dmamem __P((struct cmpci_dmanode *p));
1107 void
1108 cmpci_print_dmamem(p)
1109 	struct cmpci_dmanode *p;
1110 {
1111 	DPRINTF(("DMA at virt:%p, dmaseg:%p, mapseg:%p, size:%p\n",
1112 		 (void *)p->cd_addr, (void *)p->cd_segs[0].ds_addr,
1113 		 (void *)DMAADDR(p), (void *)p->cd_size));
1114 }
1115 #endif /* DEBUG */
1116 
1117 void *
1118 cmpci_malloc(handle, size, type, flags)
1119 	void  *handle;
1120 	u_long size;
1121 	int    type, flags;
1122 {
1123 	struct cmpci_softc *sc = handle;
1124 	caddr_t addr;
1125 
1126 	if ( cmpci_alloc_dmamem(sc, size, type, flags, &addr) )
1127 		return NULL;
1128 	return addr;
1129 }
1130 
1131 void
1132 cmpci_free(handle, addr, type)
1133 	void    *handle;
1134 	void    *addr;
1135 	int     type;
1136 {
1137 	struct cmpci_softc *sc = handle;
1138 
1139 	cmpci_free_dmamem(sc, addr, type);
1140 }
1141 
1142 #define MAXVAL 256
1143 int
1144 cmpci_adjust(val, mask)
1145     int val, mask;
1146 {
1147 	val += (MAXVAL - mask) >> 1;
1148 	if (val >= MAXVAL)
1149 		val = MAXVAL-1;
1150 	return val & mask;
1151 }
1152 
1153 void
1154 cmpci_set_mixer_gain(sc, port)
1155 	struct cmpci_softc *sc;
1156 	int port;
1157 {
1158 	int src;
1159 
1160 	switch (port) {
1161 	case CMPCI_MIC_VOL:
1162 		src = CMPCI_SB16_MIXER_MIC;
1163 		break;
1164 	case CMPCI_MASTER_VOL:
1165 		src = CMPCI_SB16_MIXER_MASTER_L;
1166 		break;
1167 	case CMPCI_LINE_IN_VOL:
1168 		src = CMPCI_SB16_MIXER_LINE_L;
1169 		break;
1170 	case CMPCI_VOICE_VOL:
1171 		src = CMPCI_SB16_MIXER_VOICE_L;
1172 		break;
1173 	case CMPCI_FM_VOL:
1174 		src = CMPCI_SB16_MIXER_FM_L;
1175 		break;
1176 	case CMPCI_CD_VOL:
1177 		src = CMPCI_SB16_MIXER_CDDA_L;
1178 		break;
1179 	case CMPCI_INPUT_GAIN:
1180 		src = CMPCI_SB16_MIXER_INGAIN_L;
1181 		break;
1182 	case CMPCI_OUTPUT_GAIN:
1183 		src = CMPCI_SB16_MIXER_OUTGAIN_L;
1184 		break;
1185 	case CMPCI_TREBLE:
1186 		src = CMPCI_SB16_MIXER_TREBLE_L;
1187 		break;
1188 	case CMPCI_BASS:
1189 		src = CMPCI_SB16_MIXER_BASS_L;
1190 		break;
1191 	case CMPCI_PCSPEAKER:
1192 		cmpci_mixerreg_write(sc, CMPCI_SB16_MIXER_SPEAKER,
1193 				     sc->gain[port][CMPCI_LEFT]);
1194 		return;
1195 	default:
1196 		return;
1197 	}
1198 	cmpci_mixerreg_write(sc, src, sc->gain[port][CMPCI_LEFT]);
1199 	cmpci_mixerreg_write(sc, CMPCI_SB16_MIXER_L_TO_R(src),
1200 			     sc->gain[port][CMPCI_RIGHT]);
1201 }
1202 
1203 int
1204 cmpci_set_in_ports(sc, mask)
1205 	struct cmpci_softc *sc;
1206 	int mask;
1207 {
1208 	int bitsl, bitsr;
1209 
1210 	if (mask & ~((1<<CMPCI_FM_VOL) | (1<<CMPCI_LINE_IN_VOL) |
1211 		     (1<<CMPCI_CD_VOL) | (1<<CMPCI_MIC_VOL)
1212 #ifdef CMPCI_SPDIF_SUPPORT
1213 		     | (1<<CMPCI_SPDIF_IN)
1214 #endif
1215 		     ))
1216 		return EINVAL;
1217 	bitsr = 0;
1218 	if (mask & (1<<CMPCI_FM_VOL))
1219 		bitsr |= CMPCI_SB16_MIXER_FM_SRC_R;
1220 	if (mask & (1<<CMPCI_LINE_IN_VOL))
1221 		bitsr |= CMPCI_SB16_MIXER_LINE_SRC_R;
1222 	if (mask & (1<<CMPCI_CD_VOL))
1223 		bitsr |= CMPCI_SB16_MIXER_CD_SRC_R;
1224 	bitsl = CMPCI_SB16_MIXER_SRC_R_TO_L(bitsr);
1225 	if (mask & (1<<CMPCI_MIC_VOL)) {
1226 		bitsl |= CMPCI_SB16_MIXER_MIC_SRC;
1227 		bitsr |= CMPCI_SB16_MIXER_MIC_SRC;
1228 	}
1229 	cmpci_mixerreg_write(sc, CMPCI_SB16_MIXER_ADCMIX_L, bitsl);
1230 	cmpci_mixerreg_write(sc, CMPCI_SB16_MIXER_ADCMIX_R, bitsr);
1231 
1232 	sc->in_mask = mask;
1233 
1234 	return 0;
1235 }
1236 
1237 int
1238 cmpci_set_port(handle, cp)
1239 	void *handle;
1240 	mixer_ctrl_t *cp;
1241 {
1242 	struct cmpci_softc *sc = handle;
1243 	int lgain, rgain;
1244 	int mask, bits;
1245 	int lmask, rmask, lbits, rbits;
1246 	int mute, swap;
1247 
1248 	switch (cp->dev) {
1249 	case CMPCI_TREBLE:
1250 	case CMPCI_BASS:
1251 	case CMPCI_PCSPEAKER:
1252 	case CMPCI_INPUT_GAIN:
1253 	case CMPCI_OUTPUT_GAIN:
1254 	case CMPCI_MIC_VOL:
1255 	case CMPCI_LINE_IN_VOL:
1256 	case CMPCI_VOICE_VOL:
1257 	case CMPCI_FM_VOL:
1258 	case CMPCI_CD_VOL:
1259 	case CMPCI_MASTER_VOL:
1260 		if (cp->type != AUDIO_MIXER_VALUE)
1261 			return EINVAL;
1262 		switch (cp->dev) {
1263 		case CMPCI_MIC_VOL:
1264 			if (cp->un.value.num_channels != 1)
1265 				return EINVAL;
1266 
1267 			lgain = rgain = CMPCI_ADJUST_MIC_GAIN(sc,
1268 			    cp->un.value.level[AUDIO_MIXER_LEVEL_MONO]);
1269 			break;
1270 		case CMPCI_PCSPEAKER:
1271 			if (cp->un.value.num_channels != 1)
1272 			    return EINVAL;
1273 			/* FALLTHROUGH */
1274 		case CMPCI_INPUT_GAIN:
1275 		case CMPCI_OUTPUT_GAIN:
1276 			lgain = rgain = CMPCI_ADJUST_2_GAIN(sc,
1277 			    cp->un.value.level[AUDIO_MIXER_LEVEL_MONO]);
1278 			break;
1279 		default:
1280 			switch (cp->un.value.num_channels) {
1281 			case 1:
1282 				lgain = rgain = CMPCI_ADJUST_GAIN(sc,
1283 				    cp->un.value.level[AUDIO_MIXER_LEVEL_MONO]);
1284 				break;
1285 			case 2:
1286 				lgain = CMPCI_ADJUST_GAIN(sc,
1287 				    cp->un.value.level[AUDIO_MIXER_LEVEL_LEFT]);
1288 				rgain = CMPCI_ADJUST_GAIN(sc,
1289 				    cp->un.value.level[AUDIO_MIXER_LEVEL_RIGHT]);
1290 				break;
1291 			default:
1292 				return EINVAL;
1293 			}
1294 			break;
1295 		}
1296 		sc->gain[cp->dev][CMPCI_LEFT]  = lgain;
1297 		sc->gain[cp->dev][CMPCI_RIGHT] = rgain;
1298 
1299 		cmpci_set_mixer_gain(sc, cp->dev);
1300 		break;
1301 
1302 	case CMPCI_RECORD_SOURCE:
1303 		if (cp->type != AUDIO_MIXER_SET)
1304 			return EINVAL;
1305 #ifdef CMPCI_SPDIF_SUPPORT
1306 		if ( cp->un.mask&(1<<CMPCI_SPDIF_IN) )
1307 			cp->un.mask = 1<<CMPCI_SPDIF_IN;
1308 #endif
1309 		return cmpci_set_in_ports(sc, cp->un.mask);
1310 
1311 	case CMPCI_AGC:
1312 		cmpci_mixerreg_write(sc, CMPCI_SB16_MIXER_AGC, cp->un.ord & 1);
1313 		break;
1314 	case CMPCI_CD_OUT_MUTE:
1315 		mask = CMPCI_SB16_SW_CD;
1316 		goto omute;
1317 	case CMPCI_MIC_OUT_MUTE:
1318 		mask = CMPCI_SB16_SW_MIC;
1319 		goto omute;
1320 	case CMPCI_LINE_OUT_MUTE:
1321 		mask = CMPCI_SB16_SW_LINE;
1322 	omute:
1323 		if (cp->type != AUDIO_MIXER_ENUM)
1324 			return EINVAL;
1325 		bits = cmpci_mixerreg_read(sc, CMPCI_SB16_MIXER_OUTMIX);
1326 		sc->gain[cp->dev][CMPCI_LR] = cp->un.ord != 0;
1327 		if (cp->un.ord)
1328 			bits = bits & ~mask;
1329 		else
1330 			bits = bits | mask;
1331 		cmpci_mixerreg_write(sc, CMPCI_SB16_MIXER_OUTMIX, bits);
1332 		break;
1333 
1334 	case CMPCI_MIC_IN_MUTE:
1335 	case CMPCI_MIC_SWAP:
1336 		lmask = rmask = CMPCI_SB16_SW_MIC;
1337 		goto imute;
1338 	case CMPCI_CD_IN_MUTE:
1339 	case CMPCI_CD_SWAP:
1340 		lmask = CMPCI_SB16_SW_CD_L;
1341 		rmask = CMPCI_SB16_SW_CD_R;
1342 		goto imute;
1343 	case CMPCI_LINE_IN_MUTE:
1344 	case CMPCI_LINE_SWAP:
1345 		lmask = CMPCI_SB16_SW_LINE_L;
1346 		rmask = CMPCI_SB16_SW_LINE_R;
1347 		goto imute;
1348 	case CMPCI_FM_IN_MUTE:
1349 	case CMPCI_FM_SWAP:
1350 		lmask = CMPCI_SB16_SW_FM_L;
1351 		rmask = CMPCI_SB16_SW_FM_R;
1352 	imute:
1353 		if (cp->type != AUDIO_MIXER_ENUM)
1354 			return EINVAL;
1355 		mask = lmask | rmask;
1356 		lbits = cmpci_mixerreg_read(sc, CMPCI_SB16_MIXER_ADCMIX_L)
1357 		    & ~mask;
1358 		rbits = cmpci_mixerreg_read(sc, CMPCI_SB16_MIXER_ADCMIX_R)
1359 		    & ~mask;
1360 		sc->gain[cp->dev][CMPCI_LR] = cp->un.ord != 0;
1361 		if (CMPCI_IS_IN_MUTE(cp->dev)) {
1362 			mute = cp->dev;
1363 			swap = mute - CMPCI_CD_IN_MUTE + CMPCI_CD_SWAP;
1364 		} else {
1365 			swap = cp->dev;
1366 			mute = swap + CMPCI_CD_IN_MUTE - CMPCI_CD_SWAP;
1367 		}
1368 		if (sc->gain[swap][CMPCI_LR]) {
1369 			mask = lmask;
1370 			lmask = rmask;
1371 			rmask = mask;
1372 		}
1373 		if (!sc->gain[mute][CMPCI_LR]) {
1374 			lbits = lbits | lmask;
1375 			rbits = rbits | rmask;
1376 		}
1377 		cmpci_mixerreg_write(sc, CMPCI_SB16_MIXER_ADCMIX_L, lbits);
1378 		cmpci_mixerreg_write(sc, CMPCI_SB16_MIXER_ADCMIX_R, rbits);
1379 		break;
1380 
1381 	default:
1382 		return EINVAL;
1383 	}
1384 
1385 	return 0;
1386 }
1387 
1388 int
1389 cmpci_get_port(handle, cp)
1390 	void *handle;
1391 	mixer_ctrl_t *cp;
1392 {
1393 	struct cmpci_softc *sc = handle;
1394 
1395 	switch (cp->dev) {
1396 	case CMPCI_MIC_VOL:
1397 	case CMPCI_LINE_IN_VOL:
1398 		if (cp->un.value.num_channels != 1)
1399 		    return EINVAL;
1400 		/* FALLTHROUGH */
1401 	case CMPCI_TREBLE:
1402 	case CMPCI_BASS:
1403 	case CMPCI_PCSPEAKER:
1404 	case CMPCI_INPUT_GAIN:
1405 	case CMPCI_OUTPUT_GAIN:
1406 	case CMPCI_VOICE_VOL:
1407 	case CMPCI_FM_VOL:
1408 	case CMPCI_CD_VOL:
1409 	case CMPCI_MASTER_VOL:
1410 		switch (cp->un.value.num_channels) {
1411 		case 1:
1412 			cp->un.value.level[AUDIO_MIXER_LEVEL_MONO] =
1413 			    sc->gain[cp->dev][CMPCI_LEFT];
1414 			break;
1415 		case 2:
1416 			cp->un.value.level[AUDIO_MIXER_LEVEL_LEFT] =
1417 			    sc->gain[cp->dev][CMPCI_LEFT];
1418 			cp->un.value.level[AUDIO_MIXER_LEVEL_RIGHT] =
1419 			    sc->gain[cp->dev][CMPCI_RIGHT];
1420 			break;
1421 		default:
1422 			return EINVAL;
1423 		}
1424 		break;
1425 
1426 	case CMPCI_RECORD_SOURCE:
1427 		cp->un.mask = sc->in_mask;
1428 		break;
1429 
1430 	case CMPCI_AGC:
1431 		cp->un.ord = cmpci_mixerreg_read(sc, CMPCI_SB16_MIXER_AGC);
1432 		break;
1433 
1434 	case CMPCI_CD_IN_MUTE:
1435 	case CMPCI_MIC_IN_MUTE:
1436 	case CMPCI_LINE_IN_MUTE:
1437 	case CMPCI_FM_IN_MUTE:
1438 	case CMPCI_CD_SWAP:
1439 	case CMPCI_MIC_SWAP:
1440 	case CMPCI_LINE_SWAP:
1441 	case CMPCI_FM_SWAP:
1442 	case CMPCI_CD_OUT_MUTE:
1443 	case CMPCI_MIC_OUT_MUTE:
1444 	case CMPCI_LINE_OUT_MUTE:
1445 		cp->un.ord = sc->gain[cp->dev][CMPCI_LR];
1446 		break;
1447 
1448 	default:
1449 		return EINVAL;
1450 	}
1451 
1452 	return 0;
1453 }
1454 
1455 /* ARGSUSED */
1456 u_long
1457 cmpci_round_buffersize(handle, bufsize)
1458 	void *handle;
1459 	u_long bufsize;
1460 {
1461 	if (bufsize > 0x10000)
1462 	    bufsize = 0x10000;
1463 
1464 	return bufsize;
1465 }
1466 
1467 paddr_t
1468 cmpci_mappage(handle, addr, offset, prot)
1469 	void *handle;
1470 	void *addr;
1471 	off_t offset;
1472 	int   prot;
1473 {
1474 	struct cmpci_softc *sc = handle;
1475 	struct cmpci_dmanode *p;
1476 
1477 	if ( offset < 0 || (p = cmpci_find_dmamem(sc, addr)) == NULL)
1478 		return -1;
1479 
1480 	return bus_dmamem_mmap(p->cd_tag, p->cd_segs,
1481 			       sizeof(p->cd_segs)/sizeof(p->cd_segs[0]),
1482 			       offset, prot, BUS_DMA_WAITOK);
1483 }
1484 
1485 /* ARGSUSED */
1486 int
1487 cmpci_get_props(handle)
1488 	void *handle;
1489 {
1490 	return AUDIO_PROP_MMAP | AUDIO_PROP_INDEPENDENT | AUDIO_PROP_FULLDUPLEX;
1491 }
1492 
1493 
1494 int
1495 cmpci_trigger_output(handle, start, end, blksize, intr, arg, param)
1496         void *handle;
1497         void *start, *end;
1498         int blksize;
1499         void (*intr) __P((void *));
1500         void *arg;
1501         struct audio_params *param;
1502 {
1503 	struct cmpci_softc *sc = handle;
1504 	struct cmpci_dmanode *p;
1505 	int bps;
1506 
1507 	sc->sc_play.intr = intr;
1508 	sc->sc_play.intr_arg = arg;
1509 	bps = param->channels * param->precision * param->factor / 8;
1510 	if (!bps)
1511 		return EINVAL;
1512 
1513 	/* set DMA frame */
1514 	if (!(p = cmpci_find_dmamem(sc, start)))
1515 		return EINVAL;
1516 	bus_space_write_4(sc->sc_iot, sc->sc_ioh, CMPCI_REG_DMA0_BASE,
1517 			  DMAADDR(p));
1518 	delay(10);
1519 	bus_space_write_2(sc->sc_iot, sc->sc_ioh, CMPCI_REG_DMA0_BYTES,
1520 			  ((caddr_t)end-(caddr_t)start+1)/bps-1);
1521 	delay(10);
1522 
1523 	/* set interrupt count */
1524 	bus_space_write_2(sc->sc_iot, sc->sc_ioh, CMPCI_REG_DMA0_SAMPLES,
1525 			  (blksize+bps-1)/bps-1);
1526 	delay(10);
1527 
1528 	/* start DMA */
1529 	cmpci_reg_clear_4(sc, CMPCI_REG_FUNC_0, CMPCI_REG_CH0_DIR); /* PLAY */
1530 	cmpci_reg_set_4(sc, CMPCI_REG_INTR_CTRL, CMPCI_REG_CH0_INTR_ENABLE);
1531 	cmpci_reg_set_4(sc, CMPCI_REG_FUNC_0, CMPCI_REG_CH0_ENABLE);
1532 
1533 	return 0;
1534 }
1535 
1536 int
1537 cmpci_trigger_input(handle, start, end, blksize, intr, arg, param)
1538         void *handle;
1539         void *start, *end;
1540         int blksize;
1541         void (*intr) __P((void *));
1542         void *arg;
1543         struct audio_params *param;
1544 {
1545 	struct cmpci_softc *sc = handle;
1546 	struct cmpci_dmanode *p;
1547 	int bps;
1548 
1549 	sc->sc_rec.intr = intr;
1550 	sc->sc_rec.intr_arg = arg;
1551 	bps = param->channels*param->precision*param->factor/8;
1552 	if (!bps)
1553 		return EINVAL;
1554 
1555 	/* set DMA frame */
1556 	if (!(p = cmpci_find_dmamem(sc, start)))
1557 		return EINVAL;
1558 	bus_space_write_4(sc->sc_iot, sc->sc_ioh, CMPCI_REG_DMA1_BASE,
1559 			  DMAADDR(p));
1560 	delay(10);
1561 	bus_space_write_2(sc->sc_iot, sc->sc_ioh, CMPCI_REG_DMA1_BYTES,
1562 			  ((caddr_t)end-(caddr_t)start+1)/bps-1);
1563 	delay(10);
1564 
1565 	/* set interrupt count */
1566 	bus_space_write_2(sc->sc_iot, sc->sc_ioh, CMPCI_REG_DMA1_SAMPLES,
1567 			  (blksize+bps-1)/bps-1);
1568 	delay(10);
1569 
1570 	/* start DMA */
1571 	cmpci_reg_set_4(sc, CMPCI_REG_FUNC_0, CMPCI_REG_CH1_DIR); /* REC */
1572 	cmpci_reg_set_4(sc, CMPCI_REG_INTR_CTRL, CMPCI_REG_CH1_INTR_ENABLE);
1573 	cmpci_reg_set_4(sc, CMPCI_REG_FUNC_0, CMPCI_REG_CH1_ENABLE);
1574 
1575 	return 0;
1576 }
1577