xref: /openbsd-src/sys/arch/sparc64/dev/ce4231.c (revision f2da64fbbbf1b03f09f390ab01267c93dfd77c4c)
1 /*	$OpenBSD: ce4231.c,v 1.35 2016/09/19 06:46:43 ratchov Exp $	*/
2 
3 /*
4  * Copyright (c) 1999 Jason L. Wright (jason@thought.net)
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 ``AS IS'' AND ANY EXPRESS OR
17  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19  * DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
20  * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
22  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
24  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
25  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
26  * POSSIBILITY OF SUCH DAMAGE.
27  */
28 
29 /*
30  * Driver for CS4231 based audio found in some sun4u systems (cs4231)
31  * based on ideas from the S/Linux project and the NetBSD project.
32  *
33  * Effort sponsored in part by the Defense Advanced Research Projects
34  * Agency (DARPA) and Air Force Research Laboratory, Air Force
35  * Materiel Command, USAF, under agreement number F30602-01-2-0537.
36  *
37  */
38 
39 #include <sys/param.h>
40 #include <sys/systm.h>
41 #include <sys/errno.h>
42 #include <sys/ioctl.h>
43 #include <sys/device.h>
44 #include <sys/proc.h>
45 #include <sys/malloc.h>
46 
47 #include <machine/cpu.h>
48 #include <machine/bus.h>
49 #include <machine/intr.h>
50 #include <machine/autoconf.h>
51 
52 #include <sys/audioio.h>
53 #include <dev/audio_if.h>
54 
55 #include <sparc64/dev/ebusreg.h>
56 #include <sparc64/dev/ebusvar.h>
57 #include <sparc64/dev/ce4231var.h>
58 
59 /* AD1418 provides basic registers, CS4231 extends with more */
60 #include <dev/ic/ad1848reg.h>
61 #include <dev/ic/cs4231reg.h>
62 
63 /* Mixer classes and mixer knobs */
64 #define CSAUDIO_INPUT_CLASS	0
65 #define CSAUDIO_OUTPUT_CLASS	1
66 #define CSAUDIO_RECORD_CLASS	2
67 #define CSAUDIO_DAC_LVL		3
68 #define CSAUDIO_DAC_MUTE	4
69 #define CSAUDIO_OUTPUTS		5
70 #define CSAUDIO_CD_LVL		6
71 #define CSAUDIO_CD_MUTE		7
72 #define CSAUDIO_LINE_IN_LVL	8
73 #define CSAUDIO_LINE_IN_MUTE	9
74 #define CSAUDIO_MONITOR_LVL	10
75 #define CSAUDIO_MONITOR_MUTE	11
76 #define CSAUDIO_REC_LVL		12
77 #define CSAUDIO_RECORD_SOURCE	13
78 #define CSAUDIO_MIC_PREAMP	14
79 
80 /* Recording sources */
81 #define REC_PORT_LINE	0
82 #define REC_PORT_CD	1
83 #define REC_PORT_MIC	2
84 #define REC_PORT_MIX	3
85 
86 /* Output ports. */
87 #define OUT_PORT_LINE	0x1
88 #define OUT_PORT_HP	0x2
89 #define OUT_PORT_SPKR	0x4
90 
91 /* Bits on the ADC reg that determine recording source */
92 #define CS_REC_SRC_BITS 0xc0
93 
94 #ifdef AUDIO_DEBUG
95 #define	DPRINTF(x)	printf x
96 #else
97 #define	DPRINTF(x)
98 #endif
99 
100 #define	CS_TIMEOUT	90000
101 
102 /* Read/write CS4231 direct registers */
103 #define CS_WRITE(sc,r,v)	\
104     bus_space_write_1((sc)->sc_bustag, (sc)->sc_cshandle, (r) << 2, (v))
105 #define	CS_READ(sc,r)		\
106     bus_space_read_1((sc)->sc_bustag, (sc)->sc_cshandle, (r) << 2)
107 
108 /* Read/write EBDMA playback registers */
109 #define	P_WRITE(sc,r,v)		\
110     bus_space_write_4((sc)->sc_bustag, (sc)->sc_pdmahandle, (r), (v))
111 #define	P_READ(sc,r)		\
112     bus_space_read_4((sc)->sc_bustag, (sc)->sc_pdmahandle, (r))
113 
114 /* Read/write EBDMA capture registers */
115 #define	C_WRITE(sc,r,v)		\
116     bus_space_write_4((sc)->sc_bustag, (sc)->sc_cdmahandle, (r), (v))
117 #define	C_READ(sc,r)		\
118     bus_space_read_4((sc)->sc_bustag, (sc)->sc_cdmahandle, (r))
119 
120 int	ce4231_match(struct device *, void *, void *);
121 void	ce4231_attach(struct device *, struct device *, void *);
122 int	ce4231_cintr(void *);
123 int	ce4231_pintr(void *);
124 
125 int	ce4231_set_speed(struct ce4231_softc *, u_long *);
126 
127 void	ce4231_set_outputs(struct ce4231_softc *, int);
128 int	ce4231_get_outputs(struct ce4231_softc *);
129 
130 void		ce4231_write(struct ce4231_softc *, u_int8_t, u_int8_t);
131 u_int8_t	ce4231_read(struct ce4231_softc *, u_int8_t);
132 
133 /* Audio interface */
134 int	ce4231_open(void *, int);
135 void	ce4231_close(void *);
136 int	ce4231_set_params(void *, int, int, struct audio_params *,
137     struct audio_params *);
138 int	ce4231_round_blocksize(void *, int);
139 int	ce4231_commit_settings(void *);
140 int	ce4231_halt_output(void *);
141 int	ce4231_halt_input(void *);
142 int	ce4231_set_port(void *, mixer_ctrl_t *);
143 int	ce4231_get_port(void *, mixer_ctrl_t *);
144 int	ce4231_query_devinfo(void *addr, mixer_devinfo_t *);
145 void *	ce4231_alloc(void *, int, size_t, int, int);
146 void	ce4231_free(void *, void *, int);
147 int	ce4231_get_props(void *);
148 int	ce4231_trigger_output(void *, void *, void *, int,
149     void (*intr)(void *), void *arg, struct audio_params *);
150 int	ce4231_trigger_input(void *, void *, void *, int,
151     void (*intr)(void *), void *arg, struct audio_params *);
152 
153 struct audio_hw_if ce4231_sa_hw_if = {
154 	ce4231_open,
155 	ce4231_close,
156 	ce4231_set_params,
157 	ce4231_round_blocksize,
158 	ce4231_commit_settings,
159 	0,
160 	0,
161 	0,
162 	0,
163 	ce4231_halt_output,
164 	ce4231_halt_input,
165 	0,
166 	0,
167 	ce4231_set_port,
168 	ce4231_get_port,
169 	ce4231_query_devinfo,
170 	ce4231_alloc,
171 	ce4231_free,
172 	0,
173 	ce4231_get_props,
174 	ce4231_trigger_output,
175 	ce4231_trigger_input
176 };
177 
178 struct cfattach audioce_ca = {
179 	sizeof (struct ce4231_softc), ce4231_match, ce4231_attach
180 };
181 
182 struct cfdriver audioce_cd = {
183 	NULL, "audioce", DV_DULL
184 };
185 
186 int
187 ce4231_match(parent, vcf, aux)
188 	struct device *parent;
189 	void *vcf, *aux;
190 {
191 	struct ebus_attach_args *ea = aux;
192 
193 	if (!strcmp("SUNW,CS4231", ea->ea_name) ||
194 	    !strcmp("audio", ea->ea_name))
195 		return (1);
196 	return (0);
197 }
198 
199 void
200 ce4231_attach(parent, self, aux)
201 	struct device *parent, *self;
202 	void *aux;
203 {
204 	struct ebus_attach_args *ea = aux;
205 	struct ce4231_softc *sc = (struct ce4231_softc *)self;
206 	mixer_ctrl_t cp;
207 	int node;
208 
209 	node = ea->ea_node;
210 
211 	sc->sc_last_format = 0xffffffff;
212 
213 	/* Pass on the bus tags */
214 	sc->sc_bustag = ea->ea_memtag;
215 	sc->sc_dmatag = ea->ea_dmatag;
216 
217 	/* Make sure things are sane. */
218 	if (ea->ea_nintrs != 2) {
219 		printf(": expected 2 interrupts, got %d\n", ea->ea_nintrs);
220 		return;
221 	}
222 	if (ea->ea_nregs != 4) {
223 		printf(": expected 4 register set, got %d\n",
224 		    ea->ea_nregs);
225 		return;
226 	}
227 
228 	sc->sc_cih = bus_intr_establish(sc->sc_bustag, ea->ea_intrs[0],
229 	    IPL_AUDIO, BUS_INTR_ESTABLISH_MPSAFE, ce4231_cintr,
230 	    sc, self->dv_xname);
231 	if (sc->sc_cih == NULL) {
232 		printf(": couldn't establish capture interrupt\n");
233 		return;
234 	}
235 	sc->sc_pih = bus_intr_establish(sc->sc_bustag, ea->ea_intrs[1],
236 	    IPL_AUDIO, BUS_INTR_ESTABLISH_MPSAFE, ce4231_pintr,
237 	    sc, self->dv_xname);
238 	if (sc->sc_pih == NULL) {
239 		printf(": couldn't establish play interrupt1\n");
240 		return;
241 	}
242 
243 	/* XXX what if prom has already mapped?! */
244 
245 	if (ebus_bus_map(sc->sc_bustag, 0,
246 	    EBUS_PADDR_FROM_REG(&ea->ea_regs[0]), ea->ea_regs[0].size,
247 	    BUS_SPACE_MAP_LINEAR, 0, &sc->sc_cshandle) != 0) {
248 		printf(": couldn't map cs4231 registers\n");
249 		return;
250 	}
251 
252 	if (ebus_bus_map(sc->sc_bustag, 0,
253 	    EBUS_PADDR_FROM_REG(&ea->ea_regs[1]), ea->ea_regs[1].size,
254 	    BUS_SPACE_MAP_LINEAR, 0, &sc->sc_pdmahandle) != 0) {
255 		printf(": couldn't map dma1 registers\n");
256 		return;
257 	}
258 
259 	if (ebus_bus_map(sc->sc_bustag, 0,
260 	    EBUS_PADDR_FROM_REG(&ea->ea_regs[2]), ea->ea_regs[2].size,
261 	    BUS_SPACE_MAP_LINEAR, 0, &sc->sc_cdmahandle) != 0) {
262 		printf(": couldn't map dma2 registers\n");
263 		return;
264 	}
265 
266 	if (ebus_bus_map(sc->sc_bustag, 0,
267 	    EBUS_PADDR_FROM_REG(&ea->ea_regs[3]), ea->ea_regs[3].size,
268 	    BUS_SPACE_MAP_LINEAR, 0, &sc->sc_auxhandle) != 0) {
269 		printf(": couldn't map aux registers\n");
270 		return;
271 	}
272 
273 	printf(": nvaddrs %d\n", ea->ea_nvaddrs);
274 
275 	audio_attach_mi(&ce4231_sa_hw_if, sc, &sc->sc_dev);
276 
277 	/* Enable mode 2. */
278 	ce4231_write(sc, SP_MISC_INFO, ce4231_read(sc, SP_MISC_INFO) | MODE2);
279 
280 	/* Attenuate DAC, CD and line-in.  -22.5 dB for all. */
281 	cp.dev = CSAUDIO_DAC_LVL;
282 	cp.type = AUDIO_MIXER_VALUE;
283 	cp.un.value.num_channels = 2;
284 	cp.un.value.level[AUDIO_MIXER_LEVEL_LEFT] = 195;
285 	cp.un.value.level[AUDIO_MIXER_LEVEL_RIGHT] = 195;
286 	ce4231_set_port(sc, &cp);
287 
288 	cp.dev = CSAUDIO_CD_LVL;
289 	cp.un.value.level[AUDIO_MIXER_LEVEL_LEFT] = 135;
290 	cp.un.value.level[AUDIO_MIXER_LEVEL_RIGHT] = 135;
291 	ce4231_set_port(sc, &cp);
292 
293 	cp.dev = CSAUDIO_LINE_IN_LVL;
294 	ce4231_set_port(sc, &cp);
295 
296 	/* Unmute DAC, CD and line-in */
297 	cp.dev = CSAUDIO_DAC_MUTE;
298 	cp.type = AUDIO_MIXER_ENUM;
299 	cp.un.ord = 0;
300 	ce4231_set_port(sc, &cp);
301 
302 	cp.dev = CSAUDIO_CD_MUTE;
303 	ce4231_set_port(sc, &cp);
304 
305 	cp.dev = CSAUDIO_LINE_IN_MUTE;
306 	ce4231_set_port(sc, &cp);
307 
308 	/* XXX get real burst... */
309 	sc->sc_burst = EBDCSR_BURST_8;
310 }
311 
312 /*
313  * Write to one of the indexed registers of cs4231.
314  */
315 void
316 ce4231_write(sc, r, v)
317 	struct ce4231_softc *sc;
318 	u_int8_t r, v;
319 {
320 	CS_WRITE(sc, AD1848_IADDR, r);
321 	CS_WRITE(sc, AD1848_IDATA, v);
322 }
323 
324 /*
325  * Read from one of the indexed registers of cs4231.
326  */
327 u_int8_t
328 ce4231_read(sc, r)
329 	struct ce4231_softc *sc;
330 	u_int8_t r;
331 {
332 	CS_WRITE(sc, AD1848_IADDR, r);
333 	return (CS_READ(sc, AD1848_IDATA));
334 }
335 
336 int
337 ce4231_set_speed(sc, argp)
338 	struct ce4231_softc *sc;
339 	u_long *argp;
340 
341 {
342 	/*
343 	 * The available speeds are in the following table. Keep the speeds in
344 	 * the increasing order.
345 	 */
346 	typedef struct {
347 		int speed;
348 		u_char bits;
349 	} speed_struct;
350 	u_long arg = *argp;
351 
352 	static speed_struct speed_table[] = {
353 		{5510,	(0 << 1) | CLOCK_XTAL2},
354 		{5510,	(0 << 1) | CLOCK_XTAL2},
355 		{6620,	(7 << 1) | CLOCK_XTAL2},
356 		{8000,	(0 << 1) | CLOCK_XTAL1},
357 		{9600,	(7 << 1) | CLOCK_XTAL1},
358 		{11025,	(1 << 1) | CLOCK_XTAL2},
359 		{16000,	(1 << 1) | CLOCK_XTAL1},
360 		{18900,	(2 << 1) | CLOCK_XTAL2},
361 		{22050,	(3 << 1) | CLOCK_XTAL2},
362 		{27420,	(2 << 1) | CLOCK_XTAL1},
363 		{32000,	(3 << 1) | CLOCK_XTAL1},
364 		{33075,	(6 << 1) | CLOCK_XTAL2},
365 		{33075,	(4 << 1) | CLOCK_XTAL2},
366 		{44100,	(5 << 1) | CLOCK_XTAL2},
367 		{48000,	(6 << 1) | CLOCK_XTAL1},
368 	};
369 
370 	int i, n, selected = -1;
371 
372 	n = sizeof(speed_table) / sizeof(speed_struct);
373 
374 	if (arg < speed_table[0].speed)
375 		selected = 0;
376 	if (arg > speed_table[n - 1].speed)
377 		selected = n - 1;
378 
379 	for (i = 1; selected == -1 && i < n; i++) {
380 		if (speed_table[i].speed == arg)
381 			selected = i;
382 		else if (speed_table[i].speed > arg) {
383 			int diff1, diff2;
384 
385 			diff1 = arg - speed_table[i - 1].speed;
386 			diff2 = speed_table[i].speed - arg;
387 			if (diff1 < diff2)
388 				selected = i - 1;
389 			else
390 				selected = i;
391 		}
392 	}
393 
394 	if (selected == -1)
395 		selected = 3;
396 
397 	sc->sc_speed_bits = speed_table[selected].bits;
398 	sc->sc_need_commit = 1;
399 	*argp = speed_table[selected].speed;
400 
401 	return (0);
402 }
403 
404 /*
405  * Audio interface functions
406  */
407 int
408 ce4231_open(addr, flags)
409 	void *addr;
410 	int flags;
411 {
412 	struct ce4231_softc *sc = addr;
413 	int tries;
414 
415 	DPRINTF(("ce4231_open\n"));
416 
417 	if (sc->sc_open)
418 		return (EBUSY);
419 
420 	sc->sc_open = 1;
421 	sc->sc_rintr = 0;
422 	sc->sc_rarg = 0;
423 	sc->sc_pintr = 0;
424 	sc->sc_parg = 0;
425 
426 	P_WRITE(sc, EBDMA_DCSR, EBDCSR_RESET);
427 	C_WRITE(sc, EBDMA_DCSR, EBDCSR_RESET);
428 	P_WRITE(sc, EBDMA_DCSR, sc->sc_burst);
429 	C_WRITE(sc, EBDMA_DCSR, sc->sc_burst);
430 
431 	DELAY(20);
432 
433 	for (tries = CS_TIMEOUT;
434 	     tries && CS_READ(sc, AD1848_IADDR) == SP_IN_INIT; tries--)
435 		DELAY(10);
436 	if (tries == 0)
437 		printf("%s: timeout waiting for reset\n", sc->sc_dev.dv_xname);
438 
439 	ce4231_write(sc, SP_PIN_CONTROL,
440 	    ce4231_read(sc, SP_PIN_CONTROL) | INTERRUPT_ENABLE);
441 
442 	return (0);
443 }
444 
445 void
446 ce4231_close(addr)
447 	void *addr;
448 {
449 	struct ce4231_softc *sc = addr;
450 
451 	ce4231_halt_input(sc);
452 	ce4231_halt_output(sc);
453 	ce4231_write(sc, SP_PIN_CONTROL,
454 	    ce4231_read(sc, SP_PIN_CONTROL) & (~INTERRUPT_ENABLE));
455 	sc->sc_open = 0;
456 }
457 
458 int
459 ce4231_set_params(addr, setmode, usemode, p, r)
460 	void *addr;
461 	int setmode, usemode;
462 	struct audio_params *p, *r;
463 {
464 	struct ce4231_softc *sc = (struct ce4231_softc *)addr;
465 	int err, bits, enc = p->encoding;
466 
467 	if (p->precision > 16)
468 		p->precision = 16;
469 	switch (enc) {
470 	case AUDIO_ENCODING_ULAW:
471 		p->precision = 8;
472 		bits = FMT_ULAW >> 5;
473 		break;
474 	case AUDIO_ENCODING_ALAW:
475 		p->precision = 8;
476 		bits = FMT_ALAW >> 5;
477 		break;
478 	case AUDIO_ENCODING_SLINEAR_LE:
479 		p->precision = 16;
480 		bits = FMT_TWOS_COMP >> 5;
481 		break;
482 	case AUDIO_ENCODING_SLINEAR_BE:
483 		p->precision = 16;
484 		bits = FMT_TWOS_COMP_BE >> 5;
485 		break;
486 	case AUDIO_ENCODING_ULINEAR_LE:
487 	case AUDIO_ENCODING_ULINEAR_BE:
488 		p->precision = 8;
489 		break;
490 	default:
491 		return (EINVAL);
492 	}
493 
494 	if (p->channels > 2)
495 		p->channels = 2;
496 
497 	err = ce4231_set_speed(sc, &p->sample_rate);
498 	if (err)
499 		return (err);
500 
501 	p->bps = AUDIO_BPS(p->precision);
502 	r->bps = AUDIO_BPS(r->precision);
503 	p->msb = r->msb = 1;
504 
505 	sc->sc_format_bits = bits;
506 	sc->sc_channels = p->channels;
507 	sc->sc_precision = p->precision;
508 	sc->sc_need_commit = 1;
509 	return (0);
510 }
511 
512 int
513 ce4231_round_blocksize(addr, blk)
514 	void *addr;
515 	int blk;
516 {
517 	return ((blk + 3) & (-4));
518 }
519 
520 int
521 ce4231_commit_settings(addr)
522 	void *addr;
523 {
524 	struct ce4231_softc *sc = (struct ce4231_softc *)addr;
525 	int tries;
526 	u_int8_t r, fs;
527 
528 	if (sc->sc_need_commit == 0)
529 		return (0);
530 
531 	fs = sc->sc_speed_bits | (sc->sc_format_bits << 5);
532 	if (sc->sc_channels == 2)
533 		fs |= FMT_STEREO;
534 
535 	if (sc->sc_last_format == fs) {
536 		sc->sc_need_commit = 0;
537 		return (0);
538 	}
539 
540 	/* XXX: this code is called before DMA (this intrs) is stopped */
541 	mtx_enter(&audio_lock);
542 
543 	r = ce4231_read(sc, SP_INTERFACE_CONFIG) | AUTO_CAL_ENABLE;
544 	CS_WRITE(sc, AD1848_IADDR, MODE_CHANGE_ENABLE);
545 	CS_WRITE(sc, AD1848_IADDR, MODE_CHANGE_ENABLE | SP_INTERFACE_CONFIG);
546 	CS_WRITE(sc, AD1848_IDATA, r);
547 
548 	CS_WRITE(sc, AD1848_IADDR, MODE_CHANGE_ENABLE | SP_CLOCK_DATA_FORMAT);
549 	CS_WRITE(sc, AD1848_IDATA, fs);
550 	CS_READ(sc, AD1848_IDATA);
551 	CS_READ(sc, AD1848_IDATA);
552 	tries = CS_TIMEOUT;
553 	for (tries = CS_TIMEOUT;
554 	     tries && CS_READ(sc, AD1848_IADDR) == SP_IN_INIT; tries--)
555 		DELAY(10);
556 	if (tries == 0)
557 		printf("%s: timeout committing fspb\n", sc->sc_dev.dv_xname);
558 
559 	CS_WRITE(sc, AD1848_IADDR, MODE_CHANGE_ENABLE | CS_REC_FORMAT);
560 	CS_WRITE(sc, AD1848_IDATA, fs);
561 	CS_READ(sc, AD1848_IDATA);
562 	CS_READ(sc, AD1848_IDATA);
563 	for (tries = CS_TIMEOUT;
564 	     tries && CS_READ(sc, AD1848_IADDR) == SP_IN_INIT; tries--)
565 		DELAY(10);
566 	if (tries == 0)
567 		printf("%s: timeout committing cdf\n", sc->sc_dev.dv_xname);
568 
569 	CS_WRITE(sc, AD1848_IADDR, 0);
570 	for (tries = CS_TIMEOUT;
571 	     tries && CS_READ(sc, AD1848_IADDR) == SP_IN_INIT; tries--)
572 		DELAY(10);
573 	if (tries == 0)
574 		printf("%s: timeout waiting for !mce\n", sc->sc_dev.dv_xname);
575 
576 	CS_WRITE(sc, AD1848_IADDR, SP_TEST_AND_INIT);
577 	for (tries = CS_TIMEOUT;
578 	     tries && CS_READ(sc, AD1848_IDATA) & AUTO_CAL_IN_PROG; tries--)
579 		DELAY(10);
580 	if (tries == 0)
581 		printf("%s: timeout waiting for autocalibration\n",
582 		    sc->sc_dev.dv_xname);
583 
584 	mtx_leave(&audio_lock);
585 
586 	sc->sc_need_commit = 0;
587 	return (0);
588 }
589 
590 int
591 ce4231_halt_output(addr)
592 	void *addr;
593 {
594 	struct ce4231_softc *sc = (struct ce4231_softc *)addr;
595 
596 	P_WRITE(sc, EBDMA_DCSR,
597 	    P_READ(sc, EBDMA_DCSR) & ~EBDCSR_DMAEN);
598 	ce4231_write(sc, SP_INTERFACE_CONFIG,
599 	    ce4231_read(sc, SP_INTERFACE_CONFIG) & (~PLAYBACK_ENABLE));
600 	return (0);
601 }
602 
603 int
604 ce4231_halt_input(addr)
605 	void *addr;
606 {
607 	struct ce4231_softc *sc = (struct ce4231_softc *)addr;
608 
609 	C_WRITE(sc, EBDMA_DCSR,
610 	    C_READ(sc, EBDMA_DCSR) & ~EBDCSR_DMAEN);
611 	ce4231_write(sc, SP_INTERFACE_CONFIG,
612 	    ce4231_read(sc, SP_INTERFACE_CONFIG) & (~CAPTURE_ENABLE));
613 	return (0);
614 }
615 
616 void
617 ce4231_set_outputs(struct ce4231_softc *sc, int mask)
618 {
619 	u_int8_t val;
620 
621 	val = ce4231_read(sc, CS_MONO_IO_CONTROL) & ~MONO_OUTPUT_MUTE;
622 	if (!(mask & OUT_PORT_SPKR))
623 		val |= MONO_OUTPUT_MUTE;
624 	ce4231_write(sc, CS_MONO_IO_CONTROL, val);
625 
626 	val = ce4231_read(sc, SP_PIN_CONTROL) & ~(XCTL0_ENABLE | XCTL1_ENABLE);
627 	if (!(mask & OUT_PORT_LINE))
628 		val |= XCTL0_ENABLE;
629 	if (!(mask & OUT_PORT_HP))
630 		val |= XCTL1_ENABLE;
631 	ce4231_write(sc, SP_PIN_CONTROL, val);
632 }
633 
634 int
635 ce4231_get_outputs(struct ce4231_softc *sc)
636 {
637 	int mask = 0;
638 	u_int8_t val;
639 
640 	if (!(ce4231_read(sc, CS_MONO_IO_CONTROL) & MONO_OUTPUT_MUTE))
641 		mask |= OUT_PORT_SPKR;
642 
643 	val = ce4231_read(sc, SP_PIN_CONTROL);
644 	if (!(val & XCTL0_ENABLE))
645 		mask |= OUT_PORT_LINE;
646 	if (!(val & XCTL1_ENABLE))
647 		mask |= OUT_PORT_HP;
648 
649 	return (mask);
650 }
651 
652 int
653 ce4231_set_port(void *addr, mixer_ctrl_t *cp)
654 {
655 	struct ce4231_softc *sc = (struct ce4231_softc *)addr;
656 	u_int8_t l, r;
657 
658 	DPRINTF(("ce4231_set_port: dev=%d type=%d\n", cp->dev, cp->type));
659 
660 	switch (cp->dev) {
661 
662 	case CSAUDIO_DAC_LVL:
663 		if (cp->type != AUDIO_MIXER_VALUE)
664 			return (EINVAL);
665 		l = ce4231_read(sc, SP_LEFT_OUTPUT_CONTROL) &
666 		    OUTPUT_ATTEN_MASK;
667 		r = ce4231_read(sc, SP_RIGHT_OUTPUT_CONTROL) &
668 		    OUTPUT_ATTEN_MASK;
669 		l |= (AUDIO_MAX_GAIN -
670 		    cp->un.value.level[AUDIO_MIXER_LEVEL_LEFT]) >> 2;
671 		r |= (AUDIO_MAX_GAIN -
672 		    cp->un.value.level[AUDIO_MIXER_LEVEL_RIGHT]) >> 2;
673 		ce4231_write(sc, SP_LEFT_OUTPUT_CONTROL, l);
674 		ce4231_write(sc, SP_RIGHT_OUTPUT_CONTROL, r);
675 		break;
676 	case CSAUDIO_DAC_MUTE:
677 		if (cp->type != AUDIO_MIXER_ENUM)
678 			return (EINVAL);
679 		l = ce4231_read(sc, SP_LEFT_OUTPUT_CONTROL) & ~OUTPUT_MUTE;
680 		r = ce4231_read(sc, SP_RIGHT_OUTPUT_CONTROL) & ~OUTPUT_MUTE;
681 		if (cp->un.ord) {
682 			l |= OUTPUT_MUTE;
683 			r |= OUTPUT_MUTE;
684 		}
685 		ce4231_write(sc, SP_LEFT_OUTPUT_CONTROL, l);
686 		ce4231_write(sc, SP_RIGHT_OUTPUT_CONTROL, r);
687 		break;
688 
689 	case CSAUDIO_OUTPUTS:
690 		if (cp->type != AUDIO_MIXER_SET)
691 			return (EINVAL);
692 		ce4231_set_outputs(sc, cp->un.mask);
693 		break;
694 
695 	case CSAUDIO_CD_LVL:
696 		if (cp->type != AUDIO_MIXER_VALUE)
697 			return (EINVAL);
698 		l = ce4231_read(sc, SP_LEFT_AUX1_CONTROL) &
699 		    AUX_INPUT_ATTEN_MASK;
700 		r = ce4231_read(sc, SP_RIGHT_AUX1_CONTROL) &
701 		    AUX_INPUT_ATTEN_MASK;
702 		l |= (AUDIO_MAX_GAIN -
703 		    cp->un.value.level[AUDIO_MIXER_LEVEL_LEFT]) >> 3;
704 		r |= (AUDIO_MAX_GAIN -
705 		    cp->un.value.level[AUDIO_MIXER_LEVEL_RIGHT]) >> 3;
706 		ce4231_write(sc, SP_LEFT_AUX1_CONTROL, l);
707 		ce4231_write(sc, SP_RIGHT_AUX1_CONTROL, r);
708 		break;
709 	case CSAUDIO_CD_MUTE:
710 		if (cp->type != AUDIO_MIXER_ENUM)
711 			return (EINVAL);
712 		l = ce4231_read(sc, SP_LEFT_AUX1_CONTROL) & ~AUX_INPUT_MUTE;
713 		r = ce4231_read(sc, SP_RIGHT_AUX1_CONTROL) & ~AUX_INPUT_MUTE;
714 		if (cp->un.ord) {
715 			l |= AUX_INPUT_MUTE;
716 			r |= AUX_INPUT_MUTE;
717 		}
718 		ce4231_write(sc, SP_LEFT_AUX1_CONTROL, l);
719 		ce4231_write(sc, SP_RIGHT_AUX1_CONTROL, r);
720 		break;
721 
722 	case CSAUDIO_LINE_IN_LVL:
723 		if (cp->type != AUDIO_MIXER_VALUE)
724 			return (EINVAL);
725 		l = ce4231_read(sc, CS_LEFT_LINE_CONTROL) &
726 		    LINE_INPUT_ATTEN_MASK;
727 		r = ce4231_read(sc, CS_RIGHT_LINE_CONTROL) &
728 		    LINE_INPUT_ATTEN_MASK;
729 		l |= (AUDIO_MAX_GAIN -
730 		    cp->un.value.level[AUDIO_MIXER_LEVEL_LEFT]) >> 3;
731 		r |= (AUDIO_MAX_GAIN -
732 		    cp->un.value.level[AUDIO_MIXER_LEVEL_RIGHT]) >> 3;
733 		ce4231_write(sc, CS_LEFT_LINE_CONTROL, l);
734 		ce4231_write(sc, CS_RIGHT_LINE_CONTROL, r);
735 		break;
736 	case CSAUDIO_LINE_IN_MUTE:
737 		l = ce4231_read(sc, CS_LEFT_LINE_CONTROL) & ~LINE_INPUT_MUTE;
738 		r = ce4231_read(sc, CS_RIGHT_LINE_CONTROL) & ~LINE_INPUT_MUTE;
739 		if (cp->un.ord) {
740 			l |= LINE_INPUT_MUTE;
741 			r |= LINE_INPUT_MUTE;
742 		}
743 		ce4231_write(sc, CS_LEFT_LINE_CONTROL, l);
744 		ce4231_write(sc, CS_RIGHT_LINE_CONTROL, r);
745 		break;
746 
747 	case CSAUDIO_MONITOR_LVL:
748 		if (cp->type != AUDIO_MIXER_VALUE)
749 			return (EINVAL);
750 		if (cp->un.value.num_channels != 1)
751 			return (EINVAL);
752 		l = ce4231_read(sc, SP_DIGITAL_MIX) & ~MIX_ATTEN_MASK;
753 		l |= (AUDIO_MAX_GAIN -
754 		    cp->un.value.level[AUDIO_MIXER_LEVEL_MONO]) &
755 		    MIX_ATTEN_MASK;
756 		ce4231_write(sc, SP_DIGITAL_MIX, l);
757 		break;
758 	case CSAUDIO_MONITOR_MUTE:
759 		if (cp->type != AUDIO_MIXER_ENUM)
760 			return (EINVAL);
761 		l = ce4231_read(sc, SP_DIGITAL_MIX) & ~DIGITAL_MIX1_ENABLE;
762 		if (!cp->un.ord)
763 			l |= DIGITAL_MIX1_ENABLE;
764 		ce4231_write(sc, SP_DIGITAL_MIX, l);
765 		break;
766 
767 	case CSAUDIO_REC_LVL:
768 		if (cp->type != AUDIO_MIXER_VALUE)
769 			return (EINVAL);
770 		l = ce4231_read(sc, SP_LEFT_INPUT_CONTROL) & INPUT_GAIN_MASK;
771 		r = ce4231_read(sc, SP_RIGHT_INPUT_CONTROL) & INPUT_GAIN_MASK;
772 		l = cp->un.value.level[AUDIO_MIXER_LEVEL_LEFT] >> 4;
773 		r = cp->un.value.level[AUDIO_MIXER_LEVEL_RIGHT] >> 4;
774 		ce4231_write(sc, SP_LEFT_INPUT_CONTROL, l);
775 		ce4231_write(sc, SP_RIGHT_INPUT_CONTROL, r);
776 		break;
777 	case CSAUDIO_RECORD_SOURCE:
778 		if (cp->type != AUDIO_MIXER_ENUM)
779 			return (EINVAL);
780 		l = ce4231_read(sc, SP_LEFT_INPUT_CONTROL) & INPUT_SOURCE_MASK;
781 		r = ce4231_read(sc, SP_RIGHT_INPUT_CONTROL) & INPUT_SOURCE_MASK;
782 		l |= cp->un.ord << 6;
783 		r |= cp->un.ord << 6;
784 		ce4231_write(sc, SP_LEFT_INPUT_CONTROL, l);
785 		ce4231_write(sc, SP_RIGHT_INPUT_CONTROL, r);
786 		break;
787 
788 	case CSAUDIO_MIC_PREAMP:
789 		if (cp->type != AUDIO_MIXER_ENUM)
790 			return (EINVAL);
791 		l = ce4231_read(sc, SP_LEFT_INPUT_CONTROL) &
792 		    ~INPUT_MIC_GAIN_ENABLE;
793 		r = ce4231_read(sc, SP_RIGHT_INPUT_CONTROL) &
794 		    ~INPUT_MIC_GAIN_ENABLE;
795 		if (cp->un.ord) {
796 			l |= INPUT_MIC_GAIN_ENABLE;
797 			r |= INPUT_MIC_GAIN_ENABLE;
798 		}
799 		ce4231_write(sc, SP_LEFT_INPUT_CONTROL, l);
800 		ce4231_write(sc, SP_RIGHT_INPUT_CONTROL, r);
801 		break;
802 
803 	default:
804 		return (EINVAL);
805 	}
806 
807 	return (0);
808 }
809 
810 int
811 ce4231_get_port(void *addr, mixer_ctrl_t *cp)
812 {
813 	struct ce4231_softc *sc = (struct ce4231_softc *)addr;
814 
815 	DPRINTF(("ce4231_get_port: port=%d type=%d\n", cp->dev, cp->type));
816 
817 	switch (cp->dev) {
818 
819 	case CSAUDIO_DAC_LVL:
820 		if (cp->type != AUDIO_MIXER_VALUE)
821 			return (EINVAL);
822 		cp->un.value.level[AUDIO_MIXER_LEVEL_LEFT] =
823 		    AUDIO_MAX_GAIN - ((ce4231_read(sc, SP_LEFT_OUTPUT_CONTROL) &
824 		    OUTPUT_ATTEN_BITS) << 2);
825 		cp->un.value.level[AUDIO_MIXER_LEVEL_RIGHT] =
826 		    AUDIO_MAX_GAIN - ((ce4231_read(sc, SP_RIGHT_OUTPUT_CONTROL) &
827 		    OUTPUT_ATTEN_BITS) << 2);
828 		break;
829 	case CSAUDIO_DAC_MUTE:
830 		if (cp->type != AUDIO_MIXER_ENUM)
831 			return (EINVAL);
832 		cp->un.ord = (ce4231_read(sc, SP_LEFT_OUTPUT_CONTROL) &
833 		    OUTPUT_MUTE) ? 1 : 0;
834 		break;
835 
836 	case CSAUDIO_OUTPUTS:
837 		if (cp->type != AUDIO_MIXER_SET)
838 			return (EINVAL);
839 		cp->un.mask = ce4231_get_outputs(sc);
840 		break;
841 
842 	case CSAUDIO_CD_LVL:
843 		if (cp->type != AUDIO_MIXER_VALUE)
844 			return (EINVAL);
845 		cp->un.value.level[AUDIO_MIXER_LEVEL_LEFT] =
846 		    AUDIO_MAX_GAIN - ((ce4231_read(sc, SP_LEFT_AUX1_CONTROL) &
847 		    AUX_INPUT_ATTEN_BITS) << 3);
848 		cp->un.value.level[AUDIO_MIXER_LEVEL_RIGHT] =
849 		    AUDIO_MAX_GAIN - ((ce4231_read(sc, SP_RIGHT_AUX1_CONTROL) &
850 		    AUX_INPUT_ATTEN_BITS) << 3);
851 		break;
852 	case CSAUDIO_CD_MUTE:
853 		if (cp->type != AUDIO_MIXER_ENUM)
854 			return (EINVAL);
855 		cp->un.ord = (ce4231_read(sc, SP_LEFT_AUX1_CONTROL) &
856 		    AUX_INPUT_MUTE) ? 1 : 0;
857 		break;
858 
859 	case CSAUDIO_LINE_IN_LVL:
860 		if (cp->type != AUDIO_MIXER_VALUE)
861 			return (EINVAL);
862 		cp->un.value.level[AUDIO_MIXER_LEVEL_LEFT] =
863 		    AUDIO_MAX_GAIN - ((ce4231_read(sc, CS_LEFT_LINE_CONTROL) &
864 		    LINE_INPUT_ATTEN_BITS) << 3);
865 		cp->un.value.level[AUDIO_MIXER_LEVEL_RIGHT] =
866 		    AUDIO_MAX_GAIN - ((ce4231_read(sc, CS_RIGHT_LINE_CONTROL) &
867 		    LINE_INPUT_ATTEN_BITS) << 3);
868 		break;
869 	case CSAUDIO_LINE_IN_MUTE:
870 		if (cp->type != AUDIO_MIXER_ENUM)
871 			return (EINVAL);
872 		cp->un.ord = (ce4231_read(sc, CS_LEFT_LINE_CONTROL) &
873 		    LINE_INPUT_MUTE) ? 1 : 0;
874 		break;
875 
876 	case CSAUDIO_MONITOR_LVL:
877 		if (cp->type != AUDIO_MIXER_VALUE)
878 			return (EINVAL);
879 		if (cp->un.value.num_channels != 1)
880 			return (EINVAL);
881 		cp->un.value.level[AUDIO_MIXER_LEVEL_MONO] =
882 		    AUDIO_MAX_GAIN - (ce4231_read(sc, SP_DIGITAL_MIX) &
883 		    MIX_ATTEN_MASK);
884 		break;
885 	case CSAUDIO_MONITOR_MUTE:
886 		if (cp->type != AUDIO_MIXER_ENUM)
887 			return (EINVAL);
888 		cp->un.ord = (ce4231_read(sc, SP_DIGITAL_MIX) &
889 		    DIGITAL_MIX1_ENABLE) ? 0 : 1;
890 		break;
891 
892 	case CSAUDIO_REC_LVL:
893 		if (cp->type != AUDIO_MIXER_VALUE)
894 			return (EINVAL);
895 		cp->un.value.level[AUDIO_MIXER_LEVEL_LEFT] =
896 		    (ce4231_read(sc, SP_LEFT_INPUT_CONTROL) &
897 		    ~INPUT_GAIN_MASK) << 4;
898 		cp->un.value.level[AUDIO_MIXER_LEVEL_RIGHT] =
899 		    (ce4231_read(sc, SP_RIGHT_INPUT_CONTROL) &
900 		    ~INPUT_GAIN_MASK) << 4;
901 		break;
902 	case CSAUDIO_RECORD_SOURCE:
903 		if (cp->type != AUDIO_MIXER_ENUM)
904 			return (EINVAL);
905 		cp->un.ord = (ce4231_read(sc, SP_LEFT_INPUT_CONTROL) &
906 		    CS_REC_SRC_BITS) >> 6;
907 		break;
908 
909 	case CSAUDIO_MIC_PREAMP:
910 		if (cp->type != AUDIO_MIXER_ENUM)
911 			return (EINVAL);
912 		cp->un.ord = (ce4231_read(sc, SP_LEFT_INPUT_CONTROL) &
913 		    INPUT_MIC_GAIN_ENABLE) ? 1 : 0;
914 		break;
915 
916 	default:
917 		return (EINVAL);
918 	}
919 	return (0);
920 }
921 
922 int
923 ce4231_query_devinfo(void *addr, mixer_devinfo_t *dip)
924 {
925 	size_t nsize = MAX_AUDIO_DEV_LEN;
926 	int err = 0;
927 
928 	switch (dip->index) {
929 	case CSAUDIO_INPUT_CLASS:
930 		dip->type = AUDIO_MIXER_CLASS;
931 		dip->mixer_class = CSAUDIO_INPUT_CLASS;
932 		dip->prev = dip->next = AUDIO_MIXER_LAST;
933 		strlcpy(dip->label.name, AudioCinputs, nsize);
934 		break;
935 	case CSAUDIO_OUTPUT_CLASS:
936 		dip->type = AUDIO_MIXER_CLASS;
937 		dip->mixer_class = CSAUDIO_OUTPUT_CLASS;
938 		dip->prev = dip->next = AUDIO_MIXER_LAST;
939 		strlcpy(dip->label.name, AudioCoutputs, nsize);
940 		break;
941 	case CSAUDIO_RECORD_CLASS:
942 		dip->type = AUDIO_MIXER_CLASS;
943 		dip->mixer_class = CSAUDIO_RECORD_CLASS;
944 		dip->prev = dip->next = AUDIO_MIXER_LAST;
945 		strlcpy(dip->label.name, AudioCrecord, nsize);
946 		break;
947 
948 	case CSAUDIO_DAC_LVL:
949 		dip->type = AUDIO_MIXER_VALUE;
950 		dip->mixer_class = CSAUDIO_OUTPUT_CLASS;
951 		dip->prev = AUDIO_MIXER_LAST;
952 		dip->next = CSAUDIO_DAC_MUTE;
953 		strlcpy(dip->label.name, AudioNdac, nsize);
954 		dip->un.v.num_channels = 2;
955 		dip->un.v.delta = 4;
956 		strlcpy(dip->un.v.units.name, AudioNvolume, nsize);
957 		break;
958 	case CSAUDIO_DAC_MUTE:
959 		dip->type = AUDIO_MIXER_ENUM;
960 		dip->mixer_class = CSAUDIO_OUTPUT_CLASS;
961 		dip->prev = CSAUDIO_DAC_LVL;
962 		dip->next = AUDIO_MIXER_LAST;
963 		strlcpy(dip->label.name, AudioNmute, nsize);
964 		goto onoff;
965 
966 	case CSAUDIO_OUTPUTS:
967 		dip->type = AUDIO_MIXER_SET;
968 		dip->mixer_class = CSAUDIO_OUTPUT_CLASS;
969 		dip->prev = dip->next = AUDIO_MIXER_LAST;
970 		strlcpy(dip->label.name, AudioNoutput, nsize);
971 		dip->un.s.num_mem = 3;
972 		strlcpy(dip->un.s.member[0].label.name, AudioNline, nsize);
973 		dip->un.s.member[0].mask = OUT_PORT_LINE;
974 		strlcpy(dip->un.s.member[1].label.name, AudioNheadphone, nsize);
975 		dip->un.s.member[1].mask = OUT_PORT_HP;
976 		strlcpy(dip->un.s.member[2].label.name, AudioNspeaker, nsize);
977 		dip->un.s.member[2].mask = OUT_PORT_SPKR;
978 		break;
979 
980 	case CSAUDIO_CD_LVL:
981 		dip->type = AUDIO_MIXER_VALUE;
982 		dip->mixer_class = CSAUDIO_INPUT_CLASS;
983 		dip->prev = AUDIO_MIXER_LAST;
984 		dip->next = CSAUDIO_CD_MUTE;
985 		strlcpy(dip->label.name, AudioNcd, nsize);
986 		dip->un.v.num_channels = 2;
987 		dip->un.v.delta = 8;
988 		strlcpy(dip->un.v.units.name, AudioNvolume, nsize);
989 		break;
990 	case CSAUDIO_CD_MUTE:
991 		dip->type = AUDIO_MIXER_ENUM;
992 		dip->mixer_class = CSAUDIO_INPUT_CLASS;
993 		dip->prev = CSAUDIO_CD_LVL;
994 		dip->next = AUDIO_MIXER_LAST;
995 		strlcpy(dip->label.name, AudioNmute, nsize);
996 		goto onoff;
997 
998 	case CSAUDIO_LINE_IN_LVL:
999 		dip->type = AUDIO_MIXER_VALUE;
1000 		dip->mixer_class = CSAUDIO_INPUT_CLASS;
1001 		dip->prev = AUDIO_MIXER_LAST;
1002 		dip->next = CSAUDIO_LINE_IN_MUTE;
1003 		strlcpy(dip->label.name, AudioNline, nsize);
1004 		dip->un.v.num_channels = 2;
1005 		dip->un.v.delta = 8;
1006 		strlcpy(dip->un.v.units.name, AudioNvolume, nsize);
1007 		break;
1008 	case CSAUDIO_LINE_IN_MUTE:
1009 		dip->type = AUDIO_MIXER_ENUM;
1010 		dip->mixer_class = CSAUDIO_INPUT_CLASS;
1011 		dip->prev = CSAUDIO_LINE_IN_LVL;
1012 		dip->next = AUDIO_MIXER_LAST;
1013 		strlcpy(dip->label.name, AudioNmute, nsize);
1014 		goto onoff;
1015 
1016 	case CSAUDIO_MONITOR_LVL:
1017 		dip->type = AUDIO_MIXER_VALUE;
1018 		dip->mixer_class = CSAUDIO_OUTPUT_CLASS;
1019 		dip->prev = AUDIO_MIXER_LAST;
1020 		dip->next = CSAUDIO_MONITOR_MUTE;
1021 		strlcpy(dip->label.name, AudioNmonitor, nsize);
1022 		dip->un.v.num_channels = 1;
1023 		dip->un.v.delta = 4;
1024 		strlcpy(dip->un.v.units.name, AudioNvolume, nsize);
1025 		break;
1026 	case CSAUDIO_MONITOR_MUTE:
1027 		dip->type = AUDIO_MIXER_ENUM;
1028 		dip->mixer_class = CSAUDIO_OUTPUT_CLASS;
1029 		dip->prev = CSAUDIO_MONITOR_LVL;
1030 		dip->next = AUDIO_MIXER_LAST;
1031 		strlcpy(dip->label.name, AudioNmute, nsize);
1032 		goto onoff;
1033 
1034 	case CSAUDIO_REC_LVL:
1035 		dip->type = AUDIO_MIXER_VALUE;
1036 		dip->mixer_class = CSAUDIO_RECORD_CLASS;
1037 		dip->prev = dip->next = AUDIO_MIXER_LAST;
1038 		strlcpy(dip->label.name, AudioNvolume, nsize);
1039 		dip->un.v.num_channels = 2;
1040 		dip->un.v.delta = 16;
1041 		strlcpy(dip->un.v.units.name, AudioNvolume, nsize);
1042 		break;
1043 	case CSAUDIO_RECORD_SOURCE:
1044 		dip->type = AUDIO_MIXER_ENUM;
1045 		dip->mixer_class = CSAUDIO_RECORD_CLASS;
1046 		dip->prev = dip->next = AUDIO_MIXER_LAST;
1047 		strlcpy(dip->label.name, AudioNsource, nsize);
1048 		dip->un.e.num_mem = 4;
1049 		strlcpy(dip->un.e.member[0].label.name, AudioNline, nsize);
1050 		dip->un.e.member[0].ord = REC_PORT_LINE;
1051 		strlcpy(dip->un.e.member[1].label.name, AudioNcd, nsize);
1052 		dip->un.e.member[1].ord = REC_PORT_CD;
1053 		strlcpy(dip->un.e.member[2].label.name, AudioNmicrophone, nsize);
1054 		dip->un.e.member[2].ord = REC_PORT_MIC;
1055 		strlcpy(dip->un.e.member[3].label.name, AudioNmixerout, nsize);
1056 		dip->un.e.member[3].ord = REC_PORT_MIX;
1057 		break;
1058 
1059 	case CSAUDIO_MIC_PREAMP:
1060 		dip->type = AUDIO_MIXER_ENUM;
1061 		dip->mixer_class = CSAUDIO_RECORD_CLASS;
1062 		dip->prev = dip->next = AUDIO_MIXER_LAST;
1063 		snprintf(dip->label.name, nsize, "%s_%s", AudioNmicrophone,
1064 		   AudioNpreamp);
1065 		goto onoff;
1066 
1067 onoff:
1068 		dip->un.e.num_mem = 2;
1069 		strlcpy(dip->un.e.member[0].label.name, AudioNon, nsize);
1070 		dip->un.e.member[0].ord = 1;
1071 		strlcpy(dip->un.e.member[1].label.name, AudioNoff, nsize);
1072 		dip->un.e.member[1].ord = 0;
1073 		break;
1074 
1075 	default:
1076 		err = ENXIO;
1077 	}
1078 
1079 	return (err);
1080 }
1081 
1082 int
1083 ce4231_get_props(addr)
1084 	void *addr;
1085 {
1086 	return (AUDIO_PROP_FULLDUPLEX);
1087 }
1088 
1089 /*
1090  * Hardware interrupt handler
1091  */
1092 /*
1093  * Don't bother with the AD1848_STATUS register.  It's interrupt bit gets
1094  * set for both recording and playback interrupts.  But we have separate
1095  * handlers for playback and recording, and if we clear the status in
1096  * one handler while there is an interrupt pending for the other direction
1097  * as well, we'll never notice the interrupt for the other direction.
1098  *
1099  * Instead rely solely on CS_IRQ_STATUS, which has separate bits for
1100  * playback and recording interrupts.  Also note that resetting
1101  * AD1848_STATUS clears the interrupt bits in CS_IRQ_STATUS.
1102  */
1103 
1104 int
1105 ce4231_pintr(v)
1106 	void *v;
1107 {
1108 	struct ce4231_softc *sc = (struct ce4231_softc *)v;
1109 	u_int32_t csr;
1110 	u_int8_t reg;
1111 	struct cs_dma *p;
1112 	struct cs_chdma *chdma = &sc->sc_pchdma;
1113 	int r = 0;
1114 
1115 	mtx_enter(&audio_lock);
1116 	csr = P_READ(sc, EBDMA_DCSR);
1117 
1118 	reg = ce4231_read(sc, CS_IRQ_STATUS);
1119 	if (reg & CS_IRQ_PI) {
1120 		ce4231_write(sc, SP_LOWER_BASE_COUNT, 0xff);
1121 		ce4231_write(sc, SP_UPPER_BASE_COUNT, 0xff);
1122 		ce4231_write(sc, CS_IRQ_STATUS, reg & ~CS_IRQ_PI);
1123 	}
1124 
1125 	P_WRITE(sc, EBDMA_DCSR, csr);
1126 
1127 	if (csr & EBDCSR_INT)
1128 		r = 1;
1129 
1130 	if ((csr & EBDCSR_TC) || ((csr & EBDCSR_A_LOADED) == 0)) {
1131 		u_long nextaddr, togo;
1132 
1133 		p = chdma->cur_dma;
1134 		togo = chdma->segsz - chdma->count;
1135 		if (togo == 0) {
1136 			nextaddr = (u_int32_t)p->dmamap->dm_segs[0].ds_addr;
1137 			chdma->count = togo = chdma->blksz;
1138 		} else {
1139 			nextaddr = chdma->lastaddr;
1140 			if (togo > chdma->blksz)
1141 				togo = chdma->blksz;
1142 			chdma->count += togo;
1143 		}
1144 
1145 		P_WRITE(sc, EBDMA_DCNT, togo);
1146 		P_WRITE(sc, EBDMA_DADDR, nextaddr);
1147 		chdma->lastaddr = nextaddr + togo;
1148 
1149 		if (sc->sc_pintr != NULL)
1150 			(*sc->sc_pintr)(sc->sc_parg);
1151 		r = 1;
1152 	}
1153 	mtx_leave(&audio_lock);
1154 	return (r);
1155 }
1156 
1157 int
1158 ce4231_cintr(v)
1159 	void *v;
1160 {
1161 	struct ce4231_softc *sc = (struct ce4231_softc *)v;
1162 	u_int32_t csr;
1163 	u_int8_t reg;
1164 	struct cs_dma *p;
1165 	struct cs_chdma *chdma = &sc->sc_rchdma;
1166 	int r = 0;
1167 
1168 	mtx_enter(&audio_lock);
1169 	csr = C_READ(sc, EBDMA_DCSR);
1170 
1171 	reg = ce4231_read(sc, CS_IRQ_STATUS);
1172 	if (reg & CS_IRQ_CI) {
1173 		ce4231_write(sc, CS_LOWER_REC_CNT, 0xff);
1174 		ce4231_write(sc, CS_UPPER_REC_CNT, 0xff);
1175 		ce4231_write(sc, CS_IRQ_STATUS, reg & ~CS_IRQ_CI);
1176 	}
1177 
1178 	C_WRITE(sc, EBDMA_DCSR, csr);
1179 
1180 	if (csr & EBDCSR_INT)
1181 		r = 1;
1182 
1183 	if ((csr & EBDCSR_TC) || ((csr & EBDCSR_A_LOADED) == 0)) {
1184 		u_long nextaddr, togo;
1185 
1186 		p = chdma->cur_dma;
1187 		togo = chdma->segsz - chdma->count;
1188 		if (togo == 0) {
1189 			nextaddr = (u_int32_t)p->dmamap->dm_segs[0].ds_addr;
1190 			chdma->count = togo = chdma->blksz;
1191 		} else {
1192 			nextaddr = chdma->lastaddr;
1193 			if (togo > chdma->blksz)
1194 				togo = chdma->blksz;
1195 			chdma->count += togo;
1196 		}
1197 
1198 		C_WRITE(sc, EBDMA_DCNT, togo);
1199 		C_WRITE(sc, EBDMA_DADDR, nextaddr);
1200 		chdma->lastaddr = nextaddr + togo;
1201 
1202 		if (sc->sc_rintr != NULL)
1203 			(*sc->sc_rintr)(sc->sc_rarg);
1204 		r = 1;
1205 	}
1206 	mtx_leave(&audio_lock);
1207 	return (r);
1208 }
1209 
1210 void *
1211 ce4231_alloc(addr, direction, size, pool, flags)
1212 	void *addr;
1213 	int direction;
1214 	size_t size;
1215 	int pool;
1216 	int flags;
1217 {
1218 	struct ce4231_softc *sc = (struct ce4231_softc *)addr;
1219 	bus_dma_tag_t dmat = sc->sc_dmatag;
1220 	struct cs_dma *p;
1221 
1222 	p = (struct cs_dma *)malloc(sizeof(struct cs_dma), pool, flags);
1223 	if (p == NULL)
1224 		return (NULL);
1225 
1226 	if (bus_dmamap_create(dmat, size, 1, size, 0,
1227 	    BUS_DMA_NOWAIT, &p->dmamap) != 0)
1228 		goto fail;
1229 
1230 	p->size = size;
1231 
1232 	if (bus_dmamem_alloc(dmat, size, 64*1024, 0, p->segs,
1233 	    sizeof(p->segs)/sizeof(p->segs[0]), &p->nsegs,
1234 	    BUS_DMA_NOWAIT) != 0)
1235 		goto fail1;
1236 
1237 	if (bus_dmamem_map(dmat, p->segs, p->nsegs, p->size,
1238 	    &p->addr, BUS_DMA_NOWAIT | BUS_DMA_COHERENT) != 0)
1239 		goto fail2;
1240 
1241 	if (bus_dmamap_load(dmat, p->dmamap, p->addr, size, NULL,
1242 	    BUS_DMA_NOWAIT) != 0)
1243 		goto fail3;
1244 
1245 	p->next = sc->sc_dmas;
1246 	sc->sc_dmas = p;
1247 	return (p->addr);
1248 
1249 fail3:
1250 	bus_dmamem_unmap(dmat, p->addr, p->size);
1251 fail2:
1252 	bus_dmamem_free(dmat, p->segs, p->nsegs);
1253 fail1:
1254 	bus_dmamap_destroy(dmat, p->dmamap);
1255 fail:
1256 	free(p, pool, 0);
1257 	return (NULL);
1258 }
1259 
1260 void
1261 ce4231_free(addr, ptr, pool)
1262 	void *addr;
1263 	void *ptr;
1264 	int pool;
1265 {
1266 	struct ce4231_softc *sc = addr;
1267 	bus_dma_tag_t dmat = sc->sc_dmatag;
1268 	struct cs_dma *p, **pp;
1269 
1270 	for (pp = &sc->sc_dmas; (p = *pp) != NULL; pp = &(*pp)->next) {
1271 		if (p->addr != ptr)
1272 			continue;
1273 		bus_dmamap_unload(dmat, p->dmamap);
1274 		bus_dmamem_unmap(dmat, p->addr, p->size);
1275 		bus_dmamem_free(dmat, p->segs, p->nsegs);
1276 		bus_dmamap_destroy(dmat, p->dmamap);
1277 		*pp = p->next;
1278 		free(p, pool, 0);
1279 		return;
1280 	}
1281 	printf("%s: attempt to free rogue pointer\n", sc->sc_dev.dv_xname);
1282 }
1283 
1284 int
1285 ce4231_trigger_output(addr, start, end, blksize, intr, arg, param)
1286 	void *addr, *start, *end;
1287 	int blksize;
1288 	void (*intr)(void *);
1289 	void *arg;
1290 	struct audio_params *param;
1291 {
1292 	struct ce4231_softc *sc = addr;
1293 	struct cs_dma *p;
1294 	struct cs_chdma *chdma = &sc->sc_pchdma;
1295 	u_int32_t csr;
1296 	vaddr_t n;
1297 
1298 	sc->sc_pintr = intr;
1299 	sc->sc_parg = arg;
1300 
1301 	for (p = sc->sc_dmas; p->addr != start; p = p->next)
1302 		/*EMPTY*/;
1303 	if (p == NULL) {
1304 		printf("%s: trigger_output: bad addr: %p\n",
1305 		    sc->sc_dev.dv_xname, start);
1306 		return (EINVAL);
1307 	}
1308 
1309 	n = (char *)end - (char *)start;
1310 
1311 	/*
1312 	 * Do only `blksize' at a time, so audio_pint() is kept
1313 	 * synchronous with us...
1314 	 */
1315 	chdma->cur_dma = p;
1316 	chdma->blksz = blksize;
1317 	chdma->segsz = n;
1318 
1319 	if (n > chdma->blksz)
1320 		n = chdma->blksz;
1321 
1322 	chdma->count = n;
1323 
1324 	csr = P_READ(sc, EBDMA_DCSR);
1325 	if (csr & EBDCSR_DMAEN) {
1326 		P_WRITE(sc, EBDMA_DCNT, (u_long)n);
1327 		P_WRITE(sc, EBDMA_DADDR,
1328 		    (u_long)p->dmamap->dm_segs[0].ds_addr);
1329 	} else {
1330 		P_WRITE(sc, EBDMA_DCSR, EBDCSR_RESET);
1331 		P_WRITE(sc, EBDMA_DCSR, sc->sc_burst);
1332 
1333 		P_WRITE(sc, EBDMA_DCNT, (u_long)n);
1334 		P_WRITE(sc, EBDMA_DADDR,
1335 		    (u_long)p->dmamap->dm_segs[0].ds_addr);
1336 
1337 		P_WRITE(sc, EBDMA_DCSR, sc->sc_burst | EBDCSR_DMAEN |
1338 		    EBDCSR_INTEN | EBDCSR_CNTEN | EBDCSR_NEXTEN);
1339 
1340 		ce4231_write(sc, SP_LOWER_BASE_COUNT, 0xff);
1341 		ce4231_write(sc, SP_UPPER_BASE_COUNT, 0xff);
1342 		ce4231_write(sc, SP_INTERFACE_CONFIG,
1343 		    ce4231_read(sc, SP_INTERFACE_CONFIG) | PLAYBACK_ENABLE);
1344 	}
1345 	chdma->lastaddr = p->dmamap->dm_segs[0].ds_addr + n;
1346 
1347 	return (0);
1348 }
1349 
1350 int
1351 ce4231_trigger_input(addr, start, end, blksize, intr, arg, param)
1352 	void *addr, *start, *end;
1353 	int blksize;
1354 	void (*intr)(void *);
1355 	void *arg;
1356 	struct audio_params *param;
1357 {
1358 	struct ce4231_softc *sc = addr;
1359 	struct cs_dma *p;
1360 	struct cs_chdma *chdma = &sc->sc_rchdma;
1361 	u_int32_t csr;
1362 	vaddr_t n;
1363 
1364 	sc->sc_rintr = intr;
1365 	sc->sc_rarg = arg;
1366 
1367 	for (p = sc->sc_dmas; p->addr != start; p = p->next)
1368 		/*EMPTY*/;
1369 	if (p == NULL) {
1370 		printf("%s: trigger_input: bad addr: %p\n",
1371 		    sc->sc_dev.dv_xname, start);
1372 		return (EINVAL);
1373 	}
1374 
1375 	n = (char *)end - (char *)start;
1376 
1377 	/*
1378 	 * Do only `blksize' at a time, so audio_rint() is kept
1379 	 * synchronous with us...
1380 	 */
1381 	chdma->cur_dma = p;
1382 	chdma->blksz = blksize;
1383 	chdma->segsz = n;
1384 
1385 	if (n > chdma->blksz)
1386 		n = chdma->blksz;
1387 
1388 	chdma->count = n;
1389 
1390 	csr = C_READ(sc, EBDMA_DCSR);
1391 	if (csr & EBDCSR_DMAEN) {
1392 		C_WRITE(sc, EBDMA_DCNT, (u_long)n);
1393 		C_WRITE(sc, EBDMA_DADDR,
1394 		    (u_long)p->dmamap->dm_segs[0].ds_addr);
1395 	} else {
1396 		C_WRITE(sc, EBDMA_DCSR, EBDCSR_RESET);
1397 		C_WRITE(sc, EBDMA_DCSR, sc->sc_burst);
1398 
1399 		C_WRITE(sc, EBDMA_DCNT, (u_long)n);
1400 		C_WRITE(sc, EBDMA_DADDR,
1401 		    (u_long)p->dmamap->dm_segs[0].ds_addr);
1402 
1403 		C_WRITE(sc, EBDMA_DCSR, sc->sc_burst | EBDCSR_WRITE |
1404 		    EBDCSR_DMAEN | EBDCSR_INTEN | EBDCSR_CNTEN | EBDCSR_NEXTEN);
1405 
1406 		ce4231_write(sc, CS_LOWER_REC_CNT, 0xff);
1407 		ce4231_write(sc, CS_UPPER_REC_CNT, 0xff);
1408 		ce4231_write(sc, SP_INTERFACE_CONFIG,
1409 		    ce4231_read(sc, SP_INTERFACE_CONFIG) | CAPTURE_ENABLE);
1410 	}
1411 	chdma->lastaddr = p->dmamap->dm_segs[0].ds_addr + n;
1412 
1413 	return (0);
1414 }
1415