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