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