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