xref: /openbsd/sys/dev/ic/arcofi.c (revision 8529ddd3)
1 /*	$OpenBSD: arcofi.c,v 1.12 2015/05/11 06:46:21 ratchov Exp $	*/
2 
3 /*
4  * Copyright (c) 2011 Miodrag Vallat.
5  *
6  * Permission to use, copy, modify, and distribute this software for any
7  * purpose with or without fee is hereby granted, provided that the above
8  * copyright notice and this permission notice appear in all copies.
9  *
10  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17  */
18 
19 /*
20  * Driver for the HP ``Audio1'' device, which is a FIFO layer around a
21  * Siemens PSB 2160 ``ARCOFI'' phone quality audio chip.
22  *
23  * It is known to exist in two flavours: on-board the HP9000/425e as a DIO
24  * device, an on-board the HP9000/{705,710,745,747} as a GIO device.
25  *
26  * The FIFO logic buffers up to 128 bytes. When using 8 bit samples and
27  * the logic set to interrupt every half FIFO, the device will interrupt
28  * 125 times per second.
29  */
30 
31 #include <sys/param.h>
32 #include <sys/systm.h>
33 #include <sys/conf.h>
34 #include <sys/device.h>
35 #include <sys/kernel.h>
36 #include <sys/proc.h>
37 #include <sys/endian.h>
38 
39 #include <sys/audioio.h>
40 #include <dev/audio_if.h>
41 
42 #include <machine/autoconf.h>
43 #include <machine/bus.h>
44 #include <machine/intr.h>
45 
46 #include <dev/ic/arcofivar.h>
47 
48 #if 0
49 #define	ARCOFI_DEBUG
50 #endif
51 
52 /*
53  * Siemens PSB2160 registers
54  */
55 
56 /* CMDR */
57 #define	CMDR_AD		0x80	/* SP1/SP2 address convention */
58 #define	CMDR_READ	0x40
59 #define	CMDR_WRITE	0x00
60 #define	CMDR_PU		0x20	/* Power Up */
61 #define	CMDR_RCS	0x10	/* Receive and transmit in CH B2 */
62 #define	CMDR_MASK	0x0f
63 
64 	/* command	     length	data */
65 #define	SOP_0	0x00	/*	5	CR4 CR3 CR2 CR1 */
66 #define	COP_1	0x01	/*	5	t1_hi t1_lo f1_hi f1_lo */
67 #define	COP_2	0x02	/*	3	gr1 gr2 */
68 #define	COP_3	0x03	/*	3	t2_hi t2_lo f2_hi f2_lo */
69 #define	SOP_4	0x04	/*	2	CR1 */
70 #define	SOP_5	0x05	/*	2	CR2 */
71 #define	SOP_6	0x06	/*	2	CR3 */
72 #define	SOP_7	0x07	/*	2	CR4 */
73 #define	COP_8	0x08	/*	3	dtmf_hi dtmf_lo */
74 #define	COP_9	0x09	/*	5	gz a3 a2 a1 */
75 #define	COP_A	0x0a	/*	9	fx1 to fx8 */
76 #define	COP_B	0x0b	/*	3	gx1 gx2 */
77 #define	COP_C	0x0c	/*	9	fr1 to fr 8 */
78 #define	COP_D	0x0d	/*	5	fr9 fr10 fx9 fx10 */
79 #define	COP_E	0x0e	/*	5	t3_hi t3_lo f3_hi f3_lo */
80 
81 /* CR1 */
82 #define	CR1_GR		0x80	/* GR gain loaded from CRAM vs 0dB */
83 #define	CR1_GZ		0x40	/* Z gain loaded from CRAM vs -18dB */
84 #define	CR1_FX		0x20	/* X filter loaded from CRAM vs 0dB flat */
85 #define	CR1_FR		0x10	/* R filter loaded from CRAM vs 0dB flat */
86 #define	CR1_GX		0x08	/* GX gain loaded from CRAM vs 0dB */
87 #define	CR1_T_MASK	0x07	/* test mode */
88 #define	CR1_DLP		0x07	/* digital loopback via PCM registers */
89 #define	CR1_DLM		0x06	/* D/A output looped back to A/D input */
90 #define	CR1_DLS		0x05	/* digital loopback via converter registers */
91 #define	CR1_IDR		0x04	/* data RAM initialization */
92 #define	CR1_BYP		0x03	/* bypass analog frontend */
93 #define	CR1_ALM		0x02	/* analog loopback via MUX */
94 #define	CR1_ALS		0x01	/* analog loopback via converter registers */
95 
96 /* CR2 */
97 #define	CR2_SD		0x80	/* SD pin set to input vs output */
98 #define	CR2_SC		0x40	/* SC pin set to input vs output */
99 #define	CR2_SB		0x20	/* SB pin set to input vs output */
100 #define	CR2_SA		0x10	/* SA pin set to input vs output */
101 #define	CR2_ELS		0x08	/* non-input S pins tristate SIP vs sending 0 */
102 #define	CR2_AM		0x04	/* only one device on the SLD bus */
103 #define	CR2_TR		0x02	/* three party conferencing */
104 #define	CR2_EFC		0x01	/* enable feature control */
105 
106 /* CR3 */
107 #define	CR3_MIC_G_MASK	0xe0		/* MIC input analog gain  */
108 #define	CR3_MIC_X_INPUT		0xe0	/* MIC disabled, X input 15.1 dB */
109 #define	CR3_MIC_G_17		0xc0	/* 17 dB */
110 #define	CR3_MIC_G_22		0xa0	/* 22 dB */
111 #define	CR3_MIC_G_28		0x80	/* 28 dB */
112 #define	CR3_MIC_G_34		0x60	/* 34 dB */
113 #define	CR3_MIC_G_40		0x40	/* 40 dB */
114 #define	CR3_MIC_G_46		0x20	/* 46 dB */
115 #define	CR3_MIC_G_52		0x00	/* 52 dB (reset default) */
116 #define	CR3_AFEC_MASK	0x1c
117 #define	CR3_AFEC_MUTE		0x18	/* mute: Hout */
118 #define	CR3_AFEC_HFS		0x14	/* hands free: FHM, LS out */
119 #define	CR3_AFEC_LH3		0x10	/* loud hearing 3: MIC, H out, LS out */
120 #define	CR3_AFEC_LH2		0x0c	/* loud hearing 2: MIC, LS out */
121 #define	CR3_AFEC_LH1		0x08	/* loud hearing 1: LS out */
122 #define	CR3_AFEC_RDY		0x04	/* ready: MIC, H out */
123 #define	CR3_AFEC_POR		0x00	/* power on reset: all off */
124 #define	CR3_OPMODE_MASK	0x03
125 #define	CR3_OPMODE_LINEAR	0x02	/* linear (16 bit) */
126 #define	CR3_OPMODE_MIXED	0x01	/* mixed */
127 #define	CR3_OPMODE_NORMAL	0x00	/* normal (A/u-Law) */
128 
129 /* CR4 */
130 #define	CR4_DHF		0x80	/* TX digital high frequency enable */
131 #define	CR4_DTMF	0x40	/* DTMF generator enable */
132 #define	CR4_TG		0x20	/* tone ring enable */
133 #define	CR4_BT		0x10	/* beat tone generator enable */
134 #define	CR4_TM		0x08	/* incoming voice enable */
135 #define	CR4_BM		0x04	/* beat mode (3 tone vs 2 tone) */
136 #define	CR4_PM		0x02	/* tone sent to piezo vs loudspeaker */
137 #define	CR4_ULAW	0x01	/* u-Law vs A-Law */
138 
139 
140 /*
141  * Glue logic registers
142  * Note the register values here are symbolic, as actual addresses
143  * depend upon the particular bus the device is connected to.
144  */
145 
146 #define	ARCOFI_ID		0	/* id (r) and reset (w) register */
147 
148 #define	ARCOFI_CSR		1	/* status and control register */
149 #define	CSR_INTR_ENABLE			0x80
150 #define	CSR_INTR_REQUEST		0x40	/* unacknowledged interrupt */
151 /* 0x20 and 0x10 used in DIO flavours, to provide IPL */
152 #define	CSR_WIDTH_16			0x08	/* 16-bit samples */
153 #define	CSR_CTRL_FIFO_ENABLE		0x04	/* connect FIFO to CMDR */
154 #define	CSR_DATA_FIFO_ENABLE		0x01	/* connect FIFO to DU/DD */
155 
156 #define	ARCOFI_FIFO_IR		2	/* FIFO interrupt register */
157 #define	FIFO_IR_ENABLE(ev)		((ev) << 4)
158 #define	FIFO_IR_EVENT(ev)		(ev)
159 #define	FIFO_IR_OUT_EMPTY		0x08
160 #define	FIFO_IR_CTRL_EMPTY		0x04
161 #define	FIFO_IR_OUT_HALF_EMPTY		0x02
162 #define	FIFO_IR_IN_HALF_EMPTY		0x01
163 
164 #define	ARCOFI_FIFO_SR		3	/* FIFO status register (ro) */
165 #define	FIFO_SR_CTRL_FULL		0x20
166 #define	FIFO_SR_CTRL_EMPTY		0x10
167 #define	FIFO_SR_OUT_FULL		0x08
168 #define	FIFO_SR_OUT_EMPTY		0x04
169 #define	FIFO_SR_IN_FULL			0x02
170 #define	FIFO_SR_IN_EMPTY		0x01
171 
172 #define	ARCOFI_FIFO_DATA	4	/* data FIFO port */
173 
174 #define	ARCOFI_FIFO_CTRL	5	/* control FIFO port (wo) */
175 
176 #define	ARCOFI_FIFO_SIZE	128
177 
178 
179 struct cfdriver arcofi_cd = {
180 	NULL, "arcofi", DV_DULL
181 };
182 
183 #define	arcofi_read(sc, r) \
184 	bus_space_read_1((sc)->sc_iot, (sc)->sc_ioh, (sc)->sc_reg[r])
185 #define	arcofi_write(sc, r, v) \
186 	bus_space_write_1((sc)->sc_iot, (sc)->sc_ioh, (sc)->sc_reg[r], v)
187 
188 int	arcofi_cmd(struct arcofi_softc *, uint8_t, const uint8_t *);
189 int	arcofi_cr3_to_portmask(uint, int);
190 int	arcofi_gain_to_mi(uint);
191 uint	arcofi_mi_to_gain(int);
192 uint	arcofi_portmask_to_cr3(int);
193 int	arcofi_set_param(struct arcofi_softc *, int, int, int,
194 	    struct audio_params *);
195 
196 void	arcofi_close(void *);
197 int	arcofi_commit_settings(void *);
198 int	arcofi_drain(void *);
199 int	arcofi_getdev(void *, struct audio_device *);
200 int	arcofi_get_port(void *, mixer_ctrl_t *);
201 int	arcofi_get_props(void *);
202 int	arcofi_halt_input(void *);
203 int	arcofi_halt_output(void *);
204 int	arcofi_open(void *, int);
205 int	arcofi_query_devinfo(void *, mixer_devinfo_t *);
206 int	arcofi_query_encoding(void *, struct audio_encoding *);
207 int	arcofi_round_blocksize(void *, int);
208 int	arcofi_set_params(void *, int, int, struct audio_params *,
209 	    struct audio_params *);
210 int	arcofi_set_port(void *, mixer_ctrl_t *);
211 int	arcofi_start_input(void *, void *, int, void (*)(void *), void *);
212 int	arcofi_start_output(void *, void *, int, void (*)(void *), void *);
213 
214 /* const */ struct audio_hw_if arcofi_hw_if = {
215 	.open = arcofi_open,
216 	.close = arcofi_close,
217 	.query_encoding = arcofi_query_encoding,
218 	.set_params = arcofi_set_params,
219 	.round_blocksize = arcofi_round_blocksize,
220 	.commit_settings = arcofi_commit_settings,
221 	.start_output = arcofi_start_output,
222 	.start_input = arcofi_start_input,
223 	.halt_output = arcofi_halt_output,
224 	.halt_input = arcofi_halt_input,
225 	.getdev = arcofi_getdev,
226 	.set_port = arcofi_set_port,
227 	.get_port = arcofi_get_port,
228 	.query_devinfo = arcofi_query_devinfo,
229 	.get_props = arcofi_get_props,
230 };
231 
232 /* mixer items */
233 #define	ARCOFI_PORT_AUDIO_IN_VOLUME	0	/* line in volume (GR) */
234 #define	ARCOFI_PORT_AUDIO_OUT_VOLUME	1	/* line out volume (GX) */
235 #define	ARCOFI_PORT_AUDIO_SPKR_VOLUME	2	/* speaker volume (GX) */
236 #define	ARCOFI_PORT_AUDIO_IN_MUTE	3	/* line in mute (MIC) */
237 #define	ARCOFI_PORT_AUDIO_OUT_MUTE	4	/* line out mute (H out) */
238 #define	ARCOFI_PORT_AUDIO_SPKR_MUTE	5	/* line in mute (LS out) */
239 /* mixer classes */
240 #define	ARCOFI_CLASS_INPUT		6
241 #define	ARCOFI_CLASS_OUTPUT		7
242 
243 /*
244  * Gain programming formulae are a complete mystery to me, and of course
245  * no two chips are compatible - not even the PSB 2163 and PSB 2165
246  * later ARCOFI chips, from the same manufacturer as the PSB 2160!
247  *
248  * Of course, the PSB 2160 datasheet does not give any set of values.
249  * The following table is taken from the HP-UX audio driver (audio_shared.o
250  * private_audio_gain_tab).
251  */
252 
253 #define	NEGATIVE_GAINS	60
254 #define	POSITIVE_GAINS	14
255 static const uint16_t arcofi_gains[1 + NEGATIVE_GAINS + 1 + POSITIVE_GAINS] = {
256 	/* minus infinity */
257 	0x0988,
258 
259 	0xf8b8, 0xf8b8, 0xf8b8, 0xf8b8, 0x099f, 0x099f, 0x099f, 0x099f,
260 	0x09af, 0x09af, 0x09af, 0x09cf, 0x09cf, 0x09cf, 0xf8a9, 0xf83a,
261 	0xf83a, 0xf82b, 0xf82d, 0xf8a3, 0xf8b2, 0xf8a1, 0xe8aa, 0xe84b,
262 	0xe89e, 0xe8d3, 0xe891, 0xe8b1, 0xd8aa, 0xd8cb, 0xd8a6, 0xd8b3,
263 	0xd842, 0xd8b1, 0xc8aa, 0xc8bb, 0xc888, 0xc853, 0xc852, 0xc8b1,
264 	0xb8aa, 0xb8ab, 0xb896, 0xb892, 0xb842, 0xb8b1, 0xa8aa, 0xa8bb,
265 	0x199f, 0x195b, 0x29c1, 0x2923, 0x29aa, 0x392b, 0xf998, 0xb988,
266 	0x1aac, 0x3aa1, 0xbaa1, 0xbb88,
267 
268 	/* 0 */
269 	0x8888,
270 
271 	0xd388, 0x5288, 0xb1a1, 0x31a1, 0x1192, 0x11d0, 0x30c0, 0x2050,
272 	0x1021, 0x1020, 0x1000, 0x0001, 0x0010, 0x0000
273 };
274 
275 int
276 arcofi_open(void *v, int flags)
277 {
278 	struct arcofi_softc *sc = (struct arcofi_softc *)v;
279 
280 	if (sc->sc_open)
281 		return EBUSY;
282 	sc->sc_open = 1;
283 	KASSERT(sc->sc_mode == 0);
284 
285 	return 0;
286 }
287 
288 void
289 arcofi_close(void *v)
290 {
291 	struct arcofi_softc *sc = (struct arcofi_softc *)v;
292 
293 	arcofi_halt_input(v);
294 	arcofi_halt_output(v);
295 	sc->sc_open = 0;
296 }
297 
298 int
299 arcofi_drain(void *v)
300 {
301 	struct arcofi_softc *sc = (struct arcofi_softc *)v;
302 
303 	mtx_enter(&audio_lock);
304 	if ((arcofi_read(sc, ARCOFI_FIFO_SR) & FIFO_SR_OUT_EMPTY) == 0) {
305 		/* enable output FIFO empty interrupt... */
306 		arcofi_write(sc, ARCOFI_FIFO_IR,
307 		    arcofi_read(sc, ARCOFI_FIFO_IR) |
308 		    FIFO_IR_ENABLE(FIFO_IR_OUT_EMPTY));
309 		/* ...and wait for it to fire */
310 		if (msleep(&sc->sc_xmit, &audio_lock, 0, "arcofidr",
311 		    1 + (ARCOFI_FIFO_SIZE * hz) / 8000) != 0) {
312 			printf("%s: drain did not complete\n",
313 			    sc->sc_dev.dv_xname);
314 			arcofi_write(sc, ARCOFI_FIFO_IR,
315 			    arcofi_read(sc, ARCOFI_FIFO_IR) &
316 			    ~FIFO_IR_ENABLE(FIFO_IR_OUT_EMPTY));
317 		}
318 	}
319 	mtx_leave(&audio_lock);
320 	return 0;
321 }
322 
323 int
324 arcofi_query_encoding(void *v, struct audio_encoding *ae)
325 {
326 	switch (ae->index) {
327 	/*
328 	 * 8-bit encodings: u-Law and A-Law are native
329 	 */
330 	case 0:
331 		strlcpy(ae->name, AudioEmulaw, sizeof ae->name);
332 		ae->precision = 8;
333 		ae->encoding = AUDIO_ENCODING_ULAW;
334 		ae->flags = 0;
335 		break;
336 	case 1:
337 		strlcpy(ae->name, AudioEalaw, sizeof ae->name);
338 		ae->precision = 8;
339 		ae->encoding = AUDIO_ENCODING_ALAW;
340 		ae->flags = 0;
341 		break;
342 
343 	/*
344 	 * 16-bit encodings: slinear big-endian is native
345 	 */
346 	case 2:
347 		strlcpy(ae->name, AudioEslinear_be, sizeof ae->name);
348 		ae->precision = 16;
349 		ae->encoding = AUDIO_ENCODING_SLINEAR_BE;
350 		ae->flags = 0;
351 		break;
352 
353 	default:
354 		return EINVAL;
355 	}
356 
357 	ae->bps = AUDIO_BPS(ae->precision);
358 	ae->msb = 1;
359 
360 	return 0;
361 }
362 
363 /*
364  * Compute proper sample and hardware settings. Invoked both for record
365  * and playback, as we don't support independent settings.
366  */
367 int
368 arcofi_set_param(struct arcofi_softc *sc, int set, int use, int mode,
369     struct audio_params *ap)
370 {
371 	if ((set & mode) == 0)
372 		return 0;
373 
374 #ifdef ARCOFI_DEBUG
375 	printf("%s: set_param, mode %d encoding %d precision %d\n",
376 	    sc->sc_dev.dv_xname, mode, ap->encoding, ap->precision);
377 #endif
378 	switch (ap->precision) {
379 	case 8:
380 		switch (ap->encoding) {
381 		case AUDIO_ENCODING_ULAW:
382 			sc->sc_shadow.cr4 |= CR4_ULAW;
383 			break;
384 		case AUDIO_ENCODING_ALAW:
385 			sc->sc_shadow.cr4 &= ~CR4_ULAW;
386 			break;
387 		default:
388 			return EINVAL;
389 		}
390 		sc->sc_shadow.cr3 = (sc->sc_shadow.cr3 & ~CR3_OPMODE_MASK) |
391 		    CR3_OPMODE_NORMAL;
392 		break;
393 	case 16:
394 		switch (ap->encoding) {
395 		case AUDIO_ENCODING_SLINEAR_BE:
396 			break;
397 		default:
398 			return EINVAL;
399 		}
400 		sc->sc_shadow.cr3 = (sc->sc_shadow.cr3 & ~CR3_OPMODE_MASK) |
401 		    CR3_OPMODE_LINEAR;
402 		break;
403 	default:
404 		return EINVAL;
405 	}
406 
407 	ap->bps = AUDIO_BPS(ap->precision);
408 	ap->msb = 1;
409 	ap->channels = 1;
410 	ap->sample_rate = 8000;
411 
412 	return 0;
413 }
414 
415 int
416 arcofi_set_params(void *v, int set, int use, struct audio_params *p,
417     struct audio_params *r)
418 {
419 	struct arcofi_softc *sc = (struct arcofi_softc *)v;
420 	int rc;
421 
422 	if (r != NULL) {
423 		rc = arcofi_set_param(sc, set, use, AUMODE_RECORD, r);
424 		if (rc != 0)
425 			return rc;
426 	}
427 
428 	if (p != NULL) {
429 		rc = arcofi_set_param(sc, set, use, AUMODE_PLAY, p);
430 		if (rc != 0)
431 			return rc;
432 	}
433 
434 	return 0;
435 }
436 
437 int
438 arcofi_round_blocksize(void *v, int blksz)
439 {
440 	/*
441 	 * Round the size up to a multiple of half the FIFO, to favour
442 	 * smooth interrupt operation.
443 	 */
444 	return roundup(blksz, ARCOFI_FIFO_SIZE / 2);
445 }
446 
447 int
448 arcofi_commit_settings(void *v)
449 {
450 	struct arcofi_softc *sc = (struct arcofi_softc *)v;
451 	int rc;
452 	uint8_t cmd[2], csr, ocsr;
453 
454 #ifdef ARCOFI_DEBUG
455 	printf("%s: commit_settings, gr %04x gx %04x cr3 %02x cr4 %02x mute %d\n",
456 	    sc->sc_dev.dv_xname,
457 	    arcofi_gains[sc->sc_shadow.gr_idx],
458 	    arcofi_gains[sc->sc_shadow.gx_idx],
459 	    sc->sc_shadow.cr3, sc->sc_shadow.cr4, sc->sc_shadow.output_mute);
460 #endif
461 
462 	if (bcmp(&sc->sc_active, &sc->sc_shadow, sizeof(sc->sc_active)) == 0)
463 		return 0;
464 
465 	mtx_enter(&audio_lock);
466 
467 	if (sc->sc_active.gr_idx != sc->sc_shadow.gr_idx) {
468 		cmd[0] = arcofi_gains[sc->sc_shadow.gr_idx] >> 8;
469 		cmd[1] = arcofi_gains[sc->sc_shadow.gr_idx];
470 		if ((rc = arcofi_cmd(sc, COP_2, cmd)) != 0)
471 			goto error;
472 		sc->sc_active.gr_idx = sc->sc_shadow.gr_idx;
473 	}
474 
475 	if (sc->sc_active.gx_idx != sc->sc_shadow.gx_idx ||
476 	    sc->sc_active.output_mute != sc->sc_shadow.output_mute) {
477 		if (sc->sc_shadow.output_mute) {
478 			cmd[0] = arcofi_gains[0] >> 8;
479 			cmd[1] = arcofi_gains[0];
480 		} else {
481 			cmd[0] = arcofi_gains[sc->sc_shadow.gx_idx] >> 8;
482 			cmd[1] = arcofi_gains[sc->sc_shadow.gx_idx];
483 		}
484 		if ((rc = arcofi_cmd(sc, COP_B, cmd)) != 0)
485 			goto error;
486 		sc->sc_active.gx_idx = sc->sc_shadow.gx_idx;
487 		sc->sc_active.output_mute = sc->sc_shadow.output_mute;
488 	}
489 
490 	if (sc->sc_active.cr3 != sc->sc_shadow.cr3) {
491 		cmd[0] = sc->sc_shadow.cr3;
492 		if ((rc = arcofi_cmd(sc, SOP_6, cmd)) != 0)
493 			goto error;
494 		sc->sc_active.cr3 = sc->sc_shadow.cr3;
495 
496 		ocsr = arcofi_read(sc, ARCOFI_CSR);
497 		if ((sc->sc_active.cr3 & CR3_OPMODE_MASK) != CR3_OPMODE_NORMAL)
498 			csr = ocsr | CSR_WIDTH_16;
499 		else
500 			csr = ocsr & ~CSR_WIDTH_16;
501 		if (csr != ocsr)
502 			arcofi_write(sc, ARCOFI_CSR, csr);
503 	}
504 
505 	if (sc->sc_active.cr4 != sc->sc_shadow.cr4) {
506 		cmd[0] = sc->sc_shadow.cr4;
507 		if ((rc = arcofi_cmd(sc, SOP_7, cmd)) != 0)
508 			goto error;
509 		sc->sc_active.cr4 = sc->sc_shadow.cr4;
510 	}
511 
512 	rc = 0;
513 error:
514 	mtx_leave(&audio_lock);
515 	return rc;
516 }
517 
518 int
519 arcofi_start_input(void *v, void *rbuf, int rsz, void (*cb)(void *),
520     void *cbarg)
521 {
522 	struct arcofi_softc *sc = (struct arcofi_softc *)v;
523 
524 #ifdef ARCOFI_DEBUG
525 	printf("%s: start_input, mode %d\n",
526 	    sc->sc_dev.dv_xname, sc->sc_mode);
527 #endif
528 
529 	/* enable data FIFO if becoming active */
530 	if (sc->sc_mode == 0)
531 		arcofi_write(sc, ARCOFI_CSR,
532 		    arcofi_read(sc, ARCOFI_CSR) | CSR_DATA_FIFO_ENABLE);
533 	sc->sc_mode |= AUMODE_RECORD;
534 
535 	sc->sc_recv.buf = (uint8_t *)rbuf;
536 	sc->sc_recv.past = (uint8_t *)rbuf + rsz;
537 	sc->sc_recv.cb = cb;
538 	sc->sc_recv.cbarg = cbarg;
539 
540 	/* enable input FIFO interrupts */
541 	arcofi_write(sc, ARCOFI_FIFO_IR, arcofi_read(sc, ARCOFI_FIFO_IR) |
542 	    FIFO_IR_ENABLE(FIFO_IR_IN_HALF_EMPTY));
543 
544 	return 0;
545 }
546 
547 int
548 arcofi_start_output(void *v, void *wbuf, int wsz, void (*cb)(void *),
549     void *cbarg)
550 {
551 	struct arcofi_softc *sc = (struct arcofi_softc *)v;
552 
553 #ifdef ARCOFI_DEBUG
554 	printf("%s: start_output, mode %d\n",
555 	    sc->sc_dev.dv_xname, sc->sc_mode);
556 #endif
557 
558 	/* enable data FIFO if becoming active */
559 	if (sc->sc_mode == 0)
560 		arcofi_write(sc, ARCOFI_CSR,
561 		    arcofi_read(sc, ARCOFI_CSR) | CSR_DATA_FIFO_ENABLE);
562 	sc->sc_mode |= AUMODE_PLAY;
563 
564 	sc->sc_xmit.buf = (uint8_t *)wbuf;
565 	sc->sc_xmit.past = (uint8_t *)wbuf + wsz;
566 	sc->sc_xmit.cb = cb;
567 	sc->sc_xmit.cbarg = cbarg;
568 
569 	/* enable output FIFO interrupts */
570 	arcofi_write(sc, ARCOFI_FIFO_IR, arcofi_read(sc, ARCOFI_FIFO_IR) |
571 	    FIFO_IR_ENABLE(FIFO_IR_OUT_HALF_EMPTY));
572 
573 	return 0;
574 }
575 
576 int
577 arcofi_halt_input(void *v)
578 {
579 	struct arcofi_softc *sc = (struct arcofi_softc *)v;
580 
581 	mtx_enter(&audio_lock);
582 
583 	/* disable input FIFO interrupts */
584 	arcofi_write(sc, ARCOFI_FIFO_IR, arcofi_read(sc, ARCOFI_FIFO_IR) &
585 	    ~FIFO_IR_ENABLE(FIFO_IR_IN_HALF_EMPTY));
586 	/* disable data FIFO if becoming idle */
587 	sc->sc_mode &= ~AUMODE_RECORD;
588 	if (sc->sc_mode == 0)
589 		arcofi_write(sc, ARCOFI_CSR,
590 		    arcofi_read(sc, ARCOFI_CSR) & ~CSR_DATA_FIFO_ENABLE);
591 
592 	mtx_leave(&audio_lock);
593 	return 0;
594 }
595 
596 int
597 arcofi_halt_output(void *v)
598 {
599 	struct arcofi_softc *sc = (struct arcofi_softc *)v;
600 
601 	mtx_enter(&audio_lock);
602 
603 	/* disable output FIFO interrupts */
604 	arcofi_write(sc, ARCOFI_FIFO_IR, arcofi_read(sc, ARCOFI_FIFO_IR) &
605 	    ~FIFO_IR_ENABLE(FIFO_IR_OUT_HALF_EMPTY));
606 	/* disable data FIFO if becoming idle */
607 	sc->sc_mode &= ~AUMODE_PLAY;
608 	if (sc->sc_mode == 0)
609 		arcofi_write(sc, ARCOFI_CSR,
610 		    arcofi_read(sc, ARCOFI_CSR) & ~CSR_DATA_FIFO_ENABLE);
611 
612 	mtx_leave(&audio_lock);
613 	return 0;
614 }
615 
616 int
617 arcofi_getdev(void *v, struct audio_device *ad)
618 {
619 	struct arcofi_softc *sc = (struct arcofi_softc *)v;
620 
621 	bcopy(&sc->sc_audio_device, ad, sizeof(*ad));
622 	return 0;
623 }
624 
625 /*
626  * Convert gain table index to AUDIO_MIN_GAIN..AUDIO_MAX_GAIN scale.
627  */
628 int
629 arcofi_gain_to_mi(uint idx)
630 {
631 	if (idx == 0)
632 		return AUDIO_MIN_GAIN;
633 	if (idx == nitems(arcofi_gains) - 1)
634 		return AUDIO_MAX_GAIN;
635 
636 	return ((idx - 1) * (AUDIO_MAX_GAIN - AUDIO_MIN_GAIN)) /
637 	    (nitems(arcofi_gains) - 1) + AUDIO_MIN_GAIN + 1;
638 }
639 
640 /*
641  * Convert AUDIO_MIN_GAIN..AUDIO_MAX_GAIN scale to gain table index.
642  */
643 uint
644 arcofi_mi_to_gain(int lvl)
645 {
646 	if (lvl <= AUDIO_MIN_GAIN)
647 		return 0;
648 	if (lvl >= AUDIO_MAX_GAIN)
649 		return nitems(arcofi_gains) - 1;
650 
651 	return ((lvl - AUDIO_MIN_GAIN - 1) * (nitems(arcofi_gains) - 1)) /
652 	    (AUDIO_MAX_GAIN - AUDIO_MIN_GAIN);
653 }
654 
655 /*
656  * The following routines rely upon this...
657  */
658 #if (AUDIO_SPEAKER == AUDIO_LINE_IN) || (AUDIO_LINE_OUT == AUDIO_LINE_IN) || \
659     (AUDIO_SPEAKER == AUDIO_LINE_OUT)
660 #error Please rework the cr3 handling logic.
661 #endif
662 
663 /*
664  * The mapping between the available inputs and outputs, and CR3, is as
665  * follows:
666  * - the `line in' connector is the `MIC' input.
667  * - the `line out' connector is the `H out' (heaphones) output.
668  * - the internal `speaker' is the `LS out' (loudspeaker) output.
669  *
670  * Each of these can be enabled or disabled independently, except for
671  * MIC enabled with H out and LS out disabled, which is not allowed
672  * by the chip (and makes no sense for a chip which was intended to
673  * be used in phones, not voice recorders); we cheat by keeping one
674  * output source enabled, but with the output gain forced to minus
675  * infinity to mute it.
676  *
677  * The truth table is thus:
678  *
679  *	MIC	LS out	H out	AFEC
680  *	off	off	off	POR
681  *	off	off	on	MUTE
682  *	off	on	off	LH1
683  *	off	on	on	LH3, X input enabled
684  *	on	off	off	RDY, GX forced to minus infinity
685  *	on	off	on	RDY
686  *	on	on	off	LH2
687  *	on	on	on	LH3
688  */
689 
690 /*
691  * Convert logical port enable settings to a valid CR3 value.
692  */
693 uint
694 arcofi_portmask_to_cr3(int mask)
695 {
696 	switch (mask) {
697 	default:
698 	case 0:
699 		return CR3_MIC_G_17 | CR3_AFEC_POR;
700 	case AUDIO_LINE_OUT:
701 		return CR3_MIC_G_17 | CR3_AFEC_MUTE;
702 	case AUDIO_SPEAKER:
703 		return CR3_MIC_G_17 | CR3_AFEC_LH1;
704 	case AUDIO_SPEAKER | AUDIO_LINE_OUT:
705 		return CR3_MIC_X_INPUT | CR3_AFEC_LH3;
706 	case AUDIO_LINE_IN:
707 		/* since we can't do this, just... */
708 		/* FALLTHROUGH */
709 	case AUDIO_LINE_IN | AUDIO_LINE_OUT:
710 		return CR3_MIC_G_17 | CR3_AFEC_RDY;
711 	case AUDIO_LINE_IN | AUDIO_SPEAKER:
712 		return CR3_MIC_G_17 | CR3_AFEC_LH2;
713 	case AUDIO_LINE_IN | AUDIO_SPEAKER | AUDIO_LINE_OUT:
714 		return CR3_MIC_G_17 | CR3_AFEC_LH3;
715 	}
716 }
717 
718 /*
719  * Convert CR3 to an enabled ports mask.
720  */
721 int
722 arcofi_cr3_to_portmask(uint cr3, int output_mute)
723 {
724 	switch (cr3 & CR3_AFEC_MASK) {
725 	default:
726 	case CR3_AFEC_POR:
727 		return 0;
728 	case CR3_AFEC_RDY:
729 		return output_mute ?
730 		    AUDIO_LINE_IN : AUDIO_LINE_IN | AUDIO_LINE_OUT;
731 	case CR3_AFEC_HFS:
732 	case CR3_AFEC_LH1:
733 		return AUDIO_SPEAKER;
734 	case CR3_AFEC_LH2:
735 		return AUDIO_LINE_IN | AUDIO_SPEAKER;
736 	case CR3_AFEC_LH3:
737 		if ((cr3 & CR3_MIC_G_MASK) == CR3_MIC_X_INPUT)
738 			return AUDIO_SPEAKER | AUDIO_LINE_OUT;
739 		else
740 			return AUDIO_LINE_IN | AUDIO_SPEAKER | AUDIO_LINE_OUT;
741 	case CR3_AFEC_MUTE:
742 		return AUDIO_LINE_OUT;
743 	}
744 }
745 
746 int
747 arcofi_set_port(void *v, mixer_ctrl_t *mc)
748 {
749 	struct arcofi_softc *sc = (struct arcofi_softc *)v;
750 	int portmask;
751 
752 	/* check for proper type */
753 	switch (mc->dev) {
754 	/* volume settings */
755 	case ARCOFI_PORT_AUDIO_IN_VOLUME:
756 	case ARCOFI_PORT_AUDIO_OUT_VOLUME:
757 	case ARCOFI_PORT_AUDIO_SPKR_VOLUME:
758 		if (mc->un.value.num_channels != 1)
759 			return EINVAL;
760 		break;
761 	/* mute settings */
762 	case ARCOFI_PORT_AUDIO_IN_MUTE:
763 	case ARCOFI_PORT_AUDIO_OUT_MUTE:
764 	case ARCOFI_PORT_AUDIO_SPKR_MUTE:
765 		if (mc->type != AUDIO_MIXER_ENUM)
766 			return EINVAL;
767 		portmask = arcofi_cr3_to_portmask(sc->sc_shadow.cr3,
768 		    sc->sc_shadow.output_mute);
769 #ifdef ARCOFI_DEBUG
770 		printf("%s: set_port cr3 %02x -> mask %02x\n",
771 		    sc->sc_dev.dv_xname, sc->sc_shadow.cr3, portmask);
772 #endif
773 		break;
774 	default:
775 		return EINVAL;
776 	}
777 
778 	switch (mc->dev) {
779 	/* volume settings */
780 	case ARCOFI_PORT_AUDIO_IN_VOLUME:
781 		sc->sc_shadow.gr_idx =
782 		    arcofi_mi_to_gain(mc->un.value.level[AUDIO_MIXER_LEVEL_MONO]);
783 		return 0;
784 	case ARCOFI_PORT_AUDIO_OUT_VOLUME:
785 	case ARCOFI_PORT_AUDIO_SPKR_VOLUME:
786 		sc->sc_shadow.gx_idx =
787 		    arcofi_mi_to_gain(mc->un.value.level[AUDIO_MIXER_LEVEL_MONO]);
788 		return 0;
789 
790 	/* mute settings */
791 	case ARCOFI_PORT_AUDIO_IN_MUTE:
792 		if (mc->un.ord)
793 			portmask &= ~AUDIO_LINE_IN;
794 		else
795 			portmask |= AUDIO_LINE_IN;
796 		break;
797 	case ARCOFI_PORT_AUDIO_OUT_MUTE:
798 		if (mc->un.ord)
799 			portmask &= ~AUDIO_LINE_OUT;
800 		else
801 			portmask |= AUDIO_LINE_OUT;
802 		break;
803 	case ARCOFI_PORT_AUDIO_SPKR_MUTE:
804 		if (mc->un.ord)
805 			portmask &= ~AUDIO_SPEAKER;
806 		else
807 			portmask |= AUDIO_SPEAKER;
808 		break;
809 	}
810 
811 	sc->sc_shadow.cr3 = (sc->sc_shadow.cr3 & CR3_OPMODE_MASK) |
812 	    arcofi_portmask_to_cr3(portmask);
813 	sc->sc_shadow.output_mute = (portmask == AUDIO_LINE_IN);
814 #ifdef ARCOFI_DEBUG
815 	printf("%s: set_port mask %02x -> cr3 %02x m %d\n",
816 	    sc->sc_dev.dv_xname, portmask,
817 	    sc->sc_shadow.cr3, sc->sc_shadow.output_mute);
818 #endif
819 
820 	return 0;
821 }
822 
823 int
824 arcofi_get_port(void *v, mixer_ctrl_t *mc)
825 {
826 	struct arcofi_softc *sc = (struct arcofi_softc *)v;
827 	int portmask;
828 
829 	/* check for proper type */
830 	switch (mc->dev) {
831 	/* volume settings */
832 	case ARCOFI_PORT_AUDIO_IN_VOLUME:
833 	case ARCOFI_PORT_AUDIO_OUT_VOLUME:
834 	case ARCOFI_PORT_AUDIO_SPKR_VOLUME:
835 		if (mc->un.value.num_channels != 1)
836 			return EINVAL;
837 		break;
838 
839 	/* mute settings */
840 	case ARCOFI_PORT_AUDIO_IN_MUTE:
841 	case ARCOFI_PORT_AUDIO_OUT_MUTE:
842 	case ARCOFI_PORT_AUDIO_SPKR_MUTE:
843 		if (mc->type != AUDIO_MIXER_ENUM)
844 			return EINVAL;
845 		portmask = arcofi_cr3_to_portmask(sc->sc_shadow.cr3,
846 		    sc->sc_shadow.output_mute);
847 #ifdef ARCOFI_DEBUG
848 		printf("%s: get_port cr3 %02x -> mask %02x\n",
849 		    sc->sc_dev.dv_xname, sc->sc_shadow.cr3, portmask);
850 #endif
851 		break;
852 	default:
853 		return EINVAL;
854 	}
855 
856 	switch (mc->dev) {
857 	/* volume settings */
858 	case ARCOFI_PORT_AUDIO_IN_VOLUME:
859 		mc->un.value.level[AUDIO_MIXER_LEVEL_MONO] =
860 		    arcofi_gain_to_mi(sc->sc_shadow.gr_idx);
861 		break;
862 	case ARCOFI_PORT_AUDIO_OUT_VOLUME:
863 	case ARCOFI_PORT_AUDIO_SPKR_VOLUME:
864 		mc->un.value.level[AUDIO_MIXER_LEVEL_MONO] =
865 		    arcofi_gain_to_mi(sc->sc_shadow.gx_idx);
866 		break;
867 
868 	/* mute settings */
869 	case ARCOFI_PORT_AUDIO_IN_MUTE:
870 		mc->un.ord = portmask & AUDIO_LINE_IN ? 0 : 1;
871 		break;
872 	case ARCOFI_PORT_AUDIO_OUT_MUTE:
873 		mc->un.ord = portmask & AUDIO_LINE_OUT ? 0 : 1;
874 		break;
875 	case ARCOFI_PORT_AUDIO_SPKR_MUTE:
876 		mc->un.ord = portmask & AUDIO_SPEAKER ? 0 : 1;
877 		break;
878 	}
879 
880 	return 0;
881 }
882 
883 int
884 arcofi_query_devinfo(void *v, mixer_devinfo_t *md)
885 {
886 	switch (md->index) {
887 	default:
888 		return ENXIO;
889 
890 	/* items */
891 	case ARCOFI_PORT_AUDIO_IN_VOLUME:
892 		md->type = AUDIO_MIXER_VALUE;
893 		md->mixer_class = ARCOFI_CLASS_INPUT;
894 		md->prev = AUDIO_MIXER_LAST;
895 		md->next = ARCOFI_PORT_AUDIO_IN_MUTE;
896 		strlcpy(md->label.name, AudioNline,
897 		    sizeof md->label.name);
898 		goto mono_volume;
899 	case ARCOFI_PORT_AUDIO_OUT_VOLUME:
900 		md->type = AUDIO_MIXER_VALUE;
901 		md->mixer_class = ARCOFI_CLASS_OUTPUT;
902 		md->prev = AUDIO_MIXER_LAST;
903 		md->next = ARCOFI_PORT_AUDIO_OUT_MUTE;
904 		strlcpy(md->label.name, AudioNline,
905 		    sizeof md->label.name);
906 		goto mono_volume;
907 	case ARCOFI_PORT_AUDIO_SPKR_VOLUME:
908 		md->type = AUDIO_MIXER_VALUE;
909 		md->mixer_class = ARCOFI_CLASS_OUTPUT;
910 		md->prev = AUDIO_MIXER_LAST;
911 		md->next = ARCOFI_PORT_AUDIO_SPKR_MUTE;
912 		strlcpy(md->label.name, AudioNspeaker,
913 		    sizeof md->label.name);
914 		/* goto mono_volume; */
915 mono_volume:
916 		md->un.v.num_channels = 1;
917 		strlcpy(md->un.v.units.name, AudioNvolume,
918 		    sizeof md->un.v.units.name);
919 		break;
920 
921 	case ARCOFI_PORT_AUDIO_IN_MUTE:
922 		md->type = AUDIO_MIXER_ENUM;
923 		md->mixer_class = ARCOFI_CLASS_INPUT;
924 		md->prev = ARCOFI_PORT_AUDIO_IN_VOLUME;
925 		md->next = AUDIO_MIXER_LAST;
926 		goto mute;
927 	case ARCOFI_PORT_AUDIO_OUT_MUTE:
928 		md->type = AUDIO_MIXER_ENUM;
929 		md->mixer_class = ARCOFI_CLASS_OUTPUT;
930 		md->prev = ARCOFI_PORT_AUDIO_OUT_VOLUME;
931 		md->next = AUDIO_MIXER_LAST;
932 		goto mute;
933 	case ARCOFI_PORT_AUDIO_SPKR_MUTE:
934 		md->type = AUDIO_MIXER_ENUM;
935 		md->mixer_class = ARCOFI_CLASS_OUTPUT;
936 		md->prev = ARCOFI_PORT_AUDIO_SPKR_VOLUME;
937 		md->next = AUDIO_MIXER_LAST;
938 		/* goto mute; */
939 mute:
940 		strlcpy(md->label.name, AudioNmute, sizeof md->label.name);
941 		md->un.e.num_mem = 2;
942 		strlcpy(md->un.e.member[0].label.name, AudioNoff,
943 		    sizeof md->un.e.member[0].label.name);
944 		md->un.e.member[0].ord = 0;
945 		strlcpy(md->un.e.member[1].label.name, AudioNon,
946 		    sizeof md->un.e.member[1].label.name);
947 		md->un.e.member[1].ord = 1;
948 		break;
949 
950 	/* classes */
951 	case ARCOFI_CLASS_INPUT:
952 		md->type = AUDIO_MIXER_CLASS;
953 		md->mixer_class = ARCOFI_CLASS_INPUT;
954 		md->prev = AUDIO_MIXER_LAST;
955 		md->next = AUDIO_MIXER_LAST;
956 		strlcpy(md->label.name, AudioCinputs,
957 		    sizeof md->label.name);
958 		break;
959 	case ARCOFI_CLASS_OUTPUT:
960 		md->type = AUDIO_MIXER_CLASS;
961 		md->mixer_class = ARCOFI_CLASS_OUTPUT;
962 		md->prev = AUDIO_MIXER_LAST;
963 		md->next = AUDIO_MIXER_LAST;
964 		strlcpy(md->label.name, AudioCoutputs,
965 		    sizeof md->label.name);
966 		break;
967 	}
968 
969 	return 0;
970 }
971 
972 int
973 arcofi_get_props(void *v)
974 {
975 	return 0;
976 }
977 
978 int
979 arcofi_hwintr(void *v)
980 {
981 	struct arcofi_softc *sc = (struct arcofi_softc *)v;
982 	uint8_t *cur, *past;
983 	uint8_t csr, fir, data;
984 	int rc = 0;
985 
986 	csr = arcofi_read(sc, ARCOFI_CSR);
987 	if ((csr & CSR_INTR_REQUEST) == 0)
988 		return 0;
989 
990 	fir = arcofi_read(sc, ARCOFI_FIFO_IR);
991 
992 	/* receive */
993 	if (fir & FIFO_IR_EVENT(FIFO_IR_IN_HALF_EMPTY)) {
994 		rc = 1;
995 		cur = sc->sc_recv.buf;
996 		past = sc->sc_recv.past;
997 
998 		while ((arcofi_read(sc, ARCOFI_FIFO_SR) &
999 		    FIFO_SR_IN_EMPTY) == 0) {
1000 			data = arcofi_read(sc, ARCOFI_FIFO_DATA);
1001 			if (cur != NULL && cur != past) {
1002 				*cur++ = data;
1003 				if (cur == past) {
1004 					softintr_schedule(sc->sc_sih);
1005 					break;
1006 				}
1007 			}
1008 		}
1009 		sc->sc_recv.buf = cur;
1010 
1011 		if (cur == NULL || cur == past) {
1012 			/* underrun, disable further interrupts */
1013 			arcofi_write(sc, ARCOFI_FIFO_IR,
1014 			    arcofi_read(sc, ARCOFI_FIFO_IR) &
1015 			    ~FIFO_IR_ENABLE(FIFO_IR_IN_HALF_EMPTY));
1016 		}
1017 	}
1018 
1019 	/* xmit */
1020 	if (fir & FIFO_IR_EVENT(FIFO_IR_OUT_HALF_EMPTY)) {
1021 		rc = 1;
1022 		cur = sc->sc_xmit.buf;
1023 		past = sc->sc_xmit.past;
1024 		if (cur != NULL) {
1025 			while ((arcofi_read(sc, ARCOFI_FIFO_SR) &
1026 			    FIFO_SR_OUT_FULL) == 0) {
1027 				if (cur != past)
1028 					arcofi_write(sc, ARCOFI_FIFO_DATA,
1029 					    *cur++);
1030 				if (cur == past) {
1031 					softintr_schedule(sc->sc_sih);
1032 					break;
1033 				}
1034 			}
1035 		}
1036 		if (cur == NULL || cur == past) {
1037 			/* disable further interrupts */
1038 			arcofi_write(sc, ARCOFI_FIFO_IR,
1039 			    arcofi_read(sc, ARCOFI_FIFO_IR) &
1040 			    ~FIFO_IR_ENABLE(FIFO_IR_OUT_HALF_EMPTY));
1041 		}
1042 		sc->sc_xmit.buf = cur;
1043 	}
1044 
1045 	/* drain */
1046 	if (fir & FIFO_IR_EVENT(FIFO_IR_OUT_EMPTY)) {
1047 		rc = 1;
1048 		arcofi_write(sc, ARCOFI_FIFO_IR,
1049 		    arcofi_read(sc, ARCOFI_FIFO_IR) &
1050 		    ~FIFO_IR_ENABLE(FIFO_IR_OUT_EMPTY));
1051 		wakeup(&sc->sc_xmit);
1052 	}
1053 
1054 #ifdef ARCOFI_DEBUG
1055 	if (rc == 0)
1056 		printf("%s: unclaimed interrupt, csr %02x fir %02x fsr %02x\n",
1057 		    sc->sc_dev.dv_xname, csr, fir,
1058 		    arcofi_read(sc, ARCOFI_FIFO_SR));
1059 #endif
1060 
1061 	return rc;
1062 }
1063 
1064 void
1065 arcofi_swintr(void *v)
1066 {
1067 	struct arcofi_softc *sc = (struct arcofi_softc *)v;
1068 	int action;
1069 
1070 	action = 0;
1071 	mtx_enter(&audio_lock);
1072 	if (sc->sc_recv.buf != NULL && sc->sc_recv.buf == sc->sc_recv.past)
1073 		action |= AUMODE_RECORD;
1074 	if (sc->sc_xmit.buf != NULL && sc->sc_xmit.buf == sc->sc_xmit.past)
1075 		action |= AUMODE_PLAY;
1076 
1077 	if (action & AUMODE_RECORD) {
1078 		if (sc->sc_recv.cb)
1079 			sc->sc_recv.cb(sc->sc_recv.cbarg);
1080 	}
1081 	if (action & AUMODE_PLAY) {
1082 		if (sc->sc_xmit.cb)
1083 			sc->sc_xmit.cb(sc->sc_xmit.cbarg);
1084 	}
1085 	mtx_leave(&audio_lock);
1086 }
1087 
1088 int
1089 arcofi_cmd(struct arcofi_softc *sc, uint8_t cmd, const uint8_t *data)
1090 {
1091 	size_t len;
1092 	uint8_t csr;
1093 	int cnt;
1094 	static const uint8_t cmdlen[] = {
1095 	    [SOP_0] = 4,
1096 	    [COP_1] = 4,
1097 	    [COP_2] = 2,
1098 	    [COP_3] = 2,
1099 	    [SOP_4] = 1,
1100 	    [SOP_5] = 1,
1101 	    [SOP_6] = 1,
1102 	    [SOP_7] = 1,
1103 	    [COP_8] = 2,
1104 	    [COP_9] = 4,
1105 	    [COP_A] = 8,
1106 	    [COP_B] = 2,
1107 	    [COP_C] = 8,
1108 	    [COP_D] = 4,
1109 	    [COP_E] = 4
1110 	};
1111 
1112 	/*
1113 	 * Compute command length.
1114 	 */
1115 	if (cmd >= nitems(cmdlen))
1116 		return EINVAL;
1117 	len = cmdlen[cmd];
1118 
1119 	mtx_enter(&audio_lock);
1120 
1121 	/*
1122 	 * Disable all FIFO processing.
1123 	 */
1124 	csr = arcofi_read(sc, ARCOFI_CSR);
1125 	arcofi_write(sc, ARCOFI_CSR,
1126 	    csr & ~(CSR_DATA_FIFO_ENABLE | CSR_CTRL_FIFO_ENABLE));
1127 
1128 	/*
1129 	 * Fill the FIFO with the command bytes.
1130 	 */
1131 	arcofi_write(sc, ARCOFI_FIFO_CTRL, CMDR_PU | CMDR_WRITE | cmd);
1132 	for (; len != 0; len--)
1133 		arcofi_write(sc, ARCOFI_FIFO_CTRL, *data++);
1134 
1135 	/*
1136 	 * Enable command processing.
1137 	 */
1138 	arcofi_write(sc, ARCOFI_CSR,
1139 	    (csr & ~CSR_DATA_FIFO_ENABLE) | CSR_CTRL_FIFO_ENABLE);
1140 
1141 	/*
1142 	 * Wait for the command FIFO to be empty.
1143 	 */
1144 	cnt = 100;
1145 	while ((arcofi_read(sc, ARCOFI_FIFO_SR) & FIFO_SR_CTRL_EMPTY) == 0) {
1146 		if (cnt-- == 0) {
1147 			mtx_leave(&audio_lock);
1148 			return EBUSY;
1149 		}
1150 		delay(10);
1151 	}
1152 
1153 	arcofi_write(sc, ARCOFI_CSR, csr);
1154 
1155 	mtx_leave(&audio_lock);
1156 	return 0;
1157 }
1158 
1159 void
1160 arcofi_attach(struct arcofi_softc *sc, const char *version)
1161 {
1162 	int rc;
1163 	uint8_t cmd[4];
1164 
1165 	/*
1166 	 * Reset logic.
1167 	 */
1168 	arcofi_write(sc, ARCOFI_ID, 0);
1169 	delay(100000);
1170 	arcofi_write(sc, ARCOFI_CSR, 0);
1171 
1172 	/*
1173 	 * Initialize the chip to default settings (8 bit, u-Law).
1174 	 */
1175 	sc->sc_active.cr3 =
1176 	    arcofi_portmask_to_cr3(AUDIO_SPEAKER) | CR3_OPMODE_NORMAL;
1177 	sc->sc_active.cr4 = CR4_TM | CR4_ULAW;
1178 	sc->sc_active.gr_idx = sc->sc_active.gx_idx = 1 + NEGATIVE_GAINS;
1179 	sc->sc_active.output_mute = 0;
1180 	bcopy(&sc->sc_active, &sc->sc_shadow, sizeof(sc->sc_active));
1181 
1182 	/* clear CRAM */
1183 	cmd[0] = CR1_IDR;
1184 	if ((rc = arcofi_cmd(sc, SOP_4, cmd)) != 0)
1185 		goto error;
1186 	delay(1000);
1187 
1188 	/* set gain values before enabling them in CR1 */
1189 	cmd[0] = arcofi_gains[sc->sc_active.gr_idx] >> 8;
1190 	cmd[1] = arcofi_gains[sc->sc_active.gr_idx];
1191 	if ((rc = arcofi_cmd(sc, COP_2, cmd)) != 0)
1192 		goto error;
1193 	/* same value for gx... */
1194 	if ((rc = arcofi_cmd(sc, COP_B, cmd)) != 0)
1195 		goto error;
1196 
1197 	/* set all CR registers at once */
1198 	cmd[0] = sc->sc_active.cr4;
1199 	cmd[1] = sc->sc_active.cr3;
1200 	cmd[2] = CR2_SD | CR2_SC | CR2_SB | CR2_SA | CR2_ELS | CR2_AM | CR2_EFC;
1201 	cmd[3] = CR1_GR | CR1_GX;
1202 	if ((rc = arcofi_cmd(sc, SOP_0, cmd)) != 0)
1203 		goto error;
1204 
1205 	arcofi_write(sc, ARCOFI_FIFO_IR, 0);
1206 	arcofi_write(sc, ARCOFI_CSR, CSR_INTR_ENABLE);
1207 
1208 	strlcpy(sc->sc_audio_device.name, arcofi_cd.cd_name,
1209 	    sizeof(sc->sc_audio_device.name));
1210 	strlcpy(sc->sc_audio_device.version, version,
1211 	    sizeof(sc->sc_audio_device.version));
1212 	strlcpy(sc->sc_audio_device.config, sc->sc_dev.dv_xname,
1213 	    sizeof(sc->sc_audio_device.config));
1214 
1215 	audio_attach_mi(&arcofi_hw_if, sc, &sc->sc_dev);
1216 	return;
1217 
1218 error:
1219 	arcofi_write(sc, ARCOFI_ID, 0);
1220 	printf("%s: command failed, error %d\n", __func__, rc);
1221 }
1222