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