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