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