xref: /openbsd-src/sys/dev/pci/cmpci.c (revision ae3cb403620ab940fbaabb3055fac045a63d56b7)
1 /*	$OpenBSD: cmpci.c,v 1.42 2016/09/19 06:46:44 ratchov Exp $	*/
2 /*	$NetBSD: cmpci.c,v 1.25 2004/10/26 06:32:20 xtraeme Exp $	*/
3 
4 /*
5  * Copyright (c) 2000, 2001 The NetBSD Foundation, Inc.
6  * All rights reserved.
7  *
8  * This code is derived from software contributed to The NetBSD Foundation
9  * by Takuya SHIOZAKI <tshiozak@NetBSD.org> .
10  *
11  * This code is derived from software contributed to The NetBSD Foundation
12  * by ITOH Yasufumi.
13  *
14  * Redistribution and use in source and binary forms, with or without
15  * modification, are permitted provided that the following conditions
16  * are met:
17  * 1. Redistributions of source code must retain the above copyright
18  *    notice, this list of conditions and the following disclaimer.
19  * 2. Redistributions in binary form must reproduce the above copyright
20  *    notice, this list of conditions and the following disclaimer in the
21  *    documentation and/or other materials provided with the distribution.
22  *
23  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
24  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
27  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
28  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
29  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
32  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33  * SUCH DAMAGE.
34  *
35  */
36 
37 /*
38  * C-Media CMI8x38, CMI8768 Audio Chip Support.
39  *
40  * TODO:
41  *   - Joystick support.
42  *
43  */
44 
45 #if defined(AUDIO_DEBUG) || defined(DEBUG)
46 #define DPRINTF(x) if (cmpcidebug) printf x
47 int cmpcidebug = 0;
48 #else
49 #define DPRINTF(x)
50 #endif
51 
52 #include <sys/param.h>
53 #include <sys/systm.h>
54 #include <sys/kernel.h>
55 #include <sys/malloc.h>
56 #include <sys/device.h>
57 
58 #include <dev/pci/pcidevs.h>
59 #include <dev/pci/pcivar.h>
60 
61 #include <sys/audioio.h>
62 #include <dev/audio_if.h>
63 #include <dev/midi_if.h>
64 
65 #include <dev/pci/cmpcireg.h>
66 #include <dev/pci/cmpcivar.h>
67 
68 #include <machine/bus.h>
69 #include <machine/intr.h>
70 
71 /*
72  * Low-level HW interface
73  */
74 uint8_t cmpci_mixerreg_read(struct cmpci_softc *, uint8_t);
75 void cmpci_mixerreg_write(struct cmpci_softc *, uint8_t, uint8_t);
76 void cmpci_reg_partial_write_1(struct cmpci_softc *, int, int,
77 						    unsigned, unsigned);
78 void cmpci_reg_partial_write_4(struct cmpci_softc *, int, int,
79 						    uint32_t, uint32_t);
80 void cmpci_reg_set_1(struct cmpci_softc *, int, uint8_t);
81 void cmpci_reg_clear_1(struct cmpci_softc *, int, uint8_t);
82 void cmpci_reg_set_4(struct cmpci_softc *, int, uint32_t);
83 void cmpci_reg_clear_4(struct cmpci_softc *, int, uint32_t);
84 void cmpci_reg_set_reg_misc(struct cmpci_softc *, uint32_t);
85 void cmpci_reg_clear_reg_misc(struct cmpci_softc *, uint32_t);
86 int cmpci_rate_to_index(int);
87 int cmpci_index_to_rate(int);
88 int cmpci_index_to_divider(int);
89 
90 int cmpci_adjust(int, int);
91 void cmpci_set_mixer_gain(struct cmpci_softc *, int);
92 void cmpci_set_out_ports(struct cmpci_softc *);
93 int cmpci_set_in_ports(struct cmpci_softc *);
94 
95 int cmpci_resume(struct cmpci_softc *);
96 
97 /*
98  * autoconf interface
99  */
100 int cmpci_match(struct device *, void *, void *);
101 void cmpci_attach(struct device *, struct device *, void *);
102 int cmpci_activate(struct device *, int);
103 
104 struct cfdriver cmpci_cd = {
105 	NULL, "cmpci", DV_DULL
106 };
107 
108 struct cfattach cmpci_ca = {
109 	sizeof (struct cmpci_softc), cmpci_match, cmpci_attach, NULL,
110 	cmpci_activate
111 };
112 
113 /* interrupt */
114 int cmpci_intr(void *);
115 
116 /*
117  * DMA stuff
118  */
119 int cmpci_alloc_dmamem(struct cmpci_softc *,
120 				   size_t, int,
121 				   int, caddr_t *);
122 int cmpci_free_dmamem(struct cmpci_softc *, caddr_t,
123 				  int);
124 struct cmpci_dmanode * cmpci_find_dmamem(struct cmpci_softc *,
125 						     caddr_t);
126 
127 /*
128  * Interface to machine independent layer
129  */
130 int cmpci_open(void *, int);
131 void cmpci_close(void *);
132 int cmpci_set_params(void *, int, int,
133 				 struct audio_params *,
134 				 struct audio_params *);
135 int cmpci_round_blocksize(void *, int);
136 int cmpci_halt_output(void *);
137 int cmpci_halt_input(void *);
138 int cmpci_set_port(void *, mixer_ctrl_t *);
139 int cmpci_get_port(void *, mixer_ctrl_t *);
140 int cmpci_query_devinfo(void *, mixer_devinfo_t *);
141 void *cmpci_malloc(void *, int, size_t, int, int);
142 void cmpci_free(void *, void *, int);
143 size_t cmpci_round_buffersize(void *, int, size_t);
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 	cmpci_set_params,	/* set_params */
156 	cmpci_round_blocksize,	/* round_blocksize */
157 	NULL,			/* commit_settings */
158 	NULL,			/* init_output */
159 	NULL,			/* init_input */
160 	NULL,			/* start_output */
161 	NULL,			/* start_input */
162 	cmpci_halt_output,	/* halt_output */
163 	cmpci_halt_input,	/* halt_input */
164 	NULL,			/* speaker_ctl */
165 	NULL,			/* setfd */
166 	cmpci_set_port,		/* set_port */
167 	cmpci_get_port,		/* get_port */
168 	cmpci_query_devinfo,	/* query_devinfo */
169 	cmpci_malloc,		/* malloc */
170 	cmpci_free,		/* free */
171 	cmpci_round_buffersize,/* round_buffersize */
172 	cmpci_get_props,	/* get_props */
173 	cmpci_trigger_output,	/* trigger_output */
174 	cmpci_trigger_input	/* trigger_input */
175 };
176 
177 /*
178  * Low-level HW interface
179  */
180 
181 /* mixer register read/write */
182 uint8_t
183 cmpci_mixerreg_read(struct cmpci_softc *sc, uint8_t no)
184 {
185 	uint8_t ret;
186 
187 	bus_space_write_1(sc->sc_iot, sc->sc_ioh, CMPCI_REG_SBADDR, no);
188 	delay(10);
189 	ret = bus_space_read_1(sc->sc_iot, sc->sc_ioh, CMPCI_REG_SBDATA);
190 	delay(10);
191 	return ret;
192 }
193 
194 void
195 cmpci_mixerreg_write(struct cmpci_softc *sc, uint8_t no, uint8_t val)
196 {
197 	bus_space_write_1(sc->sc_iot, sc->sc_ioh, CMPCI_REG_SBADDR, no);
198 	delay(10);
199 	bus_space_write_1(sc->sc_iot, sc->sc_ioh, CMPCI_REG_SBDATA, val);
200 	delay(10);
201 }
202 
203 /* register partial write */
204 void
205 cmpci_reg_partial_write_1(struct cmpci_softc *sc, int no, int shift,
206     unsigned mask, unsigned val)
207 {
208 	bus_space_write_1(sc->sc_iot, sc->sc_ioh, no,
209 	    (val<<shift) |
210 	    (bus_space_read_1(sc->sc_iot, sc->sc_ioh, no) & ~(mask<<shift)));
211 	delay(10);
212 }
213 
214 void
215 cmpci_reg_partial_write_4(struct cmpci_softc *sc, int no, int shift,
216     uint32_t mask, uint32_t 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 void
226 cmpci_reg_set_1(struct cmpci_softc *sc, int no, uint8_t mask)
227 {
228 	bus_space_write_1(sc->sc_iot, sc->sc_ioh, no,
229 	    (bus_space_read_1(sc->sc_iot, sc->sc_ioh, no) | mask));
230 	delay(10);
231 }
232 
233 void
234 cmpci_reg_clear_1(struct cmpci_softc *sc, int no, uint8_t mask)
235 {
236 	bus_space_write_1(sc->sc_iot, sc->sc_ioh, no,
237 	    (bus_space_read_1(sc->sc_iot, sc->sc_ioh, no) & ~mask));
238 	delay(10);
239 }
240 
241 void
242 cmpci_reg_set_4(struct cmpci_softc *sc, int no, uint32_t mask)
243 {
244 	/* use cmpci_reg_set_reg_misc() for CMPCI_REG_MISC */
245 	KDASSERT(no != CMPCI_REG_MISC);
246 
247 	bus_space_write_4(sc->sc_iot, sc->sc_ioh, no,
248 	    (bus_space_read_4(sc->sc_iot, sc->sc_ioh, no) | mask));
249 	delay(10);
250 }
251 
252 void
253 cmpci_reg_clear_4(struct cmpci_softc *sc, int no, uint32_t mask)
254 {
255 	/* use cmpci_reg_clear_reg_misc() for CMPCI_REG_MISC */
256 	KDASSERT(no != CMPCI_REG_MISC);
257 
258 	bus_space_write_4(sc->sc_iot, sc->sc_ioh, no,
259 	    (bus_space_read_4(sc->sc_iot, sc->sc_ioh, no) & ~mask));
260 	delay(10);
261 }
262 
263 /*
264  * The CMPCI_REG_MISC register needs special handling, since one of
265  * its bits has different read/write values.
266  */
267 void
268 cmpci_reg_set_reg_misc(struct cmpci_softc *sc, uint32_t mask)
269 {
270 	sc->sc_reg_misc |= mask;
271 	bus_space_write_4(sc->sc_iot, sc->sc_ioh, CMPCI_REG_MISC,
272 	    sc->sc_reg_misc);
273 	delay(10);
274 }
275 
276 void
277 cmpci_reg_clear_reg_misc(struct cmpci_softc *sc, uint32_t mask)
278 {
279 	sc->sc_reg_misc &= ~mask;
280 	bus_space_write_4(sc->sc_iot, sc->sc_ioh, CMPCI_REG_MISC,
281 	    sc->sc_reg_misc);
282 	delay(10);
283 }
284 
285 /* rate */
286 static const struct {
287 	int rate;
288 	int divider;
289 } cmpci_rate_table[CMPCI_REG_NUMRATE] = {
290 #define _RATE(n) { n, CMPCI_REG_RATE_ ## n }
291 	_RATE(5512),
292 	_RATE(8000),
293 	_RATE(11025),
294 	_RATE(16000),
295 	_RATE(22050),
296 	_RATE(32000),
297 	_RATE(44100),
298 	_RATE(48000)
299 #undef	_RATE
300 };
301 
302 int
303 cmpci_rate_to_index(int rate)
304 {
305 	int i;
306 
307 	for (i = 0; i < CMPCI_REG_NUMRATE - 1; i++)
308 		if (rate <=
309 		    (cmpci_rate_table[i].rate + cmpci_rate_table[i+1].rate) / 2)
310 			return i;
311 	return i;  /* 48000 */
312 }
313 
314 int
315 cmpci_index_to_rate(int index)
316 {
317 	return cmpci_rate_table[index].rate;
318 }
319 
320 int
321 cmpci_index_to_divider(int index)
322 {
323 	return cmpci_rate_table[index].divider;
324 }
325 
326 const struct pci_matchid cmpci_devices[] = {
327 	{ PCI_VENDOR_CMI, PCI_PRODUCT_CMI_CMI8338A },
328 	{ PCI_VENDOR_CMI, PCI_PRODUCT_CMI_CMI8338B },
329 	{ PCI_VENDOR_CMI, PCI_PRODUCT_CMI_CMI8738 },
330 	{ PCI_VENDOR_CMI, PCI_PRODUCT_CMI_CMI8738B }
331 };
332 
333 /*
334  * interface to configure the device.
335  */
336 
337 int
338 cmpci_match(struct device *parent, void *match, void *aux)
339 {
340 	return (pci_matchbyid((struct pci_attach_args *)aux, cmpci_devices,
341 	    nitems(cmpci_devices)));
342 }
343 
344 void
345 cmpci_attach(struct device *parent, struct device *self, void *aux)
346 {
347 	struct cmpci_softc *sc = (struct cmpci_softc *)self;
348 	struct pci_attach_args *pa = (struct pci_attach_args *)aux;
349 	struct audio_attach_args aa;
350 	pci_intr_handle_t ih;
351 	char const *intrstr;
352 	int i, v, d;
353 
354 	sc->sc_id = pa->pa_id;
355 	sc->sc_class = pa->pa_class;
356 	switch (PCI_PRODUCT(sc->sc_id)) {
357 	case PCI_PRODUCT_CMI_CMI8338A:
358 		/*FALLTHROUGH*/
359 	case PCI_PRODUCT_CMI_CMI8338B:
360 		sc->sc_capable = CMPCI_CAP_CMI8338;
361 		break;
362 	case PCI_PRODUCT_CMI_CMI8738:
363 		/*FALLTHROUGH*/
364 	case PCI_PRODUCT_CMI_CMI8738B:
365 		sc->sc_capable = CMPCI_CAP_CMI8738;
366 		break;
367 	}
368 
369 	/* map I/O space */
370 	if (pci_mapreg_map(pa, CMPCI_PCI_IOBASEREG, PCI_MAPREG_TYPE_IO, 0,
371 			   &sc->sc_iot, &sc->sc_ioh, NULL, NULL, 0)) {
372 		printf(": can't map i/o space\n");
373 		return;
374 	}
375 
376 	/* interrupt */
377 	if (pci_intr_map(pa, &ih)) {
378 		printf(": can't map interrupt\n");
379 		return;
380 	}
381 	intrstr = pci_intr_string(pa->pa_pc, ih);
382 	sc->sc_ih = pci_intr_establish(pa->pa_pc, ih, IPL_AUDIO | IPL_MPSAFE,
383 	    cmpci_intr, sc, sc->sc_dev.dv_xname);
384 	if (sc->sc_ih == NULL) {
385 		printf(": can't establish interrupt");
386 		if (intrstr != NULL)
387 			printf(" at %s", intrstr);
388 		printf("\n");
389 		return;
390 	}
391 	printf(": %s\n", intrstr);
392 
393 	sc->sc_dmat = pa->pa_dmat;
394 
395 	audio_attach_mi(&cmpci_hw_if, sc, &sc->sc_dev);
396 
397 	/* attach OPL device */
398 	aa.type = AUDIODEV_TYPE_OPL;
399 	aa.hwif = NULL;
400 	aa.hdl = NULL;
401 	(void)config_found(&sc->sc_dev, &aa, audioprint);
402 
403 	/* attach MPU-401 device */
404 	aa.type = AUDIODEV_TYPE_MPU;
405 	aa.hwif = NULL;
406 	aa.hdl = NULL;
407 	if (bus_space_subregion(sc->sc_iot, sc->sc_ioh,
408 	    CMPCI_REG_MPU_BASE, CMPCI_REG_MPU_SIZE, &sc->sc_mpu_ioh) == 0)
409 		sc->sc_mpudev = config_found(&sc->sc_dev, &aa, audioprint);
410 
411 	/* get initial value (this is 0 and may be omitted but just in case) */
412 	sc->sc_reg_misc = bus_space_read_4(sc->sc_iot, sc->sc_ioh,
413 	    CMPCI_REG_MISC) & ~CMPCI_REG_SPDIF48K;
414 
415 	/* extra capabilitites check */
416 	d = bus_space_read_4(sc->sc_iot, sc->sc_ioh, CMPCI_REG_INTR_CTRL) &
417 	    CMPCI_REG_CHIP_MASK2;
418 	if (d) {
419 		if (d & CMPCI_REG_CHIP_8768) {
420 			sc->sc_version = 68;
421 			sc->sc_capable |= CMPCI_CAP_4CH | CMPCI_CAP_6CH |
422 			    CMPCI_CAP_8CH;
423 		} else if (d & CMPCI_REG_CHIP_055) {
424 			sc->sc_version = 55;
425 			sc->sc_capable |= CMPCI_CAP_4CH | CMPCI_CAP_6CH;
426 		} else if (d & CMPCI_REG_CHIP_039) {
427 			sc->sc_version = 39;
428 			sc->sc_capable |= CMPCI_CAP_4CH |
429 			    ((d & CMPCI_REG_CHIP_039_6CH) ? CMPCI_CAP_6CH : 0);
430 		} else {
431 			/* unknown version */
432 			sc->sc_version = 0;
433 		}
434 	} else {
435 		d = bus_space_read_4(sc->sc_iot, sc->sc_ioh,
436 		    CMPCI_REG_CHANNEL_FORMAT) & CMPCI_REG_CHIP_MASK1;
437 		if (d)
438 			sc->sc_version = 37;
439 		else
440 			sc->sc_version = 33;
441 	}
442 
443 	cmpci_mixerreg_write(sc, CMPCI_SB16_MIXER_RESET, 0);
444 	cmpci_mixerreg_write(sc, CMPCI_SB16_MIXER_ADCMIX_L, 0);
445 	cmpci_mixerreg_write(sc, CMPCI_SB16_MIXER_ADCMIX_R, 0);
446 	cmpci_mixerreg_write(sc, CMPCI_SB16_MIXER_OUTMIX,
447 	    CMPCI_SB16_SW_CD|CMPCI_SB16_SW_MIC|CMPCI_SB16_SW_LINE);
448 	for (i = 0; i < CMPCI_NDEVS; i++) {
449 		switch(i) {
450 		/*
451 		 * CMI8738 defaults are
452 		 *  master:	0xe0	(0x00 - 0xf8)
453 		 *  FM, DAC:	0xc0	(0x00 - 0xf8)
454 		 *  PC speaker:	0x80	(0x00 - 0xc0)
455 		 *  others:	0
456 		 */
457 		/* volume */
458 		case CMPCI_MASTER_VOL:
459 			v = 128;	/* 224 */
460 			break;
461 		case CMPCI_FM_VOL:
462 		case CMPCI_DAC_VOL:
463 			v = 192;
464 			break;
465 		case CMPCI_PCSPEAKER:
466 			v = 128;
467 			break;
468 
469 		/* booleans, set to true */
470 		case CMPCI_CD_MUTE:
471 		case CMPCI_MIC_MUTE:
472 		case CMPCI_LINE_IN_MUTE:
473 		case CMPCI_AUX_IN_MUTE:
474 			v = 1;
475 			break;
476 
477 		/* volume with inital value 0 */
478 		case CMPCI_CD_VOL:
479 		case CMPCI_LINE_IN_VOL:
480 		case CMPCI_AUX_IN_VOL:
481 		case CMPCI_MIC_VOL:
482 		case CMPCI_MIC_RECVOL:
483 			/* FALLTHROUGH */
484 
485 		/* others are cleared */
486 		case CMPCI_MIC_PREAMP:
487 		case CMPCI_RECORD_SOURCE:
488 		case CMPCI_PLAYBACK_MODE:
489 		case CMPCI_SPDIF_IN_SELECT:
490 		case CMPCI_SPDIF_IN_PHASE:
491 		case CMPCI_SPDIF_LOOP:
492 		case CMPCI_SPDIF_OUT_PLAYBACK:
493 		case CMPCI_SPDIF_OUT_VOLTAGE:
494 		case CMPCI_MONITOR_DAC:
495 		case CMPCI_REAR:
496 		case CMPCI_INDIVIDUAL:
497 		case CMPCI_REVERSE:
498 		case CMPCI_SURROUND:
499 		default:
500 			v = 0;
501 			break;
502 		}
503 		sc->sc_gain[i][CMPCI_LEFT] = sc->sc_gain[i][CMPCI_RIGHT] = v;
504 		cmpci_set_mixer_gain(sc, i);
505 	}
506 
507 	sc->sc_play_channel = 0;
508 }
509 
510 int
511 cmpci_activate(struct device *self, int act)
512 {
513 	struct cmpci_softc *sc = (struct cmpci_softc *)self;
514 	int rv = 0;
515 
516 	switch (act) {
517 	case DVACT_RESUME:
518 		cmpci_resume(sc);
519 		rv = config_activate_children(self, act);
520 		break;
521 	default:
522 		rv = config_activate_children(self, act);
523 		break;
524 	}
525 	return (rv);
526 }
527 
528 int
529 cmpci_resume(struct cmpci_softc *sc)
530 {
531 	int i;
532 
533 	cmpci_mixerreg_write(sc, CMPCI_SB16_MIXER_RESET, 0);
534 	for (i = 0; i < CMPCI_NDEVS; i++)
535 		cmpci_set_mixer_gain(sc, i);
536 
537 	return 0;
538 }
539 
540 int
541 cmpci_intr(void *handle)
542 {
543 	struct cmpci_softc *sc = handle;
544 	struct cmpci_channel *chan;
545 	uint32_t intrstat;
546 	uint16_t hwpos;
547 
548 	mtx_enter(&audio_lock);
549 	intrstat = bus_space_read_4(sc->sc_iot, sc->sc_ioh,
550 	    CMPCI_REG_INTR_STATUS);
551 
552 	if (!(intrstat & CMPCI_REG_ANY_INTR)) {
553 		mtx_leave(&audio_lock);
554 		return 0;
555 	}
556 
557 	delay(10);
558 
559 	/* disable and reset intr */
560 	if (intrstat & CMPCI_REG_CH0_INTR)
561 		cmpci_reg_clear_4(sc, CMPCI_REG_INTR_CTRL,
562 		   CMPCI_REG_CH0_INTR_ENABLE);
563 	if (intrstat & CMPCI_REG_CH1_INTR)
564 		cmpci_reg_clear_4(sc, CMPCI_REG_INTR_CTRL,
565 		    CMPCI_REG_CH1_INTR_ENABLE);
566 
567 	if (intrstat & CMPCI_REG_CH0_INTR) {
568 		chan = &sc->sc_ch0;
569 		if (chan->intr != NULL) {
570 			hwpos = bus_space_read_2(sc->sc_iot, sc->sc_ioh,
571 			    CMPCI_REG_DMA0_BYTES);
572 			hwpos = hwpos * chan->bps / chan->blksize;
573 			hwpos = chan->nblocks - hwpos - 1;
574 			while (chan->swpos != hwpos) {
575 				(*chan->intr)(chan->intr_arg);
576 				chan->swpos++;
577 				if (chan->swpos >= chan->nblocks)
578 					chan->swpos = 0;
579 				if (chan->swpos != hwpos) {
580 					DPRINTF(("%s: DMA0 hwpos=%d swpos=%d\n",
581 					    __func__, hwpos, chan->swpos));
582 				}
583 			}
584 		}
585 	}
586 	if (intrstat & CMPCI_REG_CH1_INTR) {
587 		chan = &sc->sc_ch1;
588 		if (chan->intr != NULL) {
589 			hwpos = bus_space_read_2(sc->sc_iot, sc->sc_ioh,
590 			    CMPCI_REG_DMA1_BYTES);
591 			hwpos = hwpos * chan->bps / chan->blksize;
592 			hwpos = chan->nblocks - hwpos - 1;
593 			while (chan->swpos != hwpos) {
594 				(*chan->intr)(chan->intr_arg);
595 				chan->swpos++;
596 				if (chan->swpos >= chan->nblocks)
597 					chan->swpos = 0;
598 				if (chan->swpos != hwpos) {
599 					DPRINTF(("%s: DMA1 hwpos=%d swpos=%d\n",
600 					    __func__, hwpos, chan->swpos));
601 				}
602 			}
603 		}
604 	}
605 
606 	/* enable intr */
607 	if (intrstat & CMPCI_REG_CH0_INTR)
608 		cmpci_reg_set_4(sc, CMPCI_REG_INTR_CTRL,
609 		    CMPCI_REG_CH0_INTR_ENABLE);
610 	if (intrstat & CMPCI_REG_CH1_INTR)
611 		cmpci_reg_set_4(sc, CMPCI_REG_INTR_CTRL,
612 		    CMPCI_REG_CH1_INTR_ENABLE);
613 
614 #if 0
615 	if (intrstat & CMPCI_REG_UART_INTR && sc->sc_mpudev != NULL)
616 		mpu_intr(sc->sc_mpudev);
617 #endif
618 
619 	mtx_leave(&audio_lock);
620 	return 1;
621 }
622 
623 /* open/close */
624 int
625 cmpci_open(void *handle, int flags)
626 {
627 	return 0;
628 }
629 
630 void
631 cmpci_close(void *handle)
632 {
633 }
634 
635 int
636 cmpci_set_params(void *handle, int setmode, int usemode,
637     struct audio_params *play, struct audio_params *rec)
638 {
639 	int i;
640 	struct cmpci_softc *sc = handle;
641 
642 	for (i = 0; i < 2; i++) {
643 		int md_format;
644 		int md_divide;
645 		int md_index;
646 		int mode;
647 		struct audio_params *p;
648 
649 		switch (i) {
650 		case 0:
651 			mode = AUMODE_PLAY;
652 			p = play;
653 			break;
654 		case 1:
655 			mode = AUMODE_RECORD;
656 			p = rec;
657 			break;
658 		default:
659 			return EINVAL;
660 		}
661 
662 		if (!(setmode & mode))
663 			continue;
664 
665 		if (setmode & AUMODE_RECORD) {
666 			if (p->channels > 2)
667 				p->channels = 2;
668 			sc->sc_play_channel = 0;
669 			cmpci_reg_clear_reg_misc(sc, CMPCI_REG_ENDBDAC);
670 			cmpci_reg_clear_reg_misc(sc, CMPCI_REG_XCHGDAC);
671 		} else {
672 			sc->sc_play_channel = 1;
673 			cmpci_reg_set_reg_misc(sc, CMPCI_REG_ENDBDAC);
674 			cmpci_reg_set_reg_misc(sc, CMPCI_REG_XCHGDAC);
675 		}
676 
677 		cmpci_reg_clear_4(sc, CMPCI_REG_LEGACY_CTRL,
678 		    CMPCI_REG_NXCHG);
679 		if (sc->sc_capable & CMPCI_CAP_4CH)
680 			cmpci_reg_clear_4(sc, CMPCI_REG_CHANNEL_FORMAT,
681 			    CMPCI_REG_CHB3D);
682 		if (sc->sc_capable & CMPCI_CAP_6CH) {
683 			cmpci_reg_clear_4(sc, CMPCI_REG_CHANNEL_FORMAT,
684 			    CMPCI_REG_CHB3D5C);
685 			cmpci_reg_clear_4(sc, CMPCI_REG_LEGACY_CTRL,
686 		    	    CMPCI_REG_CHB3D6C);
687 			cmpci_reg_clear_reg_misc(sc, CMPCI_REG_ENCENTER);
688 		}
689 		if (sc->sc_capable & CMPCI_CAP_8CH)
690 			cmpci_reg_clear_4(sc, CMPCI_REG_8768_MISC,
691 			    CMPCI_REG_CHB3D8C);
692 
693 		/* format */
694 		switch (p->channels) {
695 		case 1:
696 			md_format = CMPCI_REG_FORMAT_MONO;
697 			break;
698 		case 2:
699 			md_format = CMPCI_REG_FORMAT_STEREO;
700 			break;
701 		case 4:
702 			if (mode & AUMODE_PLAY) {
703 				if (sc->sc_capable & CMPCI_CAP_4CH) {
704 					cmpci_reg_clear_reg_misc(sc,
705 					    CMPCI_REG_N4SPK3D);
706 					cmpci_reg_set_4(sc,
707 					    CMPCI_REG_CHANNEL_FORMAT,
708 					    CMPCI_REG_CHB3D);
709 					cmpci_reg_set_4(sc,
710 					    CMPCI_REG_LEGACY_CTRL,
711 					    CMPCI_REG_NXCHG);
712 				} else
713 					p->channels = 2;
714 			}
715 			md_format = CMPCI_REG_FORMAT_STEREO;
716 			break;
717 		case 6:
718 			if (mode & AUMODE_PLAY) {
719 				if (sc->sc_capable & CMPCI_CAP_6CH) {
720 					cmpci_reg_clear_reg_misc(sc,
721 					    CMPCI_REG_N4SPK3D);
722 					cmpci_reg_set_4(sc,
723 					    CMPCI_REG_CHANNEL_FORMAT,
724 					    CMPCI_REG_CHB3D5C);
725 					cmpci_reg_set_4(sc,
726 					    CMPCI_REG_LEGACY_CTRL,
727 					    CMPCI_REG_CHB3D6C);
728 					cmpci_reg_set_reg_misc(sc,
729 					    CMPCI_REG_ENCENTER);
730 					cmpci_reg_set_4(sc,
731 					    CMPCI_REG_LEGACY_CTRL,
732 					    CMPCI_REG_NXCHG);
733 				} else
734 					p->channels = 2;
735 			}
736 			md_format = CMPCI_REG_FORMAT_STEREO;
737 			break;
738 		case 8:
739 			if (mode & AUMODE_PLAY) {
740 				if (sc->sc_capable & CMPCI_CAP_8CH) {
741 					cmpci_reg_clear_reg_misc(sc,
742 					    CMPCI_REG_N4SPK3D);
743 					cmpci_reg_set_4(sc,
744 					    CMPCI_REG_CHANNEL_FORMAT,
745 					    CMPCI_REG_CHB3D5C);
746 					cmpci_reg_set_4(sc,
747 					    CMPCI_REG_LEGACY_CTRL,
748 					    CMPCI_REG_CHB3D6C);
749 					cmpci_reg_set_reg_misc(sc,
750 					    CMPCI_REG_ENCENTER);
751 					cmpci_reg_set_4(sc,
752 					    CMPCI_REG_8768_MISC,
753 					    CMPCI_REG_CHB3D8C);
754 					cmpci_reg_set_4(sc,
755 					    CMPCI_REG_LEGACY_CTRL,
756 					    CMPCI_REG_NXCHG);
757 				} else
758 					p->channels = 2;
759 			}
760 			md_format = CMPCI_REG_FORMAT_STEREO;
761 			break;
762 		default:
763 			return (EINVAL);
764 		}
765 		if (p->precision >= 16) {
766 			p->precision = 16;
767 			p->encoding = AUDIO_ENCODING_SLINEAR_LE;
768 			md_format |= CMPCI_REG_FORMAT_16BIT;
769 		} else {
770 			p->precision = 8;
771 			p->encoding = AUDIO_ENCODING_ULINEAR_LE;
772 			md_format |= CMPCI_REG_FORMAT_8BIT;
773 		}
774 		p->bps = AUDIO_BPS(p->precision);
775 		p->msb = 1;
776 		if (mode & AUMODE_PLAY) {
777 			if (sc->sc_play_channel == 1) {
778 				cmpci_reg_partial_write_4(sc,
779 				   CMPCI_REG_CHANNEL_FORMAT,
780 				   CMPCI_REG_CH1_FORMAT_SHIFT,
781 				   CMPCI_REG_CH1_FORMAT_MASK, md_format);
782 			} else {
783 				cmpci_reg_partial_write_4(sc,
784 				   CMPCI_REG_CHANNEL_FORMAT,
785 				   CMPCI_REG_CH0_FORMAT_SHIFT,
786 				   CMPCI_REG_CH0_FORMAT_MASK, md_format);
787 			}
788 		} else {
789 			cmpci_reg_partial_write_4(sc,
790 			   CMPCI_REG_CHANNEL_FORMAT,
791 			   CMPCI_REG_CH1_FORMAT_SHIFT,
792 			   CMPCI_REG_CH1_FORMAT_MASK, md_format);
793 		}
794 		/* sample rate */
795 		md_index = cmpci_rate_to_index(p->sample_rate);
796 		md_divide = cmpci_index_to_divider(md_index);
797 		p->sample_rate = cmpci_index_to_rate(md_index);
798 		DPRINTF(("%s: sample:%d, divider=%d\n",
799 			 sc->sc_dev.dv_xname, (int)p->sample_rate, md_divide));
800 		if (mode & AUMODE_PLAY) {
801 			if (sc->sc_play_channel == 1) {
802 				cmpci_reg_partial_write_4(sc,
803 				    CMPCI_REG_FUNC_1, CMPCI_REG_ADC_FS_SHIFT,
804 				    CMPCI_REG_ADC_FS_MASK, md_divide);
805 				sc->sc_ch1.md_divide = md_divide;
806 			} else {
807 				cmpci_reg_partial_write_4(sc,
808 				    CMPCI_REG_FUNC_1, CMPCI_REG_DAC_FS_SHIFT,
809 				    CMPCI_REG_DAC_FS_MASK, md_divide);
810 				sc->sc_ch0.md_divide = md_divide;
811 			}
812 		} else {
813 			cmpci_reg_partial_write_4(sc,
814 			    CMPCI_REG_FUNC_1, CMPCI_REG_ADC_FS_SHIFT,
815 			    CMPCI_REG_ADC_FS_MASK, md_divide);
816 			sc->sc_ch1.md_divide = md_divide;
817 		}
818 	}
819 
820 	return 0;
821 }
822 
823 /* ARGSUSED */
824 int
825 cmpci_round_blocksize(void *handle, int block)
826 {
827 	return ((block + 3) & -4);
828 }
829 
830 int
831 cmpci_halt_output(void *handle)
832 {
833 	struct cmpci_softc *sc = handle;
834 	uint32_t reg_intr, reg_enable, reg_reset;
835 
836 	mtx_enter(&audio_lock);
837 	if (sc->sc_play_channel == 1) {
838 		sc->sc_ch1.intr = NULL;
839 		reg_intr = CMPCI_REG_CH1_INTR_ENABLE;
840 		reg_enable = CMPCI_REG_CH1_ENABLE;
841 		reg_reset = CMPCI_REG_CH1_RESET;
842 	} else {
843 		sc->sc_ch0.intr = NULL;
844 		reg_intr = CMPCI_REG_CH0_INTR_ENABLE;
845 		reg_enable = CMPCI_REG_CH0_ENABLE;
846 		reg_reset = CMPCI_REG_CH0_RESET;
847 	}
848 	cmpci_reg_clear_4(sc, CMPCI_REG_INTR_CTRL, reg_intr);
849 	cmpci_reg_clear_4(sc, CMPCI_REG_FUNC_0, reg_enable);
850 	/* wait for reset DMA */
851 	cmpci_reg_set_4(sc, CMPCI_REG_FUNC_0, reg_reset);
852 	delay(10);
853 	cmpci_reg_clear_4(sc, CMPCI_REG_FUNC_0, reg_reset);
854 	mtx_leave(&audio_lock);
855 	return 0;
856 }
857 
858 int
859 cmpci_halt_input(void *handle)
860 {
861 	struct cmpci_softc *sc = handle;
862 
863 	mtx_enter(&audio_lock);
864 	sc->sc_ch1.intr = NULL;
865 	cmpci_reg_clear_4(sc, CMPCI_REG_INTR_CTRL, CMPCI_REG_CH1_INTR_ENABLE);
866 	cmpci_reg_clear_4(sc, CMPCI_REG_FUNC_0, CMPCI_REG_CH1_ENABLE);
867 	/* wait for reset DMA */
868 	cmpci_reg_set_4(sc, CMPCI_REG_FUNC_0, CMPCI_REG_CH1_RESET);
869 	delay(10);
870 	cmpci_reg_clear_4(sc, CMPCI_REG_FUNC_0, CMPCI_REG_CH1_RESET);
871 	mtx_leave(&audio_lock);
872 	return 0;
873 }
874 
875 /* mixer device information */
876 int
877 cmpci_query_devinfo(void *handle, mixer_devinfo_t *dip)
878 {
879 	static const char *const mixer_port_names[] = {
880 		AudioNdac, AudioNfmsynth, AudioNcd, AudioNline, AudioNaux,
881 		AudioNmicrophone
882 	};
883 	static const char *const mixer_classes[] = {
884 		AudioCinputs, AudioCoutputs, AudioCrecord, CmpciCplayback,
885 		CmpciCspdif
886 	};
887 	struct cmpci_softc *sc = handle;
888 	int i;
889 
890 	dip->prev = dip->next = AUDIO_MIXER_LAST;
891 
892 	switch (dip->index) {
893 	case CMPCI_INPUT_CLASS:
894 	case CMPCI_OUTPUT_CLASS:
895 	case CMPCI_RECORD_CLASS:
896 	case CMPCI_PLAYBACK_CLASS:
897 	case CMPCI_SPDIF_CLASS:
898 		dip->type = AUDIO_MIXER_CLASS;
899 		dip->mixer_class = dip->index;
900 		strlcpy(dip->label.name,
901 		    mixer_classes[dip->index - CMPCI_INPUT_CLASS],
902 		    sizeof dip->label.name);
903 		return 0;
904 
905 	case CMPCI_AUX_IN_VOL:
906 		dip->un.v.delta = 1 << (8 - CMPCI_REG_AUX_VALBITS);
907 		goto vol1;
908 	case CMPCI_DAC_VOL:
909 	case CMPCI_FM_VOL:
910 	case CMPCI_CD_VOL:
911 	case CMPCI_LINE_IN_VOL:
912 	case CMPCI_MIC_VOL:
913 		dip->un.v.delta = 1 << (8 - CMPCI_SB16_MIXER_VALBITS);
914 	vol1:	dip->mixer_class = CMPCI_INPUT_CLASS;
915 		dip->next = dip->index + 6;	/* CMPCI_xxx_MUTE */
916 		strlcpy(dip->label.name, mixer_port_names[dip->index],
917 		    sizeof dip->label.name);
918 		dip->un.v.num_channels = (dip->index == CMPCI_MIC_VOL ? 1 : 2);
919 	vol:
920 		dip->type = AUDIO_MIXER_VALUE;
921 		strlcpy(dip->un.v.units.name, AudioNvolume,
922 		    sizeof dip->un.v.units.name);
923 		return 0;
924 
925 	case CMPCI_MIC_MUTE:
926 		dip->next = CMPCI_MIC_PREAMP;
927 		/* FALLTHROUGH */
928 	case CMPCI_DAC_MUTE:
929 	case CMPCI_FM_MUTE:
930 	case CMPCI_CD_MUTE:
931 	case CMPCI_LINE_IN_MUTE:
932 	case CMPCI_AUX_IN_MUTE:
933 		dip->prev = dip->index - 6;	/* CMPCI_xxx_VOL */
934 		dip->mixer_class = CMPCI_INPUT_CLASS;
935 		strlcpy(dip->label.name, AudioNmute, sizeof dip->label.name);
936 		goto on_off;
937 	on_off:
938 		dip->type = AUDIO_MIXER_ENUM;
939 		dip->un.e.num_mem = 2;
940 		strlcpy(dip->un.e.member[0].label.name, AudioNoff,
941 		    sizeof dip->un.e.member[0].label.name);
942 		dip->un.e.member[0].ord = 0;
943 		strlcpy(dip->un.e.member[1].label.name, AudioNon,
944 		    sizeof dip->un.e.member[1].label.name);
945 		dip->un.e.member[1].ord = 1;
946 		return 0;
947 
948 	case CMPCI_MIC_PREAMP:
949 		dip->mixer_class = CMPCI_INPUT_CLASS;
950 		dip->prev = CMPCI_MIC_MUTE;
951 		strlcpy(dip->label.name, AudioNpreamp, sizeof dip->label.name);
952 		goto on_off;
953 	case CMPCI_PCSPEAKER:
954 		dip->mixer_class = CMPCI_INPUT_CLASS;
955 		strlcpy(dip->label.name, AudioNspeaker, sizeof dip->label.name);
956 		dip->un.v.num_channels = 1;
957 		dip->un.v.delta = 1 << (8 - CMPCI_SB16_MIXER_SPEAKER_VALBITS);
958 		goto vol;
959 	case CMPCI_RECORD_SOURCE:
960 		dip->mixer_class = CMPCI_RECORD_CLASS;
961 		strlcpy(dip->label.name, AudioNsource, sizeof dip->label.name);
962 		dip->type = AUDIO_MIXER_SET;
963 		dip->un.s.num_mem = 7;
964 		strlcpy(dip->un.s.member[0].label.name, AudioNmicrophone,
965 		    sizeof dip->un.s.member[0].label.name);
966 		dip->un.s.member[0].mask = CMPCI_RECORD_SOURCE_MIC;
967 		strlcpy(dip->un.s.member[1].label.name, AudioNcd,
968 		    sizeof dip->un.s.member[1].label.name);
969 		dip->un.s.member[1].mask = CMPCI_RECORD_SOURCE_CD;
970 		strlcpy(dip->un.s.member[2].label.name, AudioNline,
971 		    sizeof dip->un.s.member[2].label.name);
972 		dip->un.s.member[2].mask = CMPCI_RECORD_SOURCE_LINE_IN;
973 		strlcpy(dip->un.s.member[3].label.name, AudioNaux,
974 		    sizeof dip->un.s.member[3].label.name);
975 		dip->un.s.member[3].mask = CMPCI_RECORD_SOURCE_AUX_IN;
976 		strlcpy(dip->un.s.member[4].label.name, AudioNwave,
977 		    sizeof dip->un.s.member[4].label.name);
978 		dip->un.s.member[4].mask = CMPCI_RECORD_SOURCE_WAVE;
979 		strlcpy(dip->un.s.member[5].label.name, AudioNfmsynth,
980 		    sizeof dip->un.s.member[5].label.name);
981 		dip->un.s.member[5].mask = CMPCI_RECORD_SOURCE_FM;
982 		strlcpy(dip->un.s.member[6].label.name, CmpciNspdif,
983 		    sizeof dip->un.s.member[6].label.name);
984 		dip->un.s.member[6].mask = CMPCI_RECORD_SOURCE_SPDIF;
985 		return 0;
986 	case CMPCI_MIC_RECVOL:
987 		dip->mixer_class = CMPCI_RECORD_CLASS;
988 		strlcpy(dip->label.name, AudioNmicrophone, sizeof dip->label.name);
989 		dip->un.v.num_channels = 1;
990 		dip->un.v.delta = 1 << (8 - CMPCI_REG_ADMIC_VALBITS);
991 		goto vol;
992 
993 	case CMPCI_PLAYBACK_MODE:
994 		dip->mixer_class = CMPCI_PLAYBACK_CLASS;
995 		dip->type = AUDIO_MIXER_ENUM;
996 		strlcpy(dip->label.name, AudioNmode, sizeof dip->label.name);
997 		dip->un.e.num_mem = 2;
998 		strlcpy(dip->un.e.member[0].label.name, AudioNdac,
999 		    sizeof dip->un.e.member[0].label.name);
1000 		dip->un.e.member[0].ord = CMPCI_PLAYBACK_MODE_WAVE;
1001 		strlcpy(dip->un.e.member[1].label.name, CmpciNspdif,
1002 		    sizeof dip->un.e.member[1].label.name);
1003 		dip->un.e.member[1].ord = CMPCI_PLAYBACK_MODE_SPDIF;
1004 		return 0;
1005 	case CMPCI_SPDIF_IN_SELECT:
1006 		dip->mixer_class = CMPCI_SPDIF_CLASS;
1007 		dip->type = AUDIO_MIXER_ENUM;
1008 		dip->next = CMPCI_SPDIF_IN_PHASE;
1009 		strlcpy(dip->label.name, AudioNinput, sizeof dip->label.name);
1010 		i = 0;
1011 		strlcpy(dip->un.e.member[i].label.name, CmpciNspdin1,
1012 		    sizeof dip->un.e.member[i].label.name);
1013 		dip->un.e.member[i++].ord = CMPCI_SPDIF_IN_SPDIN1;
1014 		if (CMPCI_ISCAP(sc, 2ND_SPDIN)) {
1015 			strlcpy(dip->un.e.member[i].label.name, CmpciNspdin2,
1016 			    sizeof dip->un.e.member[i].label.name);
1017 			dip->un.e.member[i++].ord = CMPCI_SPDIF_IN_SPDIN2;
1018 		}
1019 		strlcpy(dip->un.e.member[i].label.name, CmpciNspdout,
1020 		    sizeof dip->un.e.member[i].label.name);
1021 		dip->un.e.member[i++].ord = CMPCI_SPDIF_IN_SPDOUT;
1022 		dip->un.e.num_mem = i;
1023 		return 0;
1024 	case CMPCI_SPDIF_IN_PHASE:
1025 		dip->mixer_class = CMPCI_SPDIF_CLASS;
1026 		dip->prev = CMPCI_SPDIF_IN_SELECT;
1027 		strlcpy(dip->label.name, CmpciNphase, sizeof dip->label.name);
1028 		dip->type = AUDIO_MIXER_ENUM;
1029 		dip->un.e.num_mem = 2;
1030 		strlcpy(dip->un.e.member[0].label.name, CmpciNpositive,
1031 		    sizeof dip->un.e.member[0].label.name);
1032 		dip->un.e.member[0].ord = CMPCI_SPDIF_IN_PHASE_POSITIVE;
1033 		strlcpy(dip->un.e.member[1].label.name, CmpciNnegative,
1034 		    sizeof dip->un.e.member[1].label.name);
1035 		dip->un.e.member[1].ord = CMPCI_SPDIF_IN_PHASE_NEGATIVE;
1036 		return 0;
1037 	case CMPCI_SPDIF_LOOP:
1038 		dip->mixer_class = CMPCI_SPDIF_CLASS;
1039 		dip->next = CMPCI_SPDIF_OUT_PLAYBACK;
1040 		strlcpy(dip->label.name, AudioNoutput, sizeof dip->label.name);
1041 		dip->type = AUDIO_MIXER_ENUM;
1042 		dip->un.e.num_mem = 2;
1043 		strlcpy(dip->un.e.member[0].label.name, CmpciNplayback,
1044 		    sizeof dip->un.e.member[0].label.name);
1045 		dip->un.e.member[0].ord = CMPCI_SPDIF_LOOP_OFF;
1046 		strlcpy(dip->un.e.member[1].label.name, CmpciNspdin,
1047 		    sizeof dip->un.e.member[1].label.name);
1048 		dip->un.e.member[1].ord = CMPCI_SPDIF_LOOP_ON;
1049 		return 0;
1050 	case CMPCI_SPDIF_OUT_PLAYBACK:
1051 		dip->mixer_class = CMPCI_SPDIF_CLASS;
1052 		dip->prev = CMPCI_SPDIF_LOOP;
1053 		dip->next = CMPCI_SPDIF_OUT_VOLTAGE;
1054 		strlcpy(dip->label.name, CmpciNplayback, sizeof dip->label.name);
1055 		dip->type = AUDIO_MIXER_ENUM;
1056 		dip->un.e.num_mem = 2;
1057 		strlcpy(dip->un.e.member[0].label.name, AudioNwave,
1058 		    sizeof dip->un.e.member[0].label.name);
1059 		dip->un.e.member[0].ord = CMPCI_SPDIF_OUT_PLAYBACK_WAVE;
1060 		strlcpy(dip->un.e.member[1].label.name, CmpciNlegacy,
1061 		    sizeof dip->un.e.member[1].label.name);
1062 		dip->un.e.member[1].ord = CMPCI_SPDIF_OUT_PLAYBACK_LEGACY;
1063 		return 0;
1064 	case CMPCI_SPDIF_OUT_VOLTAGE:
1065 		dip->mixer_class = CMPCI_SPDIF_CLASS;
1066 		dip->prev = CMPCI_SPDIF_OUT_PLAYBACK;
1067 		strlcpy(dip->label.name, CmpciNvoltage, sizeof dip->label.name);
1068 		dip->type = AUDIO_MIXER_ENUM;
1069 		dip->un.e.num_mem = 2;
1070 		strlcpy(dip->un.e.member[0].label.name, CmpciNhigh_v,
1071 		    sizeof dip->un.e.member[0].label.name);
1072 		dip->un.e.member[0].ord = CMPCI_SPDIF_OUT_VOLTAGE_HIGH;
1073 		strlcpy(dip->un.e.member[1].label.name, CmpciNlow_v,
1074 		    sizeof dip->un.e.member[1].label.name);
1075 		dip->un.e.member[1].ord = CMPCI_SPDIF_OUT_VOLTAGE_LOW;
1076 		return 0;
1077 	case CMPCI_MONITOR_DAC:
1078 		dip->mixer_class = CMPCI_SPDIF_CLASS;
1079 		strlcpy(dip->label.name, AudioNmonitor, sizeof dip->label.name);
1080 		dip->type = AUDIO_MIXER_ENUM;
1081 		dip->un.e.num_mem = 3;
1082 		strlcpy(dip->un.e.member[0].label.name, AudioNoff,
1083 		    sizeof dip->un.e.member[0].label.name);
1084 		dip->un.e.member[0].ord = CMPCI_MONITOR_DAC_OFF;
1085 		strlcpy(dip->un.e.member[1].label.name, CmpciNspdin,
1086 		    sizeof dip->un.e.member[1].label.name);
1087 		dip->un.e.member[1].ord = CMPCI_MONITOR_DAC_SPDIN;
1088 		strlcpy(dip->un.e.member[2].label.name, CmpciNspdout,
1089 		    sizeof dip->un.e.member[2].label.name);
1090 		dip->un.e.member[2].ord = CMPCI_MONITOR_DAC_SPDOUT;
1091 		return 0;
1092 
1093 	case CMPCI_MASTER_VOL:
1094 		dip->mixer_class = CMPCI_OUTPUT_CLASS;
1095 		strlcpy(dip->label.name, AudioNmaster, sizeof dip->label.name);
1096 		dip->un.v.num_channels = 2;
1097 		dip->un.v.delta = 1 << (8 - CMPCI_SB16_MIXER_VALBITS);
1098 		goto vol;
1099 	case CMPCI_REAR:
1100 		dip->mixer_class = CMPCI_OUTPUT_CLASS;
1101 		dip->next = CMPCI_INDIVIDUAL;
1102 		strlcpy(dip->label.name, CmpciNrear, sizeof dip->label.name);
1103 		goto on_off;
1104 	case CMPCI_INDIVIDUAL:
1105 		dip->mixer_class = CMPCI_OUTPUT_CLASS;
1106 		dip->prev = CMPCI_REAR;
1107 		dip->next = CMPCI_REVERSE;
1108 		strlcpy(dip->label.name, CmpciNindividual, sizeof dip->label.name);
1109 		goto on_off;
1110 	case CMPCI_REVERSE:
1111 		dip->mixer_class = CMPCI_OUTPUT_CLASS;
1112 		dip->prev = CMPCI_INDIVIDUAL;
1113 		strlcpy(dip->label.name, CmpciNreverse, sizeof dip->label.name);
1114 		goto on_off;
1115 	case CMPCI_SURROUND:
1116 		dip->mixer_class = CMPCI_OUTPUT_CLASS;
1117 		strlcpy(dip->label.name, CmpciNsurround, sizeof dip->label.name);
1118 		goto on_off;
1119 	}
1120 
1121 	return ENXIO;
1122 }
1123 
1124 int
1125 cmpci_alloc_dmamem(struct cmpci_softc *sc, size_t size, int type, int flags,
1126     caddr_t *r_addr)
1127 {
1128 	int error = 0;
1129 	struct cmpci_dmanode *n;
1130 	int w;
1131 
1132 	n = malloc(sizeof(struct cmpci_dmanode), type, flags);
1133 	if (n == NULL) {
1134 		error = ENOMEM;
1135 		goto quit;
1136 	}
1137 
1138 	w = (flags & M_NOWAIT) ? BUS_DMA_NOWAIT : BUS_DMA_WAITOK;
1139 #define CMPCI_DMABUF_ALIGN    0x4
1140 #define CMPCI_DMABUF_BOUNDARY 0x0
1141 	n->cd_tag = sc->sc_dmat;
1142 	n->cd_size = size;
1143 	error = bus_dmamem_alloc(n->cd_tag, n->cd_size,
1144 	    CMPCI_DMABUF_ALIGN, CMPCI_DMABUF_BOUNDARY, n->cd_segs,
1145 	    nitems(n->cd_segs), &n->cd_nsegs, w);
1146 	if (error)
1147 		goto mfree;
1148 	error = bus_dmamem_map(n->cd_tag, n->cd_segs, n->cd_nsegs, n->cd_size,
1149 	    &n->cd_addr, w | BUS_DMA_COHERENT);
1150 	if (error)
1151 		goto dmafree;
1152 	error = bus_dmamap_create(n->cd_tag, n->cd_size, 1, n->cd_size, 0,
1153 	    w, &n->cd_map);
1154 	if (error)
1155 		goto unmap;
1156 	error = bus_dmamap_load(n->cd_tag, n->cd_map, n->cd_addr, n->cd_size,
1157 	    NULL, w);
1158 	if (error)
1159 		goto destroy;
1160 
1161 	n->cd_next = sc->sc_dmap;
1162 	sc->sc_dmap = n;
1163 	*r_addr = KVADDR(n);
1164 	return 0;
1165 
1166  destroy:
1167 	bus_dmamap_destroy(n->cd_tag, n->cd_map);
1168  unmap:
1169 	bus_dmamem_unmap(n->cd_tag, n->cd_addr, n->cd_size);
1170  dmafree:
1171 	bus_dmamem_free(n->cd_tag,
1172 			n->cd_segs, nitems(n->cd_segs));
1173  mfree:
1174 	free(n, type, 0);
1175  quit:
1176 	return error;
1177 }
1178 
1179 int
1180 cmpci_free_dmamem(struct cmpci_softc *sc, caddr_t addr, int type)
1181 {
1182 	struct cmpci_dmanode **nnp;
1183 
1184 	for (nnp = &sc->sc_dmap; *nnp; nnp = &(*nnp)->cd_next) {
1185 		if ((*nnp)->cd_addr == addr) {
1186 			struct cmpci_dmanode *n = *nnp;
1187 			bus_dmamap_unload(n->cd_tag, n->cd_map);
1188 			bus_dmamap_destroy(n->cd_tag, n->cd_map);
1189 			bus_dmamem_unmap(n->cd_tag, n->cd_addr, n->cd_size);
1190 			bus_dmamem_free(n->cd_tag, n->cd_segs,
1191 			    nitems(n->cd_segs));
1192 			free(n, type, 0);
1193 			return 0;
1194 		}
1195 	}
1196 	return -1;
1197 }
1198 
1199 struct cmpci_dmanode *
1200 cmpci_find_dmamem(struct cmpci_softc *sc, caddr_t addr)
1201 {
1202 	struct cmpci_dmanode *p;
1203 
1204 	for (p = sc->sc_dmap; p; p = p->cd_next) {
1205 		if (KVADDR(p) == (void *)addr)
1206 			break;
1207 	}
1208 	return p;
1209 }
1210 
1211 #if 0
1212 void cmpci_print_dmamem(struct cmpci_dmanode *p);
1213 
1214 void
1215 cmpci_print_dmamem(struct cmpci_dmanode *p)
1216 {
1217 	DPRINTF(("DMA at virt:%p, dmaseg:%p, mapseg:%p, size:%p\n",
1218 		 (void *)p->cd_addr, (void *)p->cd_segs[0].ds_addr,
1219 		 (void *)DMAADDR(p), (void *)p->cd_size));
1220 }
1221 #endif /* DEBUG */
1222 
1223 void *
1224 cmpci_malloc(void *handle, int direction, size_t size, int type,
1225     int flags)
1226 {
1227 	caddr_t addr;
1228 
1229 	if (cmpci_alloc_dmamem(handle, size, type, flags, &addr))
1230 		return NULL;
1231 	return addr;
1232 }
1233 
1234 void
1235 cmpci_free(void *handle, void *addr, int type)
1236 {
1237 	cmpci_free_dmamem(handle, addr, type);
1238 }
1239 
1240 #define MAXVAL 256
1241 int
1242 cmpci_adjust(int val, int mask)
1243 {
1244 	val += (MAXVAL - mask) >> 1;
1245 	if (val >= MAXVAL)
1246 		val = MAXVAL-1;
1247 	return val & mask;
1248 }
1249 
1250 void
1251 cmpci_set_mixer_gain(struct cmpci_softc *sc, int port)
1252 {
1253 	int src;
1254 	int bits, mask;
1255 
1256 	switch (port) {
1257 	case CMPCI_MIC_VOL:
1258 		cmpci_mixerreg_write(sc, CMPCI_SB16_MIXER_MIC,
1259 		    CMPCI_ADJUST_MIC_GAIN(sc, sc->sc_gain[port][CMPCI_LR]));
1260 		return;
1261 	case CMPCI_MASTER_VOL:
1262 		src = CMPCI_SB16_MIXER_MASTER_L;
1263 		break;
1264 	case CMPCI_LINE_IN_VOL:
1265 		src = CMPCI_SB16_MIXER_LINE_L;
1266 		break;
1267 	case CMPCI_AUX_IN_VOL:
1268 		bus_space_write_1(sc->sc_iot, sc->sc_ioh, CMPCI_REG_MIXER_AUX,
1269 		    CMPCI_ADJUST_AUX_GAIN(sc, sc->sc_gain[port][CMPCI_LEFT],
1270 					      sc->sc_gain[port][CMPCI_RIGHT]));
1271 		return;
1272 	case CMPCI_MIC_RECVOL:
1273 		cmpci_reg_partial_write_1(sc, CMPCI_REG_MIXER25,
1274 		    CMPCI_REG_ADMIC_SHIFT, CMPCI_REG_ADMIC_MASK,
1275 		    CMPCI_ADJUST_ADMIC_GAIN(sc, sc->sc_gain[port][CMPCI_LR]));
1276 		return;
1277 	case CMPCI_DAC_VOL:
1278 		src = CMPCI_SB16_MIXER_VOICE_L;
1279 		break;
1280 	case CMPCI_FM_VOL:
1281 		src = CMPCI_SB16_MIXER_FM_L;
1282 		break;
1283 	case CMPCI_CD_VOL:
1284 		src = CMPCI_SB16_MIXER_CDDA_L;
1285 		break;
1286 	case CMPCI_PCSPEAKER:
1287 		cmpci_mixerreg_write(sc, CMPCI_SB16_MIXER_SPEAKER,
1288 		    CMPCI_ADJUST_2_GAIN(sc, sc->sc_gain[port][CMPCI_LR]));
1289 		return;
1290 	case CMPCI_MIC_PREAMP:
1291 		if (sc->sc_gain[port][CMPCI_LR])
1292 			cmpci_reg_clear_1(sc, CMPCI_REG_MIXER25,
1293 			    CMPCI_REG_MICGAINZ);
1294 		else
1295 			cmpci_reg_set_1(sc, CMPCI_REG_MIXER25,
1296 			    CMPCI_REG_MICGAINZ);
1297 		return;
1298 
1299 	case CMPCI_DAC_MUTE:
1300 		if (sc->sc_gain[port][CMPCI_LR])
1301 			cmpci_reg_set_1(sc, CMPCI_REG_MIXER24,
1302 			    CMPCI_REG_WSMUTE);
1303 		else
1304 			cmpci_reg_clear_1(sc, CMPCI_REG_MIXER24,
1305 			    CMPCI_REG_WSMUTE);
1306 		return;
1307 	case CMPCI_FM_MUTE:
1308 		if (sc->sc_gain[port][CMPCI_LR])
1309 			cmpci_reg_set_1(sc, CMPCI_REG_MIXER24,
1310 			    CMPCI_REG_FMMUTE);
1311 		else
1312 			cmpci_reg_clear_1(sc, CMPCI_REG_MIXER24,
1313 			    CMPCI_REG_FMMUTE);
1314 		return;
1315 	case CMPCI_AUX_IN_MUTE:
1316 		if (sc->sc_gain[port][CMPCI_LR])
1317 			cmpci_reg_clear_1(sc, CMPCI_REG_MIXER25,
1318 			    CMPCI_REG_VAUXRM|CMPCI_REG_VAUXLM);
1319 		else
1320 			cmpci_reg_set_1(sc, CMPCI_REG_MIXER25,
1321 			    CMPCI_REG_VAUXRM|CMPCI_REG_VAUXLM);
1322 		return;
1323 	case CMPCI_CD_MUTE:
1324 		mask = CMPCI_SB16_SW_CD;
1325 		goto sbmute;
1326 	case CMPCI_MIC_MUTE:
1327 		mask = CMPCI_SB16_SW_MIC;
1328 		goto sbmute;
1329 	case CMPCI_LINE_IN_MUTE:
1330 		mask = CMPCI_SB16_SW_LINE;
1331 	sbmute:
1332 		bits = cmpci_mixerreg_read(sc, CMPCI_SB16_MIXER_OUTMIX);
1333 		if (sc->sc_gain[port][CMPCI_LR])
1334 			bits = bits & ~mask;
1335 		else
1336 			bits = bits | mask;
1337 		cmpci_mixerreg_write(sc, CMPCI_SB16_MIXER_OUTMIX, bits);
1338 		return;
1339 
1340 	case CMPCI_SPDIF_IN_SELECT:
1341 	case CMPCI_MONITOR_DAC:
1342 	case CMPCI_PLAYBACK_MODE:
1343 	case CMPCI_SPDIF_LOOP:
1344 	case CMPCI_SPDIF_OUT_PLAYBACK:
1345 		cmpci_set_out_ports(sc);
1346 		return;
1347 	case CMPCI_SPDIF_OUT_VOLTAGE:
1348 		if (CMPCI_ISCAP(sc, SPDOUT_VOLTAGE)) {
1349 			if (sc->sc_gain[CMPCI_SPDIF_OUT_VOLTAGE][CMPCI_LR]
1350 			    == CMPCI_SPDIF_OUT_VOLTAGE_HIGH)
1351 				cmpci_reg_clear_reg_misc(sc, CMPCI_REG_5V);
1352 			else
1353 				cmpci_reg_set_reg_misc(sc, CMPCI_REG_5V);
1354 		}
1355 		return;
1356 	case CMPCI_SURROUND:
1357 		if (CMPCI_ISCAP(sc, SURROUND)) {
1358 			if (sc->sc_gain[CMPCI_SURROUND][CMPCI_LR])
1359 				cmpci_reg_set_1(sc, CMPCI_REG_MIXER24,
1360 						CMPCI_REG_SURROUND);
1361 			else
1362 				cmpci_reg_clear_1(sc, CMPCI_REG_MIXER24,
1363 						  CMPCI_REG_SURROUND);
1364 		}
1365 		return;
1366 	case CMPCI_REAR:
1367 		if (CMPCI_ISCAP(sc, REAR)) {
1368 			if (sc->sc_gain[CMPCI_REAR][CMPCI_LR])
1369 				cmpci_reg_set_reg_misc(sc, CMPCI_REG_N4SPK3D);
1370 			else
1371 				cmpci_reg_clear_reg_misc(sc, CMPCI_REG_N4SPK3D);
1372 		}
1373 		return;
1374 	case CMPCI_INDIVIDUAL:
1375 		if (CMPCI_ISCAP(sc, INDIVIDUAL_REAR)) {
1376 			if (sc->sc_gain[CMPCI_REAR][CMPCI_LR])
1377 				cmpci_reg_set_1(sc, CMPCI_REG_MIXER24,
1378 						CMPCI_REG_INDIVIDUAL);
1379 			else
1380 				cmpci_reg_clear_1(sc, CMPCI_REG_MIXER24,
1381 						  CMPCI_REG_INDIVIDUAL);
1382 		}
1383 		return;
1384 	case CMPCI_REVERSE:
1385 		if (CMPCI_ISCAP(sc, REVERSE_FR)) {
1386 			if (sc->sc_gain[CMPCI_REVERSE][CMPCI_LR])
1387 				cmpci_reg_set_1(sc, CMPCI_REG_MIXER24,
1388 						CMPCI_REG_REVERSE_FR);
1389 			else
1390 				cmpci_reg_clear_1(sc, CMPCI_REG_MIXER24,
1391 						  CMPCI_REG_REVERSE_FR);
1392 		}
1393 		return;
1394 	case CMPCI_SPDIF_IN_PHASE:
1395 		if (CMPCI_ISCAP(sc, SPDIN_PHASE)) {
1396 			if (sc->sc_gain[CMPCI_SPDIF_IN_PHASE][CMPCI_LR]
1397 			    == CMPCI_SPDIF_IN_PHASE_POSITIVE)
1398 				cmpci_reg_clear_1(sc, CMPCI_REG_CHANNEL_FORMAT,
1399 						  CMPCI_REG_SPDIN_PHASE);
1400 			else
1401 				cmpci_reg_set_1(sc, CMPCI_REG_CHANNEL_FORMAT,
1402 						CMPCI_REG_SPDIN_PHASE);
1403 		}
1404 		return;
1405 	default:
1406 		return;
1407 	}
1408 
1409 	cmpci_mixerreg_write(sc, src,
1410 	    CMPCI_ADJUST_GAIN(sc, sc->sc_gain[port][CMPCI_LEFT]));
1411 	cmpci_mixerreg_write(sc, CMPCI_SB16_MIXER_L_TO_R(src),
1412 	    CMPCI_ADJUST_GAIN(sc, sc->sc_gain[port][CMPCI_RIGHT]));
1413 }
1414 
1415 void
1416 cmpci_set_out_ports(struct cmpci_softc *sc)
1417 {
1418 	struct cmpci_channel *chan;
1419 	u_int8_t v;
1420 	int enspdout = 0;
1421 
1422 	if (!CMPCI_ISCAP(sc, SPDLOOP))
1423 		return;
1424 
1425 	/* SPDIF/out select */
1426 	if (sc->sc_gain[CMPCI_SPDIF_LOOP][CMPCI_LR] == CMPCI_SPDIF_LOOP_OFF) {
1427 		/* playback */
1428 		cmpci_reg_clear_4(sc, CMPCI_REG_FUNC_1, CMPCI_REG_SPDIF_LOOP);
1429 	} else {
1430 		/* monitor SPDIF/in */
1431 		cmpci_reg_set_4(sc, CMPCI_REG_FUNC_1, CMPCI_REG_SPDIF_LOOP);
1432 	}
1433 
1434 	/* SPDIF in select */
1435 	v = sc->sc_gain[CMPCI_SPDIF_IN_SELECT][CMPCI_LR];
1436 	if (v & CMPCI_SPDIFIN_SPDIFIN2)
1437 		cmpci_reg_set_reg_misc(sc, CMPCI_REG_2ND_SPDIFIN);
1438 	else
1439 		cmpci_reg_clear_reg_misc(sc, CMPCI_REG_2ND_SPDIFIN);
1440 	if (v & CMPCI_SPDIFIN_SPDIFOUT)
1441 		cmpci_reg_set_reg_misc(sc, CMPCI_REG_SPDFLOOPI);
1442 	else
1443 		cmpci_reg_clear_reg_misc(sc, CMPCI_REG_SPDFLOOPI);
1444 
1445 	if (sc->sc_play_channel == 1)
1446 		chan = &sc->sc_ch1;
1447 	else
1448 		chan = &sc->sc_ch0;
1449 
1450 	/* disable ac3 and 24 and 32 bit s/pdif modes */
1451 	cmpci_reg_clear_4(sc, CMPCI_REG_CHANNEL_FORMAT, CMPCI_REG_AC3EN1);
1452 	cmpci_reg_clear_reg_misc(sc, CMPCI_REG_AC3EN2);
1453 	cmpci_reg_clear_reg_misc(sc, CMPCI_REG_SPD32SEL);
1454 	cmpci_reg_clear_4(sc, CMPCI_REG_CHANNEL_FORMAT, CMPCI_REG_SPDIF_24);
1455 
1456 	/* playback to ... */
1457 	if (CMPCI_ISCAP(sc, SPDOUT) &&
1458 	    sc->sc_gain[CMPCI_PLAYBACK_MODE][CMPCI_LR]
1459 		== CMPCI_PLAYBACK_MODE_SPDIF &&
1460 	    (chan->md_divide == CMPCI_REG_RATE_44100 ||
1461 		(CMPCI_ISCAP(sc, SPDOUT_48K) &&
1462 		    chan->md_divide == CMPCI_REG_RATE_48000))) {
1463 		/* playback to SPDIF */
1464 		if (sc->sc_play_channel == 0)
1465 			cmpci_reg_set_4(sc, CMPCI_REG_FUNC_1,
1466 			    CMPCI_REG_SPDIF0_ENABLE);
1467 		else
1468 			cmpci_reg_set_4(sc, CMPCI_REG_FUNC_1,
1469 			    CMPCI_REG_SPDIF1_ENABLE);
1470 		enspdout = 1;
1471 		if (chan->md_divide == CMPCI_REG_RATE_48000)
1472 			cmpci_reg_set_reg_misc(sc,
1473 				CMPCI_REG_SPDIFOUT_48K | CMPCI_REG_SPDIF48K);
1474 		else
1475 			cmpci_reg_clear_reg_misc(sc,
1476 				CMPCI_REG_SPDIFOUT_48K | CMPCI_REG_SPDIF48K);
1477 		/* XXX assume sample rate <= 48kHz */
1478 		cmpci_reg_clear_4(sc, CMPCI_REG_CHANNEL_FORMAT,
1479 		    CMPCI_REG_DBL_SPD_RATE);
1480 	} else {
1481 		/* playback to DAC */
1482 		if (sc->sc_play_channel == 0)
1483 			cmpci_reg_clear_4(sc, CMPCI_REG_FUNC_1,
1484 			    CMPCI_REG_SPDIF0_ENABLE);
1485 		else
1486 			cmpci_reg_clear_4(sc, CMPCI_REG_FUNC_1,
1487 			    CMPCI_REG_SPDIF1_ENABLE);
1488 		if (CMPCI_ISCAP(sc, SPDOUT_48K))
1489 			cmpci_reg_clear_reg_misc(sc,
1490 				CMPCI_REG_SPDIFOUT_48K | CMPCI_REG_SPDIF48K);
1491 	}
1492 
1493 	/* legacy to SPDIF/out or not */
1494 	if (CMPCI_ISCAP(sc, SPDLEGACY)) {
1495 		if (sc->sc_gain[CMPCI_SPDIF_OUT_PLAYBACK][CMPCI_LR]
1496 		    == CMPCI_SPDIF_OUT_PLAYBACK_WAVE)
1497 			cmpci_reg_clear_4(sc, CMPCI_REG_LEGACY_CTRL,
1498 					CMPCI_REG_LEGACY_SPDIF_ENABLE);
1499 		else {
1500 			cmpci_reg_set_4(sc, CMPCI_REG_LEGACY_CTRL,
1501 					CMPCI_REG_LEGACY_SPDIF_ENABLE);
1502 			enspdout = 1;
1503 		}
1504 	}
1505 
1506 	/* enable/disable SPDIF/out */
1507 	if (CMPCI_ISCAP(sc, XSPDOUT) && enspdout)
1508 		cmpci_reg_set_4(sc, CMPCI_REG_LEGACY_CTRL,
1509 				CMPCI_REG_XSPDIF_ENABLE);
1510 	else
1511 		cmpci_reg_clear_4(sc, CMPCI_REG_LEGACY_CTRL,
1512 				CMPCI_REG_XSPDIF_ENABLE);
1513 
1514 	/* SPDIF monitor (digital to analog output) */
1515 	if (CMPCI_ISCAP(sc, SPDIN_MONITOR)) {
1516 		v = sc->sc_gain[CMPCI_MONITOR_DAC][CMPCI_LR];
1517 		if (!(v & CMPCI_MONDAC_ENABLE))
1518 			cmpci_reg_clear_1(sc, CMPCI_REG_MIXER24,
1519 					CMPCI_REG_SPDIN_MONITOR);
1520 		if (v & CMPCI_MONDAC_SPDOUT)
1521 			cmpci_reg_set_4(sc, CMPCI_REG_FUNC_1,
1522 					CMPCI_REG_SPDIFOUT_DAC);
1523 		else
1524 			cmpci_reg_clear_4(sc, CMPCI_REG_FUNC_1,
1525 					CMPCI_REG_SPDIFOUT_DAC);
1526 		if (v & CMPCI_MONDAC_ENABLE)
1527 			cmpci_reg_set_1(sc, CMPCI_REG_MIXER24,
1528 					CMPCI_REG_SPDIN_MONITOR);
1529 	}
1530 }
1531 
1532 int
1533 cmpci_set_in_ports(struct cmpci_softc *sc)
1534 {
1535 	int mask;
1536 	int bitsl, bitsr;
1537 
1538 	mask = sc->sc_in_mask;
1539 
1540 	/*
1541 	 * Note CMPCI_RECORD_SOURCE_CD, CMPCI_RECORD_SOURCE_LINE_IN and
1542 	 * CMPCI_RECORD_SOURCE_FM are defined to the corresponding bit
1543 	 * of the mixer register.
1544 	 */
1545 	bitsr = mask & (CMPCI_RECORD_SOURCE_CD | CMPCI_RECORD_SOURCE_LINE_IN |
1546 	    CMPCI_RECORD_SOURCE_FM);
1547 
1548 	bitsl = CMPCI_SB16_MIXER_SRC_R_TO_L(bitsr);
1549 	if (mask & CMPCI_RECORD_SOURCE_MIC) {
1550 		bitsl |= CMPCI_SB16_MIXER_MIC_SRC;
1551 		bitsr |= CMPCI_SB16_MIXER_MIC_SRC;
1552 	}
1553 	cmpci_mixerreg_write(sc, CMPCI_SB16_MIXER_ADCMIX_L, bitsl);
1554 	cmpci_mixerreg_write(sc, CMPCI_SB16_MIXER_ADCMIX_R, bitsr);
1555 
1556 	if (mask & CMPCI_RECORD_SOURCE_AUX_IN)
1557 		cmpci_reg_set_1(sc, CMPCI_REG_MIXER25,
1558 		    CMPCI_REG_RAUXREN | CMPCI_REG_RAUXLEN);
1559 	else
1560 		cmpci_reg_clear_1(sc, CMPCI_REG_MIXER25,
1561 		    CMPCI_REG_RAUXREN | CMPCI_REG_RAUXLEN);
1562 
1563 	if (mask & CMPCI_RECORD_SOURCE_WAVE)
1564 		cmpci_reg_set_1(sc, CMPCI_REG_MIXER24,
1565 		    CMPCI_REG_WAVEINL | CMPCI_REG_WAVEINR);
1566 	else
1567 		cmpci_reg_clear_1(sc, CMPCI_REG_MIXER24,
1568 		    CMPCI_REG_WAVEINL | CMPCI_REG_WAVEINR);
1569 
1570 	if (CMPCI_ISCAP(sc, SPDIN) &&
1571 	    (sc->sc_ch1.md_divide == CMPCI_REG_RATE_44100 ||
1572 		(CMPCI_ISCAP(sc, SPDOUT_48K) &&
1573 		    sc->sc_ch1.md_divide == CMPCI_REG_RATE_48000/* XXX? */))) {
1574 		if (mask & CMPCI_RECORD_SOURCE_SPDIF) {
1575 			/* enable SPDIF/in */
1576 			cmpci_reg_set_4(sc,
1577 					CMPCI_REG_FUNC_1,
1578 					CMPCI_REG_SPDIF1_ENABLE);
1579 		} else {
1580 			cmpci_reg_clear_4(sc,
1581 					CMPCI_REG_FUNC_1,
1582 					CMPCI_REG_SPDIF1_ENABLE);
1583 		}
1584 	}
1585 
1586 	return 0;
1587 }
1588 
1589 int
1590 cmpci_set_port(void *handle, mixer_ctrl_t *cp)
1591 {
1592 	struct cmpci_softc *sc = handle;
1593 	int lgain, rgain;
1594 
1595 	switch (cp->dev) {
1596 	case CMPCI_MIC_VOL:
1597 	case CMPCI_PCSPEAKER:
1598 	case CMPCI_MIC_RECVOL:
1599 		if (cp->un.value.num_channels != 1)
1600 			return EINVAL;
1601 		/* FALLTHROUGH */
1602 	case CMPCI_DAC_VOL:
1603 	case CMPCI_FM_VOL:
1604 	case CMPCI_CD_VOL:
1605 	case CMPCI_LINE_IN_VOL:
1606 	case CMPCI_AUX_IN_VOL:
1607 	case CMPCI_MASTER_VOL:
1608 		if (cp->type != AUDIO_MIXER_VALUE)
1609 			return EINVAL;
1610 		switch (cp->un.value.num_channels) {
1611 		case 1:
1612 			lgain = rgain =
1613 			    cp->un.value.level[AUDIO_MIXER_LEVEL_MONO];
1614 			break;
1615 		case 2:
1616 			lgain = cp->un.value.level[AUDIO_MIXER_LEVEL_LEFT];
1617 			rgain = cp->un.value.level[AUDIO_MIXER_LEVEL_RIGHT];
1618 			break;
1619 		default:
1620 			return EINVAL;
1621 		}
1622 		sc->sc_gain[cp->dev][CMPCI_LEFT]  = lgain;
1623 		sc->sc_gain[cp->dev][CMPCI_RIGHT] = rgain;
1624 
1625 		cmpci_set_mixer_gain(sc, cp->dev);
1626 		break;
1627 
1628 	case CMPCI_RECORD_SOURCE:
1629 		if (cp->type != AUDIO_MIXER_SET)
1630 			return EINVAL;
1631 
1632 		if (cp->un.mask & ~(CMPCI_RECORD_SOURCE_MIC |
1633 		    CMPCI_RECORD_SOURCE_CD | CMPCI_RECORD_SOURCE_LINE_IN |
1634 		    CMPCI_RECORD_SOURCE_AUX_IN | CMPCI_RECORD_SOURCE_WAVE |
1635 		    CMPCI_RECORD_SOURCE_FM | CMPCI_RECORD_SOURCE_SPDIF))
1636 			return EINVAL;
1637 
1638 		if (cp->un.mask & CMPCI_RECORD_SOURCE_SPDIF)
1639 			cp->un.mask = CMPCI_RECORD_SOURCE_SPDIF;
1640 
1641 		sc->sc_in_mask = cp->un.mask;
1642 		return cmpci_set_in_ports(sc);
1643 
1644 	/* boolean */
1645 	case CMPCI_DAC_MUTE:
1646 	case CMPCI_FM_MUTE:
1647 	case CMPCI_CD_MUTE:
1648 	case CMPCI_LINE_IN_MUTE:
1649 	case CMPCI_AUX_IN_MUTE:
1650 	case CMPCI_MIC_MUTE:
1651 	case CMPCI_MIC_PREAMP:
1652 	case CMPCI_PLAYBACK_MODE:
1653 	case CMPCI_SPDIF_IN_PHASE:
1654 	case CMPCI_SPDIF_LOOP:
1655 	case CMPCI_SPDIF_OUT_PLAYBACK:
1656 	case CMPCI_SPDIF_OUT_VOLTAGE:
1657 	case CMPCI_REAR:
1658 	case CMPCI_INDIVIDUAL:
1659 	case CMPCI_REVERSE:
1660 	case CMPCI_SURROUND:
1661 		if (cp->type != AUDIO_MIXER_ENUM)
1662 			return EINVAL;
1663 		sc->sc_gain[cp->dev][CMPCI_LR] = cp->un.ord != 0;
1664 		cmpci_set_mixer_gain(sc, cp->dev);
1665 		break;
1666 
1667 	case CMPCI_SPDIF_IN_SELECT:
1668 		switch (cp->un.ord) {
1669 		case CMPCI_SPDIF_IN_SPDIN1:
1670 		case CMPCI_SPDIF_IN_SPDIN2:
1671 		case CMPCI_SPDIF_IN_SPDOUT:
1672 			break;
1673 		default:
1674 			return EINVAL;
1675 		}
1676 		goto xenum;
1677 	case CMPCI_MONITOR_DAC:
1678 		switch (cp->un.ord) {
1679 		case CMPCI_MONITOR_DAC_OFF:
1680 		case CMPCI_MONITOR_DAC_SPDIN:
1681 		case CMPCI_MONITOR_DAC_SPDOUT:
1682 			break;
1683 		default:
1684 			return EINVAL;
1685 		}
1686 	xenum:
1687 		if (cp->type != AUDIO_MIXER_ENUM)
1688 			return EINVAL;
1689 		sc->sc_gain[cp->dev][CMPCI_LR] = cp->un.ord;
1690 		cmpci_set_mixer_gain(sc, cp->dev);
1691 		break;
1692 
1693 	default:
1694 	    return EINVAL;
1695 	}
1696 
1697 	return 0;
1698 }
1699 
1700 int
1701 cmpci_get_port(void *handle, mixer_ctrl_t *cp)
1702 {
1703 	struct cmpci_softc *sc = handle;
1704 
1705 	switch (cp->dev) {
1706 	case CMPCI_MIC_VOL:
1707 	case CMPCI_PCSPEAKER:
1708 	case CMPCI_MIC_RECVOL:
1709 		if (cp->un.value.num_channels != 1)
1710 			return EINVAL;
1711 		/*FALLTHROUGH*/
1712 	case CMPCI_DAC_VOL:
1713 	case CMPCI_FM_VOL:
1714 	case CMPCI_CD_VOL:
1715 	case CMPCI_LINE_IN_VOL:
1716 	case CMPCI_AUX_IN_VOL:
1717 	case CMPCI_MASTER_VOL:
1718 		switch (cp->un.value.num_channels) {
1719 		case 1:
1720 			cp->un.value.level[AUDIO_MIXER_LEVEL_MONO] =
1721 				sc->sc_gain[cp->dev][CMPCI_LEFT];
1722 			break;
1723 		case 2:
1724 			cp->un.value.level[AUDIO_MIXER_LEVEL_LEFT] =
1725 				sc->sc_gain[cp->dev][CMPCI_LEFT];
1726 			cp->un.value.level[AUDIO_MIXER_LEVEL_RIGHT] =
1727 				sc->sc_gain[cp->dev][CMPCI_RIGHT];
1728 			break;
1729 		default:
1730 			return EINVAL;
1731 		}
1732 		break;
1733 
1734 	case CMPCI_RECORD_SOURCE:
1735 		cp->un.mask = sc->sc_in_mask;
1736 		break;
1737 
1738 	case CMPCI_DAC_MUTE:
1739 	case CMPCI_FM_MUTE:
1740 	case CMPCI_CD_MUTE:
1741 	case CMPCI_LINE_IN_MUTE:
1742 	case CMPCI_AUX_IN_MUTE:
1743 	case CMPCI_MIC_MUTE:
1744 	case CMPCI_MIC_PREAMP:
1745 	case CMPCI_PLAYBACK_MODE:
1746 	case CMPCI_SPDIF_IN_SELECT:
1747 	case CMPCI_SPDIF_IN_PHASE:
1748 	case CMPCI_SPDIF_LOOP:
1749 	case CMPCI_SPDIF_OUT_PLAYBACK:
1750 	case CMPCI_SPDIF_OUT_VOLTAGE:
1751 	case CMPCI_MONITOR_DAC:
1752 	case CMPCI_REAR:
1753 	case CMPCI_INDIVIDUAL:
1754 	case CMPCI_REVERSE:
1755 	case CMPCI_SURROUND:
1756 		cp->un.ord = sc->sc_gain[cp->dev][CMPCI_LR];
1757 		break;
1758 
1759 	default:
1760 		return EINVAL;
1761 	}
1762 
1763 	return 0;
1764 }
1765 
1766 /* ARGSUSED */
1767 size_t
1768 cmpci_round_buffersize(void *handle, int direction, size_t bufsize)
1769 {
1770 	if (bufsize > 0x10000)
1771 		bufsize = 0x10000;
1772 
1773 	return bufsize;
1774 }
1775 
1776 /* ARGSUSED */
1777 int
1778 cmpci_get_props(void *handle)
1779 {
1780 	return AUDIO_PROP_MMAP | AUDIO_PROP_INDEPENDENT | AUDIO_PROP_FULLDUPLEX;
1781 }
1782 
1783 int
1784 cmpci_trigger_output(void *handle, void *start, void *end, int blksize,
1785     void (*intr)(void *), void *arg, struct audio_params *param)
1786 {
1787 	struct cmpci_softc *sc = handle;
1788 	struct cmpci_dmanode *p;
1789 	struct cmpci_channel *chan;
1790 	uint32_t reg_dma_base, reg_dma_bytes, reg_dma_samples, reg_dir,
1791 	    reg_intr_enable, reg_enable;
1792 	uint32_t length;
1793 	size_t buffer_size = (caddr_t)end - (caddr_t)start;
1794 
1795 	cmpci_set_out_ports(sc);
1796 
1797 	if (sc->sc_play_channel == 1) {
1798 		chan = &sc->sc_ch1;
1799 		reg_dma_base = CMPCI_REG_DMA1_BASE;
1800 		reg_dma_bytes = CMPCI_REG_DMA1_BYTES;
1801 		reg_dma_samples = CMPCI_REG_DMA1_SAMPLES;
1802 		reg_dir = CMPCI_REG_CH1_DIR;
1803 		reg_intr_enable = CMPCI_REG_CH1_INTR_ENABLE;
1804 		reg_enable = CMPCI_REG_CH1_ENABLE;
1805 	} else {
1806 		chan = &sc->sc_ch0;
1807 		reg_dma_base = CMPCI_REG_DMA0_BASE;
1808 		reg_dma_bytes = CMPCI_REG_DMA0_BYTES;
1809 		reg_dma_samples = CMPCI_REG_DMA0_SAMPLES;
1810 		reg_dir = CMPCI_REG_CH0_DIR;
1811 		reg_intr_enable = CMPCI_REG_CH0_INTR_ENABLE;
1812 		reg_enable = CMPCI_REG_CH0_ENABLE;
1813 	}
1814 
1815 	chan->bps = (param->channels > 1 ? 2 : 1) * param->bps;
1816 	if (!chan->bps)
1817 		return EINVAL;
1818 
1819 	chan->intr = intr;
1820 	chan->intr_arg = arg;
1821 	chan->blksize = blksize;
1822 	chan->nblocks = buffer_size / chan->blksize;
1823 	chan->swpos = 0;
1824 
1825 	/* set DMA frame */
1826 	if (!(p = cmpci_find_dmamem(sc, start)))
1827 		return EINVAL;
1828 	bus_space_write_4(sc->sc_iot, sc->sc_ioh, reg_dma_base,
1829 	    DMAADDR(p));
1830 	delay(10);
1831 	length = (buffer_size + 1) / chan->bps - 1;
1832 	bus_space_write_2(sc->sc_iot, sc->sc_ioh, reg_dma_bytes, length);
1833 	delay(10);
1834 
1835 	/* set interrupt count */
1836 	length = (chan->blksize + chan->bps - 1) / chan->bps - 1;
1837 	bus_space_write_2(sc->sc_iot, sc->sc_ioh, reg_dma_samples, length);
1838 	delay(10);
1839 
1840 	/* start DMA */
1841 	mtx_enter(&audio_lock);
1842 	cmpci_reg_clear_4(sc, CMPCI_REG_FUNC_0, reg_dir); /* PLAY */
1843 	cmpci_reg_set_4(sc, CMPCI_REG_INTR_CTRL, reg_intr_enable);
1844 	cmpci_reg_set_4(sc, CMPCI_REG_FUNC_0, reg_enable);
1845 	mtx_leave(&audio_lock);
1846 	return 0;
1847 }
1848 
1849 int
1850 cmpci_trigger_input(void *handle, void *start, void *end, int blksize,
1851     void (*intr)(void *), void *arg, struct audio_params *param)
1852 {
1853 	struct cmpci_softc *sc = handle;
1854 	struct cmpci_dmanode *p;
1855 	struct cmpci_channel *chan = &sc->sc_ch1;
1856 	size_t buffer_size = (caddr_t)end - (caddr_t)start;
1857 
1858 	cmpci_set_in_ports(sc);
1859 
1860 	chan->bps = param->channels * param->bps;
1861 	if (!chan->bps)
1862 		return EINVAL;
1863 
1864 	chan->intr = intr;
1865 	chan->intr_arg = arg;
1866 	chan->blksize = blksize;
1867 	chan->nblocks = buffer_size / chan->blksize;
1868 	chan->swpos = 0;
1869 
1870 	/* set DMA frame */
1871 	if (!(p = cmpci_find_dmamem(sc, start)))
1872 		return EINVAL;
1873 	bus_space_write_4(sc->sc_iot, sc->sc_ioh, CMPCI_REG_DMA1_BASE,
1874 	    DMAADDR(p));
1875 	delay(10);
1876 	bus_space_write_2(sc->sc_iot, sc->sc_ioh, CMPCI_REG_DMA1_BYTES,
1877 	    (buffer_size + 1) / chan->bps - 1);
1878 	delay(10);
1879 
1880 	/* set interrupt count */
1881 	bus_space_write_2(sc->sc_iot, sc->sc_ioh, CMPCI_REG_DMA1_SAMPLES,
1882 	    (chan->blksize + chan->bps - 1) / chan->bps - 1);
1883 	delay(10);
1884 
1885 	/* start DMA */
1886 	mtx_enter(&audio_lock);
1887 	cmpci_reg_set_4(sc, CMPCI_REG_FUNC_0, CMPCI_REG_CH1_DIR); /* REC */
1888 	cmpci_reg_set_4(sc, CMPCI_REG_INTR_CTRL, CMPCI_REG_CH1_INTR_ENABLE);
1889 	cmpci_reg_set_4(sc, CMPCI_REG_FUNC_0, CMPCI_REG_CH1_ENABLE);
1890 	mtx_leave(&audio_lock);
1891 	return 0;
1892 }
1893 
1894 /* end of file */
1895