xref: /openbsd/sys/arch/sparc64/dev/ce4231.c (revision 404b540a)
1 /*	$OpenBSD: ce4231.c,v 1.22 2008/04/21 00:32:42 jakemsr 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 #include <dev/auconv.h>
55 
56 #include <sparc64/dev/ebusreg.h>
57 #include <sparc64/dev/ebusvar.h>
58 #include <sparc64/dev/ce4231var.h>
59 
60 #include <dev/ic/ad1848reg.h>
61 #include <dev/ic/cs4231reg.h>
62 
63 #define	CSAUDIO_DAC_LVL		0
64 #define	CSAUDIO_LINE_IN_LVL	1
65 #define	CSAUDIO_MIC_LVL		2
66 #define	CSAUDIO_CD_LVL		3
67 #define	CSAUDIO_MONITOR_LVL	4
68 #define	CSAUDIO_OUTPUT_LVL	5
69 #define	CSAUDIO_LINE_IN_MUTE	6
70 #define	CSAUDIO_DAC_MUTE	7
71 #define	CSAUDIO_CD_MUTE		8
72 #define	CSAUDIO_MIC_MUTE	9
73 #define	CSAUDIO_MONITOR_MUTE	10
74 #define	CSAUDIO_OUTPUT_MUTE	11
75 #define	CSAUDIO_REC_LVL		12
76 #define	CSAUDIO_RECORD_SOURCE	13
77 #define	CSAUDIO_OUTPUT		14
78 #define	CSAUDIO_INPUT_CLASS	15
79 #define	CSAUDIO_OUTPUT_CLASS	16
80 #define	CSAUDIO_RECORD_CLASS	17
81 #define	CSAUDIO_MONITOR_CLASS	18
82 
83 #define	CSPORT_AUX2		0
84 #define	CSPORT_AUX1		1
85 #define	CSPORT_DAC		2
86 #define	CSPORT_LINEIN		3
87 #define	CSPORT_MONO		4
88 #define	CSPORT_MONITOR		5
89 #define	CSPORT_SPEAKER		6
90 #define	CSPORT_LINEOUT		7
91 #define	CSPORT_HEADPHONE	8
92 
93 #define MIC_IN_PORT	0
94 #define LINE_IN_PORT	1
95 #define AUX1_IN_PORT	2
96 #define DAC_IN_PORT	3
97 
98 #ifdef AUDIO_DEBUG
99 #define	DPRINTF(x)	printf x
100 #else
101 #define	DPRINTF(x)
102 #endif
103 
104 #define	CS_TIMEOUT	90000
105 
106 #define	CS_PC_LINEMUTE	XCTL0_ENABLE
107 #define	CS_PC_HDPHMUTE	XCTL1_ENABLE
108 #define	CS_AFS_PI	0x10
109 
110 /* Read/write CS4231 direct registers */
111 #define CS_WRITE(sc,r,v)	\
112     bus_space_write_1((sc)->sc_bustag, (sc)->sc_cshandle, (r) << 2, (v))
113 #define	CS_READ(sc,r)		\
114     bus_space_read_1((sc)->sc_bustag, (sc)->sc_cshandle, (r) << 2)
115 
116 /* Read/write EBDMA playback registers */
117 #define	P_WRITE(sc,r,v)		\
118     bus_space_write_4((sc)->sc_bustag, (sc)->sc_pdmahandle, (r), (v))
119 #define	P_READ(sc,r)		\
120     bus_space_read_4((sc)->sc_bustag, (sc)->sc_pdmahandle, (r))
121 
122 /* Read/write EBDMA capture registers */
123 #define	C_WRITE(sc,r,v)		\
124     bus_space_write_4((sc)->sc_bustag, (sc)->sc_cdmahandle, (r), (v))
125 #define	C_READ(sc,r)		\
126     bus_space_read_4((sc)->sc_bustag, (sc)->sc_cdmahandle, (r))
127 
128 int	ce4231_match(struct device *, void *, void *);
129 void	ce4231_attach(struct device *, struct device *, void *);
130 int	ce4231_cintr(void *);
131 int	ce4231_pintr(void *);
132 
133 int	ce4231_set_speed(struct ce4231_softc *, u_long *);
134 void	ce4231_setup_output(struct ce4231_softc *sc);
135 
136 void		ce4231_write(struct ce4231_softc *, u_int8_t, u_int8_t);
137 u_int8_t	ce4231_read(struct ce4231_softc *, u_int8_t);
138 
139 /* Audio interface */
140 int	ce4231_open(void *, int);
141 void	ce4231_close(void *);
142 int	ce4231_query_encoding(void *, struct audio_encoding *);
143 int	ce4231_set_params(void *, int, int, struct audio_params *,
144     struct audio_params *);
145 int	ce4231_round_blocksize(void *, int);
146 int	ce4231_commit_settings(void *);
147 int	ce4231_halt_output(void *);
148 int	ce4231_halt_input(void *);
149 int	ce4231_getdev(void *, struct audio_device *);
150 int	ce4231_set_port(void *, mixer_ctrl_t *);
151 int	ce4231_get_port(void *, mixer_ctrl_t *);
152 int	ce4231_query_devinfo(void *addr, mixer_devinfo_t *);
153 void *	ce4231_alloc(void *, int, size_t, int, int);
154 void	ce4231_free(void *, void *, int);
155 int	ce4231_get_props(void *);
156 int	ce4231_trigger_output(void *, void *, void *, int,
157     void (*intr)(void *), void *arg, struct audio_params *);
158 int	ce4231_trigger_input(void *, void *, void *, int,
159     void (*intr)(void *), void *arg, struct audio_params *);
160 
161 struct audio_hw_if ce4231_sa_hw_if = {
162 	ce4231_open,
163 	ce4231_close,
164 	0,
165 	ce4231_query_encoding,
166 	ce4231_set_params,
167 	ce4231_round_blocksize,
168 	ce4231_commit_settings,
169 	0,
170 	0,
171 	0,
172 	0,
173 	ce4231_halt_output,
174 	ce4231_halt_input,
175 	0,
176 	ce4231_getdev,
177 	0,
178 	ce4231_set_port,
179 	ce4231_get_port,
180 	ce4231_query_devinfo,
181 	ce4231_alloc,
182 	ce4231_free,
183 	0,
184 	0,
185 	ce4231_get_props,
186 	ce4231_trigger_output,
187 	ce4231_trigger_input,
188 	0
189 };
190 
191 struct cfattach audioce_ca = {
192 	sizeof (struct ce4231_softc), ce4231_match, ce4231_attach
193 };
194 
195 struct cfdriver audioce_cd = {
196 	NULL, "audioce", DV_DULL
197 };
198 
199 struct audio_device ce4231_device = {
200 	"SUNW,CS4231",
201 	"b",
202 	"onboard1",
203 };
204 
205 int
206 ce4231_match(parent, vcf, aux)
207 	struct device *parent;
208 	void *vcf, *aux;
209 {
210 	struct ebus_attach_args *ea = aux;
211 
212 	if (!strcmp("SUNW,CS4231", ea->ea_name) ||
213 	    !strcmp("audio", ea->ea_name))
214 		return (1);
215 	return (0);
216 }
217 
218 void
219 ce4231_attach(parent, self, aux)
220 	struct device *parent, *self;
221 	void *aux;
222 {
223 	struct ebus_attach_args *ea = aux;
224 	struct ce4231_softc *sc = (struct ce4231_softc *)self;
225 	int node;
226 
227 	node = ea->ea_node;
228 
229 	sc->sc_last_format = 0xffffffff;
230 
231 	/* Pass on the bus tags */
232 	sc->sc_bustag = ea->ea_memtag;
233 	sc->sc_dmatag = ea->ea_dmatag;
234 
235 	/* Make sure things are sane. */
236 	if (ea->ea_nintrs != 2) {
237 		printf(": expected 2 interrupts, got %d\n", ea->ea_nintrs);
238 		return;
239 	}
240 	if (ea->ea_nregs != 4) {
241 		printf(": expected 4 register set, got %d\n",
242 		    ea->ea_nregs);
243 		return;
244 	}
245 
246 	sc->sc_cih = bus_intr_establish(sc->sc_bustag, ea->ea_intrs[0],
247 	    IPL_AUDIO, 0, ce4231_cintr, sc, self->dv_xname);
248 	if (sc->sc_cih == NULL) {
249 		printf(": couldn't establish capture interrupt\n");
250 		return;
251 	}
252 	sc->sc_pih = bus_intr_establish(sc->sc_bustag, ea->ea_intrs[1],
253 	    IPL_AUDIO, 0, ce4231_pintr, sc, self->dv_xname);
254 	if (sc->sc_pih == NULL) {
255 		printf(": couldn't establish play interrupt1\n");
256 		return;
257 	}
258 
259 	/* XXX what if prom has already mapped?! */
260 
261 	if (ebus_bus_map(sc->sc_bustag, 0,
262 	    EBUS_PADDR_FROM_REG(&ea->ea_regs[0]), ea->ea_regs[0].size,
263 	    BUS_SPACE_MAP_LINEAR, 0, &sc->sc_cshandle) != 0) {
264 		printf(": couldn't map cs4231 registers\n");
265 		return;
266 	}
267 
268 	if (ebus_bus_map(sc->sc_bustag, 0,
269 	    EBUS_PADDR_FROM_REG(&ea->ea_regs[1]), ea->ea_regs[1].size,
270 	    BUS_SPACE_MAP_LINEAR, 0, &sc->sc_pdmahandle) != 0) {
271 		printf(": couldn't map dma1 registers\n");
272 		return;
273 	}
274 
275 	if (ebus_bus_map(sc->sc_bustag, 0,
276 	    EBUS_PADDR_FROM_REG(&ea->ea_regs[2]), ea->ea_regs[2].size,
277 	    BUS_SPACE_MAP_LINEAR, 0, &sc->sc_cdmahandle) != 0) {
278 		printf(": couldn't map dma2 registers\n");
279 		return;
280 	}
281 
282 	if (ebus_bus_map(sc->sc_bustag, 0,
283 	    EBUS_PADDR_FROM_REG(&ea->ea_regs[3]), ea->ea_regs[3].size,
284 	    BUS_SPACE_MAP_LINEAR, 0, &sc->sc_auxhandle) != 0) {
285 		printf(": couldn't map aux registers\n");
286 		return;
287 	}
288 
289 	printf(": nvaddrs %d\n", ea->ea_nvaddrs);
290 
291 	audio_attach_mi(&ce4231_sa_hw_if, sc, &sc->sc_dev);
292 
293 	/* Default to speaker, unmuted, reasonable volume */
294 	sc->sc_out_port = CSPORT_SPEAKER;
295 	sc->sc_mute[CSPORT_SPEAKER] = 1;
296 	sc->sc_mute[CSPORT_MONITOR] = 1;
297 	sc->sc_volume[CSPORT_SPEAKER].left = 192;
298 	sc->sc_volume[CSPORT_SPEAKER].right = 192;
299 
300 	/* XXX get real burst... */
301 	sc->sc_burst = EBDCSR_BURST_8;
302 }
303 
304 /*
305  * Write to one of the indexed registers of cs4231.
306  */
307 void
308 ce4231_write(sc, r, v)
309 	struct ce4231_softc *sc;
310 	u_int8_t r, v;
311 {
312 	CS_WRITE(sc, AD1848_IADDR, r);
313 	CS_WRITE(sc, AD1848_IDATA, v);
314 }
315 
316 /*
317  * Read from one of the indexed registers of cs4231.
318  */
319 u_int8_t
320 ce4231_read(sc, r)
321 	struct ce4231_softc *sc;
322 	u_int8_t r;
323 {
324 	CS_WRITE(sc, AD1848_IADDR, r);
325 	return (CS_READ(sc, AD1848_IDATA));
326 }
327 
328 int
329 ce4231_set_speed(sc, argp)
330 	struct ce4231_softc *sc;
331 	u_long *argp;
332 
333 {
334 	/*
335 	 * The available speeds are in the following table. Keep the speeds in
336 	 * the increasing order.
337 	 */
338 	typedef struct {
339 		int speed;
340 		u_char bits;
341 	} speed_struct;
342 	u_long arg = *argp;
343 
344 	static speed_struct speed_table[] = {
345 		{5510,	(0 << 1) | CLOCK_XTAL2},
346 		{5510,	(0 << 1) | CLOCK_XTAL2},
347 		{6620,	(7 << 1) | CLOCK_XTAL2},
348 		{8000,	(0 << 1) | CLOCK_XTAL1},
349 		{9600,	(7 << 1) | CLOCK_XTAL1},
350 		{11025,	(1 << 1) | CLOCK_XTAL2},
351 		{16000,	(1 << 1) | CLOCK_XTAL1},
352 		{18900,	(2 << 1) | CLOCK_XTAL2},
353 		{22050,	(3 << 1) | CLOCK_XTAL2},
354 		{27420,	(2 << 1) | CLOCK_XTAL1},
355 		{32000,	(3 << 1) | CLOCK_XTAL1},
356 		{33075,	(6 << 1) | CLOCK_XTAL2},
357 		{33075,	(4 << 1) | CLOCK_XTAL2},
358 		{44100,	(5 << 1) | CLOCK_XTAL2},
359 		{48000,	(6 << 1) | CLOCK_XTAL1},
360 	};
361 
362 	int i, n, selected = -1;
363 
364 	n = sizeof(speed_table) / sizeof(speed_struct);
365 
366 	if (arg < speed_table[0].speed)
367 		selected = 0;
368 	if (arg > speed_table[n - 1].speed)
369 		selected = n - 1;
370 
371 	for (i = 1; selected == -1 && i < n; i++) {
372 		if (speed_table[i].speed == arg)
373 			selected = i;
374 		else if (speed_table[i].speed > arg) {
375 			int diff1, diff2;
376 
377 			diff1 = arg - speed_table[i - 1].speed;
378 			diff2 = speed_table[i].speed - arg;
379 			if (diff1 < diff2)
380 				selected = i - 1;
381 			else
382 				selected = i;
383 		}
384 	}
385 
386 	if (selected == -1)
387 		selected = 3;
388 
389 	sc->sc_speed_bits = speed_table[selected].bits;
390 	sc->sc_need_commit = 1;
391 	*argp = speed_table[selected].speed;
392 
393 	return (0);
394 }
395 
396 /*
397  * Audio interface functions
398  */
399 int
400 ce4231_open(addr, flags)
401 	void *addr;
402 	int flags;
403 {
404 	struct ce4231_softc *sc = addr;
405 	int tries;
406 
407 	if (sc->sc_open)
408 		return (EBUSY);
409 	sc->sc_open = 1;
410 	sc->sc_locked = 0;
411 	sc->sc_rintr = 0;
412 	sc->sc_rarg = 0;
413 	sc->sc_pintr = 0;
414 	sc->sc_parg = 0;
415 
416 	P_WRITE(sc, EBDMA_DCSR, EBDCSR_RESET);
417 	C_WRITE(sc, EBDMA_DCSR, EBDCSR_RESET);
418 	P_WRITE(sc, EBDMA_DCSR, sc->sc_burst);
419 	C_WRITE(sc, EBDMA_DCSR, sc->sc_burst);
420 
421 	DELAY(20);
422 
423 	for (tries = CS_TIMEOUT;
424 	     tries && CS_READ(sc, AD1848_IADDR) == SP_IN_INIT; tries--)
425 		DELAY(10);
426 	if (tries == 0)
427 		printf("%s: timeout waiting for reset\n", sc->sc_dev.dv_xname);
428 
429 	/* Turn on cs4231 mode */
430 	ce4231_write(sc, SP_MISC_INFO,
431 	    ce4231_read(sc, SP_MISC_INFO) | MODE2);
432 
433 	ce4231_setup_output(sc);
434 
435 	ce4231_write(sc, SP_PIN_CONTROL,
436 	    ce4231_read(sc, SP_PIN_CONTROL) | INTERRUPT_ENABLE);
437 
438 	return (0);
439 }
440 
441 void
442 ce4231_setup_output(sc)
443 	struct ce4231_softc *sc;
444 {
445 	u_int8_t pc, mi, rm, lm;
446 
447 	pc = ce4231_read(sc, SP_PIN_CONTROL) | CS_PC_HDPHMUTE | CS_PC_LINEMUTE;
448 
449 	mi = ce4231_read(sc, CS_MONO_IO_CONTROL) | MONO_OUTPUT_MUTE;
450 
451 	lm = ce4231_read(sc, SP_LEFT_OUTPUT_CONTROL);
452 	lm &= ~OUTPUT_ATTEN_BITS;
453 	lm |= ((~(sc->sc_volume[CSPORT_SPEAKER].left >> 2)) &
454 	    OUTPUT_ATTEN_BITS) | OUTPUT_MUTE;
455 
456 	rm = ce4231_read(sc, SP_RIGHT_OUTPUT_CONTROL);
457 	rm &= ~OUTPUT_ATTEN_BITS;
458 	rm |= ((~(sc->sc_volume[CSPORT_SPEAKER].right >> 2)) &
459 	    OUTPUT_ATTEN_BITS) | OUTPUT_MUTE;
460 
461 	if (sc->sc_mute[CSPORT_MONITOR]) {
462 		lm &= ~OUTPUT_MUTE;
463 		rm &= ~OUTPUT_MUTE;
464 	}
465 
466 	switch (sc->sc_out_port) {
467 	case CSPORT_HEADPHONE:
468 		if (sc->sc_mute[CSPORT_SPEAKER])
469 			pc &= ~CS_PC_HDPHMUTE;
470 		break;
471 	case CSPORT_SPEAKER:
472 		if (sc->sc_mute[CSPORT_SPEAKER])
473 			mi &= ~MONO_OUTPUT_MUTE;
474 		break;
475 	case CSPORT_LINEOUT:
476 		if (sc->sc_mute[CSPORT_SPEAKER])
477 			pc &= ~CS_PC_LINEMUTE;
478 		break;
479 	}
480 
481 	ce4231_write(sc, SP_LEFT_OUTPUT_CONTROL, lm);
482 	ce4231_write(sc, SP_RIGHT_OUTPUT_CONTROL, rm);
483 	ce4231_write(sc, SP_PIN_CONTROL, pc);
484 	ce4231_write(sc, CS_MONO_IO_CONTROL, mi);
485 }
486 
487 void
488 ce4231_close(addr)
489 	void *addr;
490 {
491 	struct ce4231_softc *sc = addr;
492 
493 	ce4231_halt_input(sc);
494 	ce4231_halt_output(sc);
495 	ce4231_write(sc, SP_PIN_CONTROL,
496 	    ce4231_read(sc, SP_PIN_CONTROL) & (~INTERRUPT_ENABLE));
497 	sc->sc_open = 0;
498 }
499 
500 int
501 ce4231_query_encoding(addr, fp)
502 	void *addr;
503 	struct audio_encoding *fp;
504 {
505 	int err = 0;
506 
507 	switch (fp->index) {
508 	case 0:
509 		strlcpy(fp->name, AudioEmulaw, sizeof fp->name);
510 		fp->encoding = AUDIO_ENCODING_ULAW;
511 		fp->precision = 8;
512 		fp->flags = 0;
513 		break;
514 	case 1:
515 		strlcpy(fp->name, AudioEalaw, sizeof fp->name);
516 		fp->encoding = AUDIO_ENCODING_ALAW;
517 		fp->precision = 8;
518 		fp->flags = 0;
519 		break;
520 	case 2:
521 		strlcpy(fp->name, AudioEslinear_le, sizeof fp->name);
522 		fp->encoding = AUDIO_ENCODING_SLINEAR_LE;
523 		fp->precision = 16;
524 		fp->flags = 0;
525 		break;
526 	case 3:
527 		strlcpy(fp->name, AudioEulinear, sizeof fp->name);
528 		fp->encoding = AUDIO_ENCODING_ULINEAR;
529 		fp->precision = 8;
530 		fp->flags = 0;
531 		break;
532 	case 4:
533 		strlcpy(fp->name, AudioEslinear_be, sizeof fp->name);
534 		fp->encoding = AUDIO_ENCODING_SLINEAR_BE;
535 		fp->precision = 16;
536 		fp->flags = 0;
537 		break;
538 	case 5:
539 		strlcpy(fp->name, AudioEslinear, sizeof fp->name);
540 		fp->encoding = AUDIO_ENCODING_SLINEAR;
541 		fp->precision = 8;
542 		fp->flags = AUDIO_ENCODINGFLAG_EMULATED;
543 		break;
544 	case 6:
545 		strlcpy(fp->name, AudioEulinear_le, sizeof fp->name);
546 		fp->encoding = AUDIO_ENCODING_ULINEAR_LE;
547 		fp->precision = 16;
548 		fp->flags = AUDIO_ENCODINGFLAG_EMULATED;
549 		break;
550 	case 7:
551 		strlcpy(fp->name, AudioEulinear_be, sizeof fp->name);
552 		fp->encoding = AUDIO_ENCODING_ULINEAR_BE;
553 		fp->precision = 16;
554 		fp->flags = AUDIO_ENCODINGFLAG_EMULATED;
555 		break;
556 	case 8:
557 		strlcpy(fp->name, AudioEadpcm, sizeof fp->name);
558 		fp->encoding = AUDIO_ENCODING_ADPCM;
559 		fp->precision = 8;
560 		fp->flags = 0;
561 		break;
562 	default:
563 		err = EINVAL;
564 	}
565 	return (err);
566 }
567 
568 int
569 ce4231_set_params(addr, setmode, usemode, p, r)
570 	void *addr;
571 	int setmode, usemode;
572 	struct audio_params *p, *r;
573 {
574 	struct ce4231_softc *sc = (struct ce4231_softc *)addr;
575 	int err, bits, enc = p->encoding;
576 	void (*pswcode)(void *, u_char *, int cnt) = NULL;
577 	void (*rswcode)(void *, u_char *, int cnt) = NULL;
578 
579 	switch (enc) {
580 	case AUDIO_ENCODING_ULAW:
581 		if (p->precision != 8)
582 			return (EINVAL);
583 		bits = FMT_ULAW >> 5;
584 		break;
585 	case AUDIO_ENCODING_ALAW:
586 		if (p->precision != 8)
587 			return (EINVAL);
588 		bits = FMT_ALAW >> 5;
589 		break;
590 	case AUDIO_ENCODING_SLINEAR_LE:
591 		if (p->precision == 8) {
592 			bits = FMT_PCM8 >> 5;
593 			pswcode = rswcode = change_sign8;
594 		} else if (p->precision == 16)
595 			bits = FMT_TWOS_COMP >> 5;
596 		else
597 			return (EINVAL);
598 		break;
599 	case AUDIO_ENCODING_ULINEAR:
600 		if (p->precision != 8)
601 			return (EINVAL);
602 		bits = FMT_PCM8 >> 5;
603 		break;
604 	case AUDIO_ENCODING_SLINEAR_BE:
605 		if (p->precision == 8) {
606 			bits = FMT_PCM8 >> 5;
607 			pswcode = rswcode = change_sign8;
608 		} else if (p->precision == 16)
609 			bits = FMT_TWOS_COMP_BE >> 5;
610 		else
611 			return (EINVAL);
612 		break;
613 	case AUDIO_ENCODING_SLINEAR:
614 		if (p->precision != 8)
615 			return (EINVAL);
616 		bits = FMT_PCM8 >> 5;
617 		pswcode = rswcode = change_sign8;
618 		break;
619 	case AUDIO_ENCODING_ULINEAR_LE:
620 		if (p->precision == 8)
621 			bits = FMT_PCM8 >> 5;
622 		else if (p->precision == 16) {
623 			bits = FMT_TWOS_COMP >> 5;
624 			pswcode = rswcode = change_sign16_le;
625 		} else
626 			return (EINVAL);
627 		break;
628 	case AUDIO_ENCODING_ULINEAR_BE:
629 		if (p->precision == 8)
630 			bits = FMT_PCM8 >> 5;
631 		else if (p->precision == 16) {
632 			bits = FMT_TWOS_COMP_BE >> 5;
633 			pswcode = rswcode = change_sign16_be;
634 		} else
635 			return (EINVAL);
636 		break;
637 	case AUDIO_ENCODING_ADPCM:
638 		if (p->precision != 8)
639 			return (EINVAL);
640 		bits = FMT_ADPCM >> 5;
641 		break;
642 	default:
643 		return (EINVAL);
644 	}
645 
646 	if (p->channels != 1 && p->channels != 2)
647 		return (EINVAL);
648 
649 	err = ce4231_set_speed(sc, &p->sample_rate);
650 	if (err)
651 		return (err);
652 
653 	p->sw_code = pswcode;
654 	r->sw_code = rswcode;
655 
656 	sc->sc_format_bits = bits;
657 	sc->sc_channels = p->channels;
658 	sc->sc_precision = p->precision;
659 	sc->sc_need_commit = 1;
660 	return (0);
661 }
662 
663 int
664 ce4231_round_blocksize(addr, blk)
665 	void *addr;
666 	int blk;
667 {
668 	return ((blk + 3) & (-4));
669 }
670 
671 int
672 ce4231_commit_settings(addr)
673 	void *addr;
674 {
675 	struct ce4231_softc *sc = (struct ce4231_softc *)addr;
676 	int s, tries;
677 	u_int8_t r, fs;
678 
679 	if (sc->sc_need_commit == 0)
680 		return (0);
681 
682 	fs = sc->sc_speed_bits | (sc->sc_format_bits << 5);
683 	if (sc->sc_channels == 2)
684 		fs |= FMT_STEREO;
685 
686 	if (sc->sc_last_format == fs) {
687 		sc->sc_need_commit = 0;
688 		return (0);
689 	}
690 
691 	s = splaudio();
692 
693 	r = ce4231_read(sc, SP_INTERFACE_CONFIG) | AUTO_CAL_ENABLE;
694 	CS_WRITE(sc, AD1848_IADDR, MODE_CHANGE_ENABLE);
695 	CS_WRITE(sc, AD1848_IADDR, MODE_CHANGE_ENABLE | SP_INTERFACE_CONFIG);
696 	CS_WRITE(sc, AD1848_IDATA, r);
697 
698 	CS_WRITE(sc, AD1848_IADDR, MODE_CHANGE_ENABLE | SP_CLOCK_DATA_FORMAT);
699 	CS_WRITE(sc, AD1848_IDATA, fs);
700 	CS_READ(sc, AD1848_IDATA);
701 	CS_READ(sc, AD1848_IDATA);
702 	tries = CS_TIMEOUT;
703 	for (tries = CS_TIMEOUT;
704 	     tries && CS_READ(sc, AD1848_IADDR) == SP_IN_INIT; tries--)
705 		DELAY(10);
706 	if (tries == 0)
707 		printf("%s: timeout committing fspb\n", sc->sc_dev.dv_xname);
708 
709 	CS_WRITE(sc, AD1848_IADDR, MODE_CHANGE_ENABLE | CS_REC_FORMAT);
710 	CS_WRITE(sc, AD1848_IDATA, fs);
711 	CS_READ(sc, AD1848_IDATA);
712 	CS_READ(sc, AD1848_IDATA);
713 	for (tries = CS_TIMEOUT;
714 	     tries && CS_READ(sc, AD1848_IADDR) == SP_IN_INIT; tries--)
715 		DELAY(10);
716 	if (tries == 0)
717 		printf("%s: timeout committing cdf\n", sc->sc_dev.dv_xname);
718 
719 	CS_WRITE(sc, AD1848_IADDR, 0);
720 	for (tries = CS_TIMEOUT;
721 	     tries && CS_READ(sc, AD1848_IADDR) == SP_IN_INIT; tries--)
722 		DELAY(10);
723 	if (tries == 0)
724 		printf("%s: timeout waiting for !mce\n", sc->sc_dev.dv_xname);
725 
726 	CS_WRITE(sc, AD1848_IADDR, SP_TEST_AND_INIT);
727 	for (tries = CS_TIMEOUT;
728 	     tries && CS_READ(sc, AD1848_IDATA) & AUTO_CAL_IN_PROG; tries--)
729 		DELAY(10);
730 	if (tries == 0)
731 		printf("%s: timeout waiting for autocalibration\n",
732 		    sc->sc_dev.dv_xname);
733 
734 	splx(s);
735 
736 	sc->sc_need_commit = 0;
737 	return (0);
738 }
739 
740 int
741 ce4231_halt_output(addr)
742 	void *addr;
743 {
744 	struct ce4231_softc *sc = (struct ce4231_softc *)addr;
745 
746 	P_WRITE(sc, EBDMA_DCSR,
747 	    P_READ(sc, EBDMA_DCSR) & ~EBDCSR_DMAEN);
748 	ce4231_write(sc, SP_INTERFACE_CONFIG,
749 	    ce4231_read(sc, SP_INTERFACE_CONFIG) & (~PLAYBACK_ENABLE));
750 	sc->sc_locked = 0;
751 	return (0);
752 }
753 
754 int
755 ce4231_halt_input(addr)
756 	void *addr;
757 {
758 	struct ce4231_softc *sc = (struct ce4231_softc *)addr;
759 
760 	C_WRITE(sc, EBDMA_DCSR,
761 	    C_READ(sc, EBDMA_DCSR) & ~EBDCSR_DMAEN);
762 	ce4231_write(sc, SP_INTERFACE_CONFIG,
763 	    ce4231_read(sc, SP_INTERFACE_CONFIG) & (~CAPTURE_ENABLE));
764 	sc->sc_locked = 0;
765 	return (0);
766 }
767 
768 int
769 ce4231_getdev(addr, retp)
770 	void *addr;
771 	struct audio_device *retp;
772 {
773 	*retp = ce4231_device;
774 	return (0);
775 }
776 
777 int
778 ce4231_set_port(addr, cp)
779 	void *addr;
780 	mixer_ctrl_t *cp;
781 {
782 	struct ce4231_softc *sc = (struct ce4231_softc *)addr;
783 	int error = EINVAL;
784 
785 	DPRINTF(("ce4231_set_port: port=%d type=%d\n", cp->dev, cp->type));
786 
787 	switch (cp->dev) {
788 	case CSAUDIO_DAC_LVL:
789 		if (cp->type != AUDIO_MIXER_VALUE)
790 			break;
791 		if (cp->un.value.num_channels == 1)
792 			ce4231_write(sc, SP_LEFT_AUX1_CONTROL,
793 			    cp->un.value.level[AUDIO_MIXER_LEVEL_MONO] &
794 			    LINE_INPUT_ATTEN_BITS);
795 		else if (cp->un.value.num_channels == 2) {
796 			ce4231_write(sc, SP_LEFT_AUX1_CONTROL,
797 			    cp->un.value.level[AUDIO_MIXER_LEVEL_LEFT] &
798 			    LINE_INPUT_ATTEN_BITS);
799 			ce4231_write(sc, SP_RIGHT_AUX1_CONTROL,
800 			    cp->un.value.level[AUDIO_MIXER_LEVEL_RIGHT] &
801 			    LINE_INPUT_ATTEN_BITS);
802 		} else
803 			break;
804 		error = 0;
805 		break;
806 	case CSAUDIO_LINE_IN_LVL:
807 		if (cp->type != AUDIO_MIXER_VALUE)
808 			break;
809 		if (cp->un.value.num_channels == 1)
810 			ce4231_write(sc, CS_LEFT_LINE_CONTROL,
811 			    cp->un.value.level[AUDIO_MIXER_LEVEL_MONO] &
812 			    AUX_INPUT_ATTEN_BITS);
813 		else if (cp->un.value.num_channels == 2) {
814 			ce4231_write(sc, CS_LEFT_LINE_CONTROL,
815 			    cp->un.value.level[AUDIO_MIXER_LEVEL_LEFT] &
816 			    AUX_INPUT_ATTEN_BITS);
817 			ce4231_write(sc, CS_RIGHT_LINE_CONTROL,
818 			    cp->un.value.level[AUDIO_MIXER_LEVEL_RIGHT] &
819 			    AUX_INPUT_ATTEN_BITS);
820 		} else
821 			break;
822 		error = 0;
823 		break;
824 	case CSAUDIO_MIC_LVL:
825 		if (cp->type != AUDIO_MIXER_VALUE)
826 			break;
827 		if (cp->un.value.num_channels == 1) {
828 #if 0
829 			ce4231_write(sc, CS_MONO_IO_CONTROL,
830 			    cp->un.value.level[AUDIO_MIXER_LEVEL_MONO] &
831 			    MONO_INPUT_ATTEN_BITS);
832 #endif
833 		} else
834 			break;
835 		error = 0;
836 		break;
837 	case CSAUDIO_CD_LVL:
838 		if (cp->type != AUDIO_MIXER_VALUE)
839 			break;
840 		if (cp->un.value.num_channels == 1) {
841 			ce4231_write(sc, SP_LEFT_AUX2_CONTROL,
842 			    cp->un.value.level[AUDIO_MIXER_LEVEL_MONO] &
843 			    LINE_INPUT_ATTEN_BITS);
844 		} else if (cp->un.value.num_channels == 2) {
845 			ce4231_write(sc, SP_LEFT_AUX2_CONTROL,
846 			    cp->un.value.level[AUDIO_MIXER_LEVEL_LEFT] &
847 			    LINE_INPUT_ATTEN_BITS);
848 			ce4231_write(sc, SP_RIGHT_AUX2_CONTROL,
849 			    cp->un.value.level[AUDIO_MIXER_LEVEL_RIGHT] &
850 			    LINE_INPUT_ATTEN_BITS);
851 		} else
852 			break;
853 		error = 0;
854 		break;
855 	case CSAUDIO_MONITOR_LVL:
856 		if (cp->type != AUDIO_MIXER_VALUE)
857 			break;
858 		if (cp->un.value.num_channels == 1)
859 			ce4231_write(sc, SP_DIGITAL_MIX,
860 			    cp->un.value.level[AUDIO_MIXER_LEVEL_MONO] << 2);
861 		else
862 			break;
863 		error = 0;
864 		break;
865 	case CSAUDIO_OUTPUT_LVL:
866 		if (cp->type != AUDIO_MIXER_VALUE)
867 			break;
868 		if (cp->un.value.num_channels == 1) {
869 			sc->sc_volume[CSPORT_SPEAKER].left =
870 			    cp->un.value.level[AUDIO_MIXER_LEVEL_MONO];
871 			sc->sc_volume[CSPORT_SPEAKER].right =
872 			    cp->un.value.level[AUDIO_MIXER_LEVEL_MONO];
873 		}
874 		else if (cp->un.value.num_channels == 2) {
875 			sc->sc_volume[CSPORT_SPEAKER].left =
876 			    cp->un.value.level[AUDIO_MIXER_LEVEL_LEFT];
877 			sc->sc_volume[CSPORT_SPEAKER].right =
878 			    cp->un.value.level[AUDIO_MIXER_LEVEL_RIGHT];
879 		}
880 		else
881 			break;
882 
883 		ce4231_setup_output(sc);
884 		error = 0;
885 		break;
886 	case CSAUDIO_OUTPUT:
887 		if (cp->type != AUDIO_MIXER_ENUM)
888 			break;
889 		if (cp->un.ord != CSPORT_LINEOUT &&
890 		    cp->un.ord != CSPORT_SPEAKER &&
891 		    cp->un.ord != CSPORT_HEADPHONE)
892 			return (EINVAL);
893 		sc->sc_out_port = cp->un.ord;
894 		ce4231_setup_output(sc);
895 		error = 0;
896 		break;
897 	case CSAUDIO_LINE_IN_MUTE:
898 		if (cp->type != AUDIO_MIXER_ENUM)
899 			break;
900 		sc->sc_mute[CSPORT_LINEIN] = cp->un.ord ? 1 : 0;
901 		error = 0;
902 		break;
903 	case CSAUDIO_DAC_MUTE:
904 		if (cp->type != AUDIO_MIXER_ENUM)
905 			break;
906 		sc->sc_mute[CSPORT_AUX1] = cp->un.ord ? 1 : 0;
907 		error = 0;
908 		break;
909 	case CSAUDIO_CD_MUTE:
910 		if (cp->type != AUDIO_MIXER_ENUM)
911 			break;
912 		sc->sc_mute[CSPORT_AUX2] = cp->un.ord ? 1 : 0;
913 		error = 0;
914 		break;
915 	case CSAUDIO_MIC_MUTE:
916 		if (cp->type != AUDIO_MIXER_ENUM)
917 			break;
918 		sc->sc_mute[CSPORT_MONO] = cp->un.ord ? 1 : 0;
919 		error = 0;
920 		break;
921 	case CSAUDIO_MONITOR_MUTE:
922 		if (cp->type != AUDIO_MIXER_ENUM)
923 			break;
924 		sc->sc_mute[CSPORT_MONITOR] = cp->un.ord ? 1 : 0;
925 		error = 0;
926 		break;
927 	case CSAUDIO_OUTPUT_MUTE:
928 		if (cp->type != AUDIO_MIXER_ENUM)
929 			break;
930 		sc->sc_mute[CSPORT_SPEAKER] = cp->un.ord ? 1 : 0;
931 		ce4231_setup_output(sc);
932 		error = 0;
933 		break;
934 	case CSAUDIO_REC_LVL:
935 		if (cp->type != AUDIO_MIXER_VALUE)
936 			break;
937 		break;
938 	case CSAUDIO_RECORD_SOURCE:
939 		if (cp->type != AUDIO_MIXER_ENUM)
940 			break;
941 		break;
942 	}
943 
944 	return (error);
945 }
946 
947 int
948 ce4231_get_port(addr, cp)
949 	void *addr;
950 	mixer_ctrl_t *cp;
951 {
952 	struct ce4231_softc *sc = (struct ce4231_softc *)addr;
953 	int error = EINVAL;
954 
955 	DPRINTF(("ce4231_get_port: port=%d type=%d\n", cp->dev, cp->type));
956 
957 	switch (cp->dev) {
958 	case CSAUDIO_DAC_LVL:
959 		if (cp->type != AUDIO_MIXER_VALUE)
960 			break;
961 		if (cp->un.value.num_channels == 1)
962 			cp->un.value.level[AUDIO_MIXER_LEVEL_MONO]=
963 			    ce4231_read(sc, SP_LEFT_AUX1_CONTROL) &
964 			    LINE_INPUT_ATTEN_BITS;
965 		else if (cp->un.value.num_channels == 2) {
966 			cp->un.value.level[AUDIO_MIXER_LEVEL_LEFT] =
967 			    ce4231_read(sc, SP_LEFT_AUX1_CONTROL) &
968 			    LINE_INPUT_ATTEN_BITS;
969 			cp->un.value.level[AUDIO_MIXER_LEVEL_RIGHT] =
970 			    ce4231_read(sc, SP_RIGHT_AUX1_CONTROL) &
971 			    LINE_INPUT_ATTEN_BITS;
972 		} else
973 			break;
974 		error = 0;
975 		break;
976 	case CSAUDIO_LINE_IN_LVL:
977 		if (cp->type != AUDIO_MIXER_VALUE)
978 			break;
979 		if (cp->un.value.num_channels == 1)
980 			cp->un.value.level[AUDIO_MIXER_LEVEL_MONO] =
981 			    ce4231_read(sc, CS_LEFT_LINE_CONTROL) & AUX_INPUT_ATTEN_BITS;
982 		else if (cp->un.value.num_channels == 2) {
983 			cp->un.value.level[AUDIO_MIXER_LEVEL_LEFT] =
984 			    ce4231_read(sc, CS_LEFT_LINE_CONTROL) & AUX_INPUT_ATTEN_BITS;
985 			cp->un.value.level[AUDIO_MIXER_LEVEL_RIGHT] =
986 			    ce4231_read(sc, CS_RIGHT_LINE_CONTROL) & AUX_INPUT_ATTEN_BITS;
987 		} else
988 			break;
989 		error = 0;
990 		break;
991 	case CSAUDIO_MIC_LVL:
992 		if (cp->type != AUDIO_MIXER_VALUE)
993 			break;
994 		if (cp->un.value.num_channels == 1) {
995 #if 0
996 			cp->un.value.level[AUDIO_MIXER_LEVEL_MONO] =
997 			    ce4231_read(sc, CS_MONO_IO_CONTROL) &
998 			    MONO_INPUT_ATTEN_BITS;
999 #endif
1000 		} else
1001 			break;
1002 		error = 0;
1003 		break;
1004 	case CSAUDIO_CD_LVL:
1005 		if (cp->type != AUDIO_MIXER_VALUE)
1006 			break;
1007 		if (cp->un.value.num_channels == 1)
1008 			cp->un.value.level[AUDIO_MIXER_LEVEL_MONO] =
1009 			    ce4231_read(sc, SP_LEFT_AUX2_CONTROL) &
1010 			    LINE_INPUT_ATTEN_BITS;
1011 		else if (cp->un.value.num_channels == 2) {
1012 			cp->un.value.level[AUDIO_MIXER_LEVEL_LEFT] =
1013 			    ce4231_read(sc, SP_LEFT_AUX2_CONTROL) &
1014 			    LINE_INPUT_ATTEN_BITS;
1015 			cp->un.value.level[AUDIO_MIXER_LEVEL_RIGHT] =
1016 			    ce4231_read(sc, SP_RIGHT_AUX2_CONTROL) &
1017 			    LINE_INPUT_ATTEN_BITS;
1018 		}
1019 		else
1020 			break;
1021 		error = 0;
1022 		break;
1023 	case CSAUDIO_MONITOR_LVL:
1024 		if (cp->type != AUDIO_MIXER_VALUE)
1025 			break;
1026 		if (cp->un.value.num_channels != 1)
1027 			break;
1028 		cp->un.value.level[AUDIO_MIXER_LEVEL_MONO] =
1029 		    ce4231_read(sc, SP_DIGITAL_MIX) >> 2;
1030 		error = 0;
1031 		break;
1032 	case CSAUDIO_OUTPUT_LVL:
1033 		if (cp->type != AUDIO_MIXER_VALUE)
1034 			break;
1035 		if (cp->un.value.num_channels == 1)
1036 			cp->un.value.level[AUDIO_MIXER_LEVEL_MONO] =
1037 			    sc->sc_volume[CSPORT_SPEAKER].left;
1038 		else if (cp->un.value.num_channels == 2) {
1039 			cp->un.value.level[AUDIO_MIXER_LEVEL_LEFT] =
1040 			    sc->sc_volume[CSPORT_SPEAKER].left;
1041 			cp->un.value.level[AUDIO_MIXER_LEVEL_RIGHT] =
1042 			    sc->sc_volume[CSPORT_SPEAKER].right;
1043 		}
1044 		else
1045 			break;
1046 		error = 0;
1047 		break;
1048 	case CSAUDIO_LINE_IN_MUTE:
1049 		if (cp->type != AUDIO_MIXER_ENUM)
1050 			break;
1051 		cp->un.ord = sc->sc_mute[CSPORT_LINEIN] ? 1 : 0;
1052 		error = 0;
1053 		break;
1054 	case CSAUDIO_DAC_MUTE:
1055 		if (cp->type != AUDIO_MIXER_ENUM)
1056 			break;
1057 		cp->un.ord = sc->sc_mute[CSPORT_AUX1] ? 1 : 0;
1058 		error = 0;
1059 		break;
1060 	case CSAUDIO_CD_MUTE:
1061 		if (cp->type != AUDIO_MIXER_ENUM)
1062 			break;
1063 		cp->un.ord = sc->sc_mute[CSPORT_AUX2] ? 1 : 0;
1064 		error = 0;
1065 		break;
1066 	case CSAUDIO_MIC_MUTE:
1067 		if (cp->type != AUDIO_MIXER_ENUM)
1068 			break;
1069 		cp->un.ord = sc->sc_mute[CSPORT_MONO] ? 1 : 0;
1070 		error = 0;
1071 		break;
1072 	case CSAUDIO_MONITOR_MUTE:
1073 		if (cp->type != AUDIO_MIXER_ENUM)
1074 			break;
1075 		cp->un.ord = sc->sc_mute[CSPORT_MONITOR] ? 1 : 0;
1076 		error = 0;
1077 		break;
1078 	case CSAUDIO_OUTPUT_MUTE:
1079 		if (cp->type != AUDIO_MIXER_ENUM)
1080 			break;
1081 		cp->un.ord = sc->sc_mute[CSPORT_SPEAKER] ? 1 : 0;
1082 		error = 0;
1083 		break;
1084 	case CSAUDIO_REC_LVL:
1085 		if (cp->type != AUDIO_MIXER_VALUE)
1086 			break;
1087 		if (cp->un.value.num_channels == 1) {
1088 			cp->un.value.level[AUDIO_MIXER_LEVEL_MONO] =
1089 			    AUDIO_MIN_GAIN;
1090 		} else if (cp->un.value.num_channels == 2) {
1091 			cp->un.value.level[AUDIO_MIXER_LEVEL_LEFT] =
1092 			    AUDIO_MIN_GAIN;
1093 			cp->un.value.level[AUDIO_MIXER_LEVEL_RIGHT] =
1094 			    AUDIO_MIN_GAIN;
1095 		} else
1096 			break;
1097 		error = 0;
1098 		break;
1099 	case CSAUDIO_RECORD_SOURCE:
1100 		if (cp->type != AUDIO_MIXER_ENUM)
1101 			break;
1102 		cp->un.ord = MIC_IN_PORT;
1103 		error = 0;
1104 		break;
1105 	case CSAUDIO_OUTPUT:
1106 		if (cp->type != AUDIO_MIXER_ENUM)
1107 			break;
1108 		cp->un.ord = sc->sc_out_port;
1109 		error = 0;
1110 		break;
1111 	}
1112 	return (error);
1113 }
1114 
1115 int
1116 ce4231_query_devinfo(addr, dip)
1117 	void *addr;
1118 	mixer_devinfo_t *dip;
1119 {
1120 	int err = 0;
1121 
1122 	switch (dip->index) {
1123 	case CSAUDIO_MIC_LVL:		/* mono/microphone mixer */
1124 		dip->type = AUDIO_MIXER_VALUE;
1125 		dip->mixer_class = CSAUDIO_INPUT_CLASS;
1126 		dip->prev = AUDIO_MIXER_LAST;
1127 		dip->next = CSAUDIO_MIC_MUTE;
1128 		strlcpy(dip->label.name, AudioNmicrophone, sizeof dip->label.name);
1129 		dip->un.v.num_channels = 1;
1130 		strlcpy(dip->un.v.units.name, AudioNvolume,
1131 		    sizeof dip->un.v.units.name);
1132 		break;
1133 	case CSAUDIO_DAC_LVL:		/* dacout */
1134 		dip->type = AUDIO_MIXER_VALUE;
1135 		dip->mixer_class = CSAUDIO_INPUT_CLASS;
1136 		dip->prev = AUDIO_MIXER_LAST;
1137 		dip->next = CSAUDIO_DAC_MUTE;
1138 		strlcpy(dip->label.name, AudioNdac, sizeof dip->label.name);
1139 		dip->un.v.num_channels = 2;
1140 		strlcpy(dip->un.v.units.name, AudioNvolume,
1141 		    sizeof dip->un.v.units.name);
1142 		break;
1143 	case CSAUDIO_LINE_IN_LVL:	/* line */
1144 		dip->type = AUDIO_MIXER_VALUE;
1145 		dip->mixer_class = CSAUDIO_INPUT_CLASS;
1146 		dip->prev = AUDIO_MIXER_LAST;
1147 		dip->next = CSAUDIO_LINE_IN_MUTE;
1148 		strlcpy(dip->label.name, AudioNline, sizeof dip->label.name);
1149 		dip->un.v.num_channels = 2;
1150 		strlcpy(dip->un.v.units.name, AudioNvolume,
1151 		    sizeof dip->un.v.units.name);
1152 		break;
1153 	case CSAUDIO_CD_LVL:		/* cd */
1154 		dip->type = AUDIO_MIXER_VALUE;
1155 		dip->mixer_class = CSAUDIO_INPUT_CLASS;
1156 		dip->prev = AUDIO_MIXER_LAST;
1157 		dip->next = CSAUDIO_CD_MUTE;
1158 		strlcpy(dip->label.name, AudioNcd, sizeof dip->label.name);
1159 		dip->un.v.num_channels = 2;
1160 		strlcpy(dip->un.v.units.name, AudioNvolume,
1161 		    sizeof dip->un.v.units.name);
1162 		break;
1163 	case CSAUDIO_MONITOR_LVL:	/* monitor level */
1164 		dip->type = AUDIO_MIXER_VALUE;
1165 		dip->mixer_class = CSAUDIO_MONITOR_CLASS;
1166 		dip->prev = AUDIO_MIXER_LAST;
1167 		dip->next = CSAUDIO_MONITOR_MUTE;
1168 		strlcpy(dip->label.name, AudioNmonitor, sizeof dip->label.name);
1169 		dip->un.v.num_channels = 1;
1170 		strlcpy(dip->un.v.units.name, AudioNvolume,
1171 		    sizeof dip->un.v.units.name);
1172 		break;
1173 	case CSAUDIO_OUTPUT_LVL:
1174 		dip->type = AUDIO_MIXER_VALUE;
1175 		dip->mixer_class = CSAUDIO_OUTPUT_CLASS;
1176 		dip->prev = AUDIO_MIXER_LAST;
1177 		dip->next = CSAUDIO_OUTPUT_MUTE;
1178 		strlcpy(dip->label.name, AudioNoutput, sizeof dip->label.name);
1179 		dip->un.v.num_channels = 2;
1180 		strlcpy(dip->un.v.units.name, AudioNvolume,
1181 		    sizeof dip->un.v.units.name);
1182 		break;
1183 	case CSAUDIO_LINE_IN_MUTE:
1184 		dip->type = AUDIO_MIXER_ENUM;
1185 		dip->mixer_class = CSAUDIO_INPUT_CLASS;
1186 		dip->prev = CSAUDIO_LINE_IN_LVL;
1187 		dip->next = AUDIO_MIXER_LAST;
1188 		goto mute;
1189 	case CSAUDIO_DAC_MUTE:
1190 		dip->type = AUDIO_MIXER_ENUM;
1191 		dip->mixer_class = CSAUDIO_INPUT_CLASS;
1192 		dip->prev = CSAUDIO_DAC_LVL;
1193 		dip->next = AUDIO_MIXER_LAST;
1194 		goto mute;
1195 	case CSAUDIO_CD_MUTE:
1196 		dip->type = AUDIO_MIXER_ENUM;
1197 		dip->mixer_class = CSAUDIO_INPUT_CLASS;
1198 		dip->prev = CSAUDIO_CD_LVL;
1199 		dip->next = AUDIO_MIXER_LAST;
1200 		goto mute;
1201 	case CSAUDIO_MIC_MUTE:
1202 		dip->type = AUDIO_MIXER_ENUM;
1203 		dip->mixer_class = CSAUDIO_INPUT_CLASS;
1204 		dip->prev = CSAUDIO_MIC_LVL;
1205 		dip->next = AUDIO_MIXER_LAST;
1206 		goto mute;
1207 	case CSAUDIO_MONITOR_MUTE:
1208 		dip->type = AUDIO_MIXER_ENUM;
1209 		dip->mixer_class = CSAUDIO_OUTPUT_CLASS;
1210 		dip->prev = CSAUDIO_MONITOR_LVL;
1211 		dip->next = AUDIO_MIXER_LAST;
1212 		goto mute;
1213 	case CSAUDIO_OUTPUT_MUTE:
1214 		dip->type = AUDIO_MIXER_ENUM;
1215 		dip->mixer_class = CSAUDIO_OUTPUT_CLASS;
1216 		dip->prev = CSAUDIO_OUTPUT_LVL;
1217 		dip->next = AUDIO_MIXER_LAST;
1218 		goto mute;
1219 
1220 	mute:
1221 		strlcpy(dip->label.name, AudioNmute, sizeof dip->label.name);
1222 		dip->un.e.num_mem = 2;
1223 		strlcpy(dip->un.e.member[0].label.name, AudioNon,
1224 		    sizeof dip->un.e.member[0].label.name);
1225 		dip->un.e.member[0].ord = 0;
1226 		strlcpy(dip->un.e.member[1].label.name, AudioNoff,
1227 		    sizeof dip->un.e.member[1].label.name);
1228 		dip->un.e.member[1].ord = 1;
1229 		break;
1230 	case CSAUDIO_REC_LVL:		/* record level */
1231 		dip->type = AUDIO_MIXER_VALUE;
1232 		dip->mixer_class = CSAUDIO_RECORD_CLASS;
1233 		dip->prev = AUDIO_MIXER_LAST;
1234 		dip->next = CSAUDIO_RECORD_SOURCE;
1235 		strlcpy(dip->label.name, AudioNrecord, sizeof dip->label.name);
1236 		dip->un.v.num_channels = 2;
1237 		strlcpy(dip->un.v.units.name, AudioNvolume,
1238 		    sizeof dip->un.v.units.name);
1239 		break;
1240 	case CSAUDIO_RECORD_SOURCE:
1241 		dip->type = AUDIO_MIXER_ENUM;
1242 		dip->mixer_class = CSAUDIO_RECORD_CLASS;
1243 		dip->prev = CSAUDIO_REC_LVL;
1244 		dip->next = AUDIO_MIXER_LAST;
1245 		strlcpy(dip->label.name, AudioNsource, sizeof dip->label.name);
1246 		dip->un.e.num_mem = 3;
1247 		strlcpy(dip->un.e.member[0].label.name, AudioNcd,
1248 		    sizeof dip->un.e.member[0].label.name);
1249 		dip->un.e.member[0].ord = DAC_IN_PORT;
1250 		strlcpy(dip->un.e.member[1].label.name, AudioNmicrophone,
1251 		    sizeof dip->un.e.member[1].label.name);
1252 		dip->un.e.member[1].ord = MIC_IN_PORT;
1253 		strlcpy(dip->un.e.member[2].label.name, AudioNdac,
1254 		    sizeof dip->un.e.member[2].label.name);
1255 		dip->un.e.member[2].ord = AUX1_IN_PORT;
1256 		strlcpy(dip->un.e.member[3].label.name, AudioNline,
1257 		    sizeof dip->un.e.member[3].label.name);
1258 		dip->un.e.member[3].ord = LINE_IN_PORT;
1259 		break;
1260 	case CSAUDIO_OUTPUT:
1261 		dip->type = AUDIO_MIXER_ENUM;
1262 		dip->mixer_class = CSAUDIO_MONITOR_CLASS;
1263 		dip->prev = dip->next = AUDIO_MIXER_LAST;
1264 		strlcpy(dip->label.name, AudioNoutput, sizeof dip->label.name);
1265 		dip->un.e.num_mem = 3;
1266 		strlcpy(dip->un.e.member[0].label.name, AudioNspeaker,
1267 		    sizeof dip->un.e.member[0].label.name);
1268 		dip->un.e.member[0].ord = CSPORT_SPEAKER;
1269 		strlcpy(dip->un.e.member[1].label.name, AudioNline,
1270 		    sizeof dip->un.e.member[1].label.name);
1271 		dip->un.e.member[1].ord = CSPORT_LINEOUT;
1272 		strlcpy(dip->un.e.member[2].label.name, AudioNheadphone,
1273 		    sizeof dip->un.e.member[2].label.name);
1274 		dip->un.e.member[2].ord = CSPORT_HEADPHONE;
1275 		break;
1276 	case CSAUDIO_INPUT_CLASS:	/* input class descriptor */
1277 		dip->type = AUDIO_MIXER_CLASS;
1278 		dip->mixer_class = CSAUDIO_INPUT_CLASS;
1279 		dip->prev = AUDIO_MIXER_LAST;
1280 		dip->next = AUDIO_MIXER_LAST;
1281 		strlcpy(dip->label.name, AudioCinputs, sizeof dip->label.name);
1282 		break;
1283 	case CSAUDIO_OUTPUT_CLASS:	/* output class descriptor */
1284 		dip->type = AUDIO_MIXER_CLASS;
1285 		dip->mixer_class = CSAUDIO_OUTPUT_CLASS;
1286 		dip->prev = AUDIO_MIXER_LAST;
1287 		dip->next = AUDIO_MIXER_LAST;
1288 		strlcpy(dip->label.name, AudioCoutputs, sizeof dip->label.name);
1289 		break;
1290 	case CSAUDIO_MONITOR_CLASS:	/* monitor class descriptor */
1291 		dip->type = AUDIO_MIXER_CLASS;
1292 		dip->mixer_class = CSAUDIO_MONITOR_CLASS;
1293 		dip->prev = AUDIO_MIXER_LAST;
1294 		dip->next = AUDIO_MIXER_LAST;
1295 		strlcpy(dip->label.name, AudioCmonitor, sizeof dip->label.name);
1296 		break;
1297 	case CSAUDIO_RECORD_CLASS:	/* record class descriptor */
1298 		dip->type = AUDIO_MIXER_CLASS;
1299 		dip->mixer_class = CSAUDIO_RECORD_CLASS;
1300 		dip->prev = AUDIO_MIXER_LAST;
1301 		dip->next = AUDIO_MIXER_LAST;
1302 		strlcpy(dip->label.name, AudioCrecord, sizeof dip->label.name);
1303 		break;
1304 	default:
1305 		err = ENXIO;
1306 	}
1307 
1308 	return (err);
1309 }
1310 
1311 int
1312 ce4231_get_props(addr)
1313 	void *addr;
1314 {
1315 	return (AUDIO_PROP_FULLDUPLEX);
1316 }
1317 
1318 /*
1319  * Hardware interrupt handler
1320  */
1321 int
1322 ce4231_cintr(v)
1323 	void *v;
1324 {
1325 	return (0);
1326 }
1327 
1328 int
1329 ce4231_pintr(v)
1330 	void *v;
1331 {
1332 	struct ce4231_softc *sc = (struct ce4231_softc *)v;
1333 	u_int32_t csr;
1334 	u_int8_t reg, status;
1335 	struct cs_dma *p;
1336 	int r = 0;
1337 
1338 	csr = P_READ(sc, EBDMA_DCSR);
1339 	status = CS_READ(sc, AD1848_STATUS);
1340 	if (status & (INTERRUPT_STATUS | SAMPLE_ERROR)) {
1341 		reg = ce4231_read(sc, CS_IRQ_STATUS);
1342 		if (reg & CS_AFS_PI) {
1343 			ce4231_write(sc, SP_LOWER_BASE_COUNT, 0xff);
1344 			ce4231_write(sc, SP_UPPER_BASE_COUNT, 0xff);
1345 		}
1346 		CS_WRITE(sc, AD1848_STATUS, 0);
1347 	}
1348 
1349 	P_WRITE(sc, EBDMA_DCSR, csr);
1350 
1351 	if (csr & EBDCSR_INT)
1352 		r = 1;
1353 
1354 	if ((csr & EBDCSR_TC) || ((csr & EBDCSR_A_LOADED) == 0)) {
1355 		u_long nextaddr, togo;
1356 
1357 		p = sc->sc_nowplaying;
1358 		togo = sc->sc_playsegsz - sc->sc_playcnt;
1359 		if (togo == 0) {
1360 			nextaddr = (u_int32_t)p->dmamap->dm_segs[0].ds_addr;
1361 			sc->sc_playcnt = togo = sc->sc_blksz;
1362 		} else {
1363 			nextaddr = sc->sc_lastaddr;
1364 			if (togo > sc->sc_blksz)
1365 				togo = sc->sc_blksz;
1366 			sc->sc_playcnt += togo;
1367 		}
1368 
1369 		P_WRITE(sc, EBDMA_DCNT, togo);
1370 		P_WRITE(sc, EBDMA_DADDR, nextaddr);
1371 		sc->sc_lastaddr = nextaddr + togo;
1372 
1373 		if (sc->sc_pintr != NULL)
1374 			(*sc->sc_pintr)(sc->sc_parg);
1375 		r = 1;
1376 	}
1377 
1378 	return (r);
1379 }
1380 
1381 void *
1382 ce4231_alloc(addr, direction, size, pool, flags)
1383 	void *addr;
1384 	int direction;
1385 	size_t size;
1386 	int pool;
1387 	int flags;
1388 {
1389 	struct ce4231_softc *sc = (struct ce4231_softc *)addr;
1390 	bus_dma_tag_t dmat = sc->sc_dmatag;
1391 	struct cs_dma *p;
1392 
1393 	p = (struct cs_dma *)malloc(sizeof(struct cs_dma), pool, flags);
1394 	if (p == NULL)
1395 		return (NULL);
1396 
1397 	if (bus_dmamap_create(dmat, size, 1, size, 0,
1398 	    BUS_DMA_NOWAIT, &p->dmamap) != 0)
1399 		goto fail;
1400 
1401 	p->size = size;
1402 
1403 	if (bus_dmamem_alloc(dmat, size, 64*1024, 0, p->segs,
1404 	    sizeof(p->segs)/sizeof(p->segs[0]), &p->nsegs,
1405 	    BUS_DMA_NOWAIT) != 0)
1406 		goto fail1;
1407 
1408 	if (bus_dmamem_map(dmat, p->segs, p->nsegs, p->size,
1409 	    &p->addr, BUS_DMA_NOWAIT | BUS_DMA_COHERENT) != 0)
1410 		goto fail2;
1411 
1412 	if (bus_dmamap_load(dmat, p->dmamap, p->addr, size, NULL,
1413 	    BUS_DMA_NOWAIT) != 0)
1414 		goto fail3;
1415 
1416 	p->next = sc->sc_dmas;
1417 	sc->sc_dmas = p;
1418 	return (p->addr);
1419 
1420 fail3:
1421 	bus_dmamem_unmap(dmat, p->addr, p->size);
1422 fail2:
1423 	bus_dmamem_free(dmat, p->segs, p->nsegs);
1424 fail1:
1425 	bus_dmamap_destroy(dmat, p->dmamap);
1426 fail:
1427 	free(p, pool);
1428 	return (NULL);
1429 }
1430 
1431 void
1432 ce4231_free(addr, ptr, pool)
1433 	void *addr;
1434 	void *ptr;
1435 	int pool;
1436 {
1437 	struct ce4231_softc *sc = addr;
1438 	bus_dma_tag_t dmat = sc->sc_dmatag;
1439 	struct cs_dma *p, **pp;
1440 
1441 	for (pp = &sc->sc_dmas; (p = *pp) != NULL; pp = &(*pp)->next) {
1442 		if (p->addr != ptr)
1443 			continue;
1444 		bus_dmamap_unload(dmat, p->dmamap);
1445 		bus_dmamem_unmap(dmat, p->addr, p->size);
1446 		bus_dmamem_free(dmat, p->segs, p->nsegs);
1447 		bus_dmamap_destroy(dmat, p->dmamap);
1448 		*pp = p->next;
1449 		free(p, pool);
1450 		return;
1451 	}
1452 	printf("%s: attempt to free rogue pointer\n", sc->sc_dev.dv_xname);
1453 }
1454 
1455 int
1456 ce4231_trigger_output(addr, start, end, blksize, intr, arg, param)
1457 	void *addr, *start, *end;
1458 	int blksize;
1459 	void (*intr)(void *);
1460 	void *arg;
1461 	struct audio_params *param;
1462 {
1463 	struct ce4231_softc *sc = addr;
1464 	struct cs_dma *p;
1465 	u_int32_t csr;
1466 	vaddr_t n;
1467 
1468 	if (sc->sc_locked != 0) {
1469 		printf("%s: trigger_output: already running\n",
1470 		    sc->sc_dev.dv_xname);
1471 		return (EINVAL);
1472 	}
1473 
1474 	sc->sc_locked = 1;
1475 	sc->sc_pintr = intr;
1476 	sc->sc_parg = arg;
1477 
1478 	for (p = sc->sc_dmas; p->addr != start; p = p->next)
1479 		/*EMPTY*/;
1480 	if (p == NULL) {
1481 		printf("%s: trigger_output: bad addr: %p\n",
1482 		    sc->sc_dev.dv_xname, start);
1483 		return (EINVAL);
1484 	}
1485 
1486 	n = (char *)end - (char *)start;
1487 
1488 	/*
1489 	 * Do only `blksize' at a time, so audio_pint() is kept
1490 	 * synchronous with us...
1491 	 */
1492 	sc->sc_blksz = blksize;
1493 	sc->sc_nowplaying = p;
1494 	sc->sc_playsegsz = n;
1495 
1496 	if (n > sc->sc_blksz)
1497 		n = sc->sc_blksz;
1498 
1499 	sc->sc_playcnt = n;
1500 
1501 	csr = P_READ(sc, EBDMA_DCSR);
1502 	if (csr & EBDCSR_DMAEN) {
1503 		P_WRITE(sc, EBDMA_DCNT, (u_long)n);
1504 		P_WRITE(sc, EBDMA_DADDR,
1505 		    (u_long)p->dmamap->dm_segs[0].ds_addr);
1506 	} else {
1507 		P_WRITE(sc, EBDMA_DCSR, EBDCSR_RESET);
1508 		P_WRITE(sc, EBDMA_DCSR, sc->sc_burst);
1509 
1510 		P_WRITE(sc, EBDMA_DCNT, (u_long)n);
1511 		P_WRITE(sc, EBDMA_DADDR,
1512 		    (u_long)p->dmamap->dm_segs[0].ds_addr);
1513 
1514 		P_WRITE(sc, EBDMA_DCSR, sc->sc_burst | EBDCSR_DMAEN |
1515 		    EBDCSR_INTEN | EBDCSR_CNTEN | EBDCSR_NEXTEN);
1516 
1517 		ce4231_write(sc, SP_LOWER_BASE_COUNT, 0xff);
1518 		ce4231_write(sc, SP_UPPER_BASE_COUNT, 0xff);
1519 		ce4231_write(sc, SP_INTERFACE_CONFIG,
1520 		    ce4231_read(sc, SP_INTERFACE_CONFIG) | PLAYBACK_ENABLE);
1521 	}
1522 	sc->sc_lastaddr = p->dmamap->dm_segs[0].ds_addr + n;
1523 
1524 	return (0);
1525 }
1526 
1527 int
1528 ce4231_trigger_input(addr, start, end, blksize, intr, arg, param)
1529 	void *addr, *start, *end;
1530 	int blksize;
1531 	void (*intr)(void *);
1532 	void *arg;
1533 	struct audio_params *param;
1534 {
1535 	return (ENXIO);
1536 }
1537