Home | History | Annotate | Line # | Download | only in ic
arcofi.c revision 1.1.28.2
      1 /*	$NetBSD: arcofi.c,v 1.1.28.2 2019/04/21 06:55:34 isaki 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_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 
    199 static int	arcofi_open(void *, int);
    200 static void	arcofi_close(void *);
    201 static int	arcofi_query_format(void *, audio_format_query_t *);
    202 static int	arcofi_set_format(void *, int,
    203 		    const audio_params_t *, const audio_params_t *,
    204 		    audio_filter_reg_t *, audio_filter_reg_t *);
    205 static int	arcofi_round_blocksize(void *, int, int,
    206 		    const audio_params_t *);
    207 static int	arcofi_commit_settings(void *);
    208 static int	arcofi_start_output(void *, void *, int, void (*)(void *),
    209 		    void *);
    210 static int	arcofi_start_input(void *, void *, int, void (*)(void *),
    211 		    void *);
    212 static int	arcofi_halt_output(void *);
    213 static int	arcofi_halt_input(void *);
    214 static int	arcofi_getdev(void *, struct audio_device *);
    215 static int	arcofi_set_port(void *, mixer_ctrl_t *);
    216 static int	arcofi_get_port(void *, mixer_ctrl_t *);
    217 static int	arcofi_query_devinfo(void *, mixer_devinfo_t *);
    218 static int	arcofi_get_props(void *);
    219 static void	arcofi_get_locks(void *, kmutex_t **, kmutex_t **);
    220 
    221 static const struct audio_hw_if arcofi_hw_if = {
    222 	.open		  = arcofi_open,
    223 	.close		  = arcofi_close,
    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 	.setfd		  = NULL,
    235 	.set_port	  = arcofi_set_port,
    236 	.get_port	  = arcofi_get_port,
    237 	.query_devinfo	  = arcofi_query_devinfo,
    238 	.allocm		  = NULL,
    239 	.freem		  = NULL,
    240 	.round_buffersize = NULL,
    241 	.mappage	  = NULL,
    242 	.get_props	  = arcofi_get_props,
    243 	.trigger_output	  = NULL,
    244 	.trigger_input	  = NULL,
    245 	.dev_ioctl	  = NULL,
    246 	.get_locks	  = arcofi_get_locks,
    247 };
    248 
    249 #define ARCOFI_FORMAT(prio, enc, prec) \
    250 	{ \
    251 		.mode		= AUMODE_PLAY | AUMODE_RECORD, \
    252 		.priority	= (prio), \
    253 		.encoding	= (enc), \
    254 		.validbits	= (prec), \
    255 		.precision	= (prec), \
    256 		.channels	= 1, \
    257 		.channel_mask	= AUFMT_MONAURAL, \
    258 		.frequency_type	= 1, \
    259 		.frequency	= { 8000 }, \
    260 	}
    261 static const struct audio_format arcofi_formats[] = {
    262 	/*
    263 	 * 8-bit u-Law and A-Law are native.
    264 	 */
    265 	ARCOFI_FORMAT(1, AUDIO_ENCODING_ULAW,        8),
    266 	ARCOFI_FORMAT(0, AUDIO_ENCODING_ALAW,        8),
    267 	/*
    268 	 * 16-bit slinear big-endian is native.
    269 	 * But it's hard to use due to hardware restrictions.
    270 	 */
    271 	ARCOFI_FORMAT(0, AUDIO_ENCODING_SLINEAR_BE, 16),
    272 };
    273 #define ARCOFI_NFORMATS  __arraycount(arcofi_formats)
    274 
    275 /* mixer items */
    276 #define	ARCOFI_PORT_AUDIO_IN_VOLUME	0	/* line in volume (GR) */
    277 #define	ARCOFI_PORT_AUDIO_OUT_VOLUME	1	/* line out volume (GX) */
    278 #define	ARCOFI_PORT_AUDIO_SPKR_VOLUME	2	/* speaker volume (GX) */
    279 #define	ARCOFI_PORT_AUDIO_IN_MUTE	3	/* line in mute (MIC) */
    280 #define	ARCOFI_PORT_AUDIO_OUT_MUTE	4	/* line out mute (H out) */
    281 #define	ARCOFI_PORT_AUDIO_SPKR_MUTE	5	/* line in mute (LS out) */
    282 /* mixer classes */
    283 #define	ARCOFI_CLASS_INPUT		6
    284 #define	ARCOFI_CLASS_OUTPUT		7
    285 
    286 /*
    287  * Gain programming formulae are a complete mystery to me, and of course
    288  * no two chips are compatible - not even the PSB 2163 and PSB 2165
    289  * later ARCOFI chips, from the same manufacturer as the PSB 2160!
    290  *
    291  * Of course, the PSB 2160 datasheet does not give any set of values.
    292  * The following table is taken from the HP-UX audio driver (audio_shared.o
    293  * private_audio_gain_tab).
    294  */
    295 
    296 #define	NEGATIVE_GAINS	60
    297 #define	POSITIVE_GAINS	14
    298 static const uint16_t arcofi_gains[1 + NEGATIVE_GAINS + 1 + POSITIVE_GAINS] = {
    299 	/* minus infinity */
    300 	0x0988,
    301 
    302 	0xf8b8, 0xf8b8, 0xf8b8, 0xf8b8, 0x099f, 0x099f, 0x099f, 0x099f,
    303 	0x09af, 0x09af, 0x09af, 0x09cf, 0x09cf, 0x09cf, 0xf8a9, 0xf83a,
    304 	0xf83a, 0xf82b, 0xf82d, 0xf8a3, 0xf8b2, 0xf8a1, 0xe8aa, 0xe84b,
    305 	0xe89e, 0xe8d3, 0xe891, 0xe8b1, 0xd8aa, 0xd8cb, 0xd8a6, 0xd8b3,
    306 	0xd842, 0xd8b1, 0xc8aa, 0xc8bb, 0xc888, 0xc853, 0xc852, 0xc8b1,
    307 	0xb8aa, 0xb8ab, 0xb896, 0xb892, 0xb842, 0xb8b1, 0xa8aa, 0xa8bb,
    308 	0x199f, 0x195b, 0x29c1, 0x2923, 0x29aa, 0x392b, 0xf998, 0xb988,
    309 	0x1aac, 0x3aa1, 0xbaa1, 0xbb88,
    310 
    311 	/* 0 */
    312 	0x8888,
    313 
    314 	0xd388, 0x5288, 0xb1a1, 0x31a1, 0x1192, 0x11d0, 0x30c0, 0x2050,
    315 	0x1021, 0x1020, 0x1000, 0x0001, 0x0010, 0x0000
    316 };
    317 
    318 static int
    319 arcofi_open(void *v, int flags)
    320 {
    321 	struct arcofi_softc *sc = (struct arcofi_softc *)v;
    322 
    323 	if (sc->sc_open)
    324 		return EBUSY;
    325 	sc->sc_open = 1;
    326 	KASSERT(sc->sc_mode == 0);
    327 
    328 	return 0;
    329 }
    330 
    331 static void
    332 arcofi_close(void *v)
    333 {
    334 	struct arcofi_softc *sc = (struct arcofi_softc *)v;
    335 
    336 	sc->sc_open = 0;
    337 }
    338 
    339 static int
    340 arcofi_query_format(void *v, audio_format_query_t *afp)
    341 {
    342 
    343 	return audio_query_format(arcofi_formats, ARCOFI_NFORMATS, afp);
    344 }
    345 
    346 static int
    347 arcofi_set_format(void *handle, int setmode,
    348     const audio_params_t *play, const audio_params_t *rec,
    349     audio_filter_reg_t *pfil, audio_filter_reg_t *rfil)
    350 {
    351 	struct arcofi_softc *sc;
    352 
    353 	sc = handle;
    354 
    355 	if ((setmode & AUMODE_PLAY)) {
    356 		switch (play->encoding) {
    357 		case AUDIO_ENCODING_ULAW:
    358 			pfil->codec = audio_internal_to_mulaw;
    359 			break;
    360 		case AUDIO_ENCODING_ALAW:
    361 			pfil->codec = audio_internal_to_alaw;
    362 			break;
    363 		}
    364 	}
    365 	if ((setmode & AUMODE_RECORD)) {
    366 		switch (rec->encoding) {
    367 		case AUDIO_ENCODING_ULAW:
    368 			rfil->codec = audio_mulaw_to_internal;
    369 			break;
    370 		case AUDIO_ENCODING_ALAW:
    371 			rfil->codec = audio_alaw_to_internal;
    372 			break;
    373 		}
    374 	}
    375 
    376 	/* *play and *rec are identical because !AUDIO_PROP_INDEPENDENT */
    377 
    378 	if (play->precision == 8) {
    379 		if (play->encoding == AUDIO_ENCODING_ULAW)
    380 			sc->sc_shadow.cr4 |= CR4_ULAW;
    381 		else
    382 			sc->sc_shadow.cr4 &= ~CR4_ULAW;
    383 		sc->sc_shadow.cr3 =
    384 		    (sc->sc_shadow.cr3 & ~CR3_OPMODE_MASK) |
    385 		    CR3_OPMODE_NORMAL;
    386 	} else {
    387 		sc->sc_shadow.cr3 =
    388 		    (sc->sc_shadow.cr3 & ~CR3_OPMODE_MASK) |
    389 		    CR3_OPMODE_LINEAR;
    390 	}
    391 
    392 	return 0;
    393 }
    394 
    395 static int
    396 arcofi_round_blocksize(void *handle, int block, int mode,
    397     const audio_params_t *param)
    398 {
    399 
    400 	/*
    401 	 * Round the size up to a multiple of half the FIFO, to favour
    402 	 * smooth interrupt operation.
    403 	 */
    404 	return roundup(block, ARCOFI_FIFO_SIZE / 2);
    405 }
    406 
    407 static int
    408 arcofi_commit_settings(void *v)
    409 {
    410 	struct arcofi_softc *sc = (struct arcofi_softc *)v;
    411 	int rc;
    412 	uint8_t cmd[2], csr, ocsr;
    413 
    414 #ifdef ARCOFI_DEBUG
    415 	printf("%s: %s, gr %04x gx %04x cr3 %02x cr4 %02x mute %d\n",
    416 	    device_xname(sc->sc_dev), __func__,
    417 	    arcofi_gains[sc->sc_shadow.gr_idx],
    418 	    arcofi_gains[sc->sc_shadow.gx_idx],
    419 	    sc->sc_shadow.cr3, sc->sc_shadow.cr4, sc->sc_shadow.output_mute);
    420 #endif
    421 
    422 	if (memcmp(&sc->sc_active, &sc->sc_shadow, sizeof(sc->sc_active)) == 0)
    423 		return 0;
    424 
    425 	mutex_spin_enter(&sc->sc_intr_lock);
    426 
    427 	if (sc->sc_active.gr_idx != sc->sc_shadow.gr_idx) {
    428 		cmd[0] = arcofi_gains[sc->sc_shadow.gr_idx] >> 8;
    429 		cmd[1] = arcofi_gains[sc->sc_shadow.gr_idx];
    430 		if ((rc = arcofi_cmd(sc, COP_2, cmd)) != 0)
    431 			goto error;
    432 		sc->sc_active.gr_idx = sc->sc_shadow.gr_idx;
    433 	}
    434 
    435 	if (sc->sc_active.gx_idx != sc->sc_shadow.gx_idx ||
    436 	    sc->sc_active.output_mute != sc->sc_shadow.output_mute) {
    437 		if (sc->sc_shadow.output_mute) {
    438 			cmd[0] = arcofi_gains[0] >> 8;
    439 			cmd[1] = arcofi_gains[0];
    440 		} else {
    441 			cmd[0] = arcofi_gains[sc->sc_shadow.gx_idx] >> 8;
    442 			cmd[1] = arcofi_gains[sc->sc_shadow.gx_idx];
    443 		}
    444 		if ((rc = arcofi_cmd(sc, COP_B, cmd)) != 0)
    445 			goto error;
    446 		sc->sc_active.gx_idx = sc->sc_shadow.gx_idx;
    447 		sc->sc_active.output_mute = sc->sc_shadow.output_mute;
    448 	}
    449 
    450 	if (sc->sc_active.cr3 != sc->sc_shadow.cr3) {
    451 		cmd[0] = sc->sc_shadow.cr3;
    452 		if ((rc = arcofi_cmd(sc, SOP_6, cmd)) != 0)
    453 			goto error;
    454 		sc->sc_active.cr3 = sc->sc_shadow.cr3;
    455 
    456 		ocsr = arcofi_read(sc, ARCOFI_CSR);
    457 		if ((sc->sc_active.cr3 & CR3_OPMODE_MASK) != CR3_OPMODE_NORMAL)
    458 			csr = ocsr | CSR_WIDTH_16;
    459 		else
    460 			csr = ocsr & ~CSR_WIDTH_16;
    461 		if (csr != ocsr)
    462 			arcofi_write(sc, ARCOFI_CSR, csr);
    463 	}
    464 
    465 	if (sc->sc_active.cr4 != sc->sc_shadow.cr4) {
    466 		cmd[0] = sc->sc_shadow.cr4;
    467 		if ((rc = arcofi_cmd(sc, SOP_7, cmd)) != 0)
    468 			goto error;
    469 		sc->sc_active.cr4 = sc->sc_shadow.cr4;
    470 	}
    471 
    472 	rc = 0;
    473  error:
    474 	mutex_spin_exit(&sc->sc_intr_lock);
    475 	return rc;
    476 }
    477 
    478 /*
    479  * Take it out of the queue as much as possible.
    480  */
    481 static int
    482 arcofi_recv_data(struct arcofi_softc *sc)
    483 {
    484 	uint8_t *cur;
    485 	uint8_t *past;
    486 
    487 	cur = sc->sc_recv.buf;
    488 	past = sc->sc_recv.past;
    489 
    490 	while (cur != past &&
    491 	    (arcofi_read(sc, ARCOFI_FIFO_SR) & FIFO_SR_IN_EMPTY) == 0) {
    492 		*cur++ = arcofi_read(sc, ARCOFI_FIFO_DATA);
    493 	}
    494 	sc->sc_recv.buf = cur;
    495 
    496 	return past - cur;
    497 }
    498 
    499 /*
    500  * Fill the queue as much as possible.
    501  */
    502 static int
    503 arcofi_xmit_data(struct arcofi_softc *sc)
    504 {
    505 	uint8_t *cur;
    506 	uint8_t *past;
    507 
    508 	cur = sc->sc_xmit.buf;
    509 	past = sc->sc_xmit.past;
    510 
    511 	while (cur != past &&
    512 	    (arcofi_read(sc, ARCOFI_FIFO_SR) & FIFO_SR_OUT_FULL) == 0) {
    513 		arcofi_write(sc, ARCOFI_FIFO_DATA, *cur++);
    514 	}
    515 	sc->sc_xmit.buf = cur;
    516 
    517 	return past - cur;
    518 }
    519 
    520 static int
    521 arcofi_start_input(void *v, void *rbuf, int rsz, void (*cb)(void *),
    522     void *cbarg)
    523 {
    524 	struct arcofi_softc *sc = (struct arcofi_softc *)v;
    525 
    526 #ifdef ARCOFI_DEBUG
    527 	printf("%s: %s, mode %d\n",
    528 	    device_xname(sc->sc_dev), __func__, sc->sc_mode);
    529 #endif
    530 
    531 	/* enable data FIFO if becoming active */
    532 	if (sc->sc_mode == 0)
    533 		arcofi_write(sc, ARCOFI_CSR,
    534 		    arcofi_read(sc, ARCOFI_CSR) | CSR_DATA_FIFO_ENABLE);
    535 	sc->sc_mode |= AUMODE_RECORD;
    536 
    537 	sc->sc_recv.buf = (uint8_t *)rbuf;
    538 	sc->sc_recv.past = (uint8_t *)rbuf + rsz;
    539 	sc->sc_recv.cb = cb;
    540 	sc->sc_recv.cbarg = cbarg;
    541 
    542 	/* enable input FIFO interrupts */
    543 	arcofi_write(sc, ARCOFI_FIFO_IR, arcofi_read(sc, ARCOFI_FIFO_IR) |
    544 	    FIFO_IR_ENABLE(FIFO_IR_IN_HALF_EMPTY));
    545 
    546 	return 0;
    547 }
    548 
    549 static int
    550 arcofi_start_output(void *v, void *wbuf, int wsz, void (*cb)(void *),
    551     void *cbarg)
    552 {
    553 	struct arcofi_softc *sc = (struct arcofi_softc *)v;
    554 
    555 #ifdef ARCOFI_DEBUG
    556 	printf("%s: %s, mode %d\n",
    557 	    device_xname(sc->sc_dev), __func__, sc->sc_mode);
    558 #endif
    559 
    560 	/* enable data FIFO if becoming active */
    561 	if (sc->sc_mode == 0)
    562 		arcofi_write(sc, ARCOFI_CSR,
    563 		    arcofi_read(sc, ARCOFI_CSR) | CSR_DATA_FIFO_ENABLE);
    564 	sc->sc_mode |= AUMODE_PLAY;
    565 
    566 	sc->sc_xmit.buf = (uint8_t *)wbuf;
    567 	sc->sc_xmit.past = (uint8_t *)wbuf + wsz;
    568 	sc->sc_xmit.cb = cb;
    569 	sc->sc_xmit.cbarg = cbarg;
    570 
    571 	/* enable output FIFO interrupts */
    572 	arcofi_write(sc, ARCOFI_FIFO_IR, arcofi_read(sc, ARCOFI_FIFO_IR) |
    573 	    FIFO_IR_ENABLE(FIFO_IR_OUT_HALF_EMPTY));
    574 
    575 	return 0;
    576 }
    577 
    578 static int
    579 arcofi_halt_input(void *v)
    580 {
    581 	struct arcofi_softc *sc = (struct arcofi_softc *)v;
    582 
    583 #ifdef ARCOFI_DEBUG
    584 	printf("%s: %s, mode %d\n",
    585 	    device_xname(sc->sc_dev), __func__, sc->sc_mode);
    586 #endif
    587 
    588 	/* disable input FIFO interrupts */
    589 	arcofi_write(sc, ARCOFI_FIFO_IR, arcofi_read(sc, ARCOFI_FIFO_IR) &
    590 	    ~FIFO_IR_ENABLE(FIFO_IR_IN_HALF_EMPTY));
    591 	/* disable data FIFO if becoming idle */
    592 	sc->sc_mode &= ~AUMODE_RECORD;
    593 	if (sc->sc_mode == 0)
    594 		arcofi_write(sc, ARCOFI_CSR,
    595 		    arcofi_read(sc, ARCOFI_CSR) & ~CSR_DATA_FIFO_ENABLE);
    596 
    597 	return 0;
    598 }
    599 
    600 static int
    601 arcofi_halt_output(void *v)
    602 {
    603 	struct arcofi_softc *sc = (struct arcofi_softc *)v;
    604 
    605 #ifdef ARCOFI_DEBUG
    606 	printf("%s: %s, mode %d\n",
    607 	    device_xname(sc->sc_dev), __func__, sc->sc_mode);
    608 #endif
    609 
    610 	/* disable output FIFO interrupts */
    611 	arcofi_write(sc, ARCOFI_FIFO_IR, arcofi_read(sc, ARCOFI_FIFO_IR) &
    612 	    ~FIFO_IR_ENABLE(FIFO_IR_OUT_HALF_EMPTY));
    613 	/* disable data FIFO if becoming idle */
    614 	sc->sc_mode &= ~AUMODE_PLAY;
    615 	if (sc->sc_mode == 0)
    616 		arcofi_write(sc, ARCOFI_CSR,
    617 		    arcofi_read(sc, ARCOFI_CSR) & ~CSR_DATA_FIFO_ENABLE);
    618 
    619 	return 0;
    620 }
    621 
    622 static int
    623 arcofi_getdev(void *v, struct audio_device *ad)
    624 {
    625 	struct arcofi_softc *sc = (struct arcofi_softc *)v;
    626 
    627 	*ad = sc->sc_audio_device;
    628 	return 0;
    629 }
    630 
    631 /*
    632  * Convert gain table index to AUDIO_MIN_GAIN..AUDIO_MAX_GAIN scale.
    633  */
    634 static int
    635 arcofi_gain_to_mi(uint idx)
    636 {
    637 
    638 	if (idx == 0)
    639 		return AUDIO_MIN_GAIN;
    640 	if (idx == __arraycount(arcofi_gains) - 1)
    641 		return AUDIO_MAX_GAIN;
    642 
    643 	return ((idx - 1) * (AUDIO_MAX_GAIN - AUDIO_MIN_GAIN)) /
    644 	    (__arraycount(arcofi_gains) - 1) + AUDIO_MIN_GAIN + 1;
    645 }
    646 
    647 /*
    648  * Convert AUDIO_MIN_GAIN..AUDIO_MAX_GAIN scale to gain table index.
    649  */
    650 static uint
    651 arcofi_mi_to_gain(int lvl)
    652 {
    653 
    654 	if (lvl <= AUDIO_MIN_GAIN)
    655 		return 0;
    656 	if (lvl >= AUDIO_MAX_GAIN)
    657 		return __arraycount(arcofi_gains) - 1;
    658 
    659 	return ((lvl - AUDIO_MIN_GAIN - 1) * (__arraycount(arcofi_gains) - 1)) /
    660 	    (AUDIO_MAX_GAIN - AUDIO_MIN_GAIN);
    661 }
    662 
    663 /*
    664  * The following routines rely upon this...
    665  */
    666 #if (AUDIO_SPEAKER == AUDIO_LINE_IN) || (AUDIO_LINE_OUT == AUDIO_LINE_IN) || \
    667     (AUDIO_SPEAKER == AUDIO_LINE_OUT)
    668 #error Please rework the cr3 handling logic.
    669 #endif
    670 
    671 /*
    672  * The mapping between the available inputs and outputs, and CR3, is as
    673  * follows:
    674  * - the `line in' connector is the `MIC' input.
    675  * - the `line out' connector is the `H out' (heaphones) output.
    676  * - the internal `speaker' is the `LS out' (loudspeaker) output.
    677  *
    678  * Each of these can be enabled or disabled indepently, except for
    679  * MIC enabled with H out and LS out disabled, which is not allowed
    680  * by the chip (and makes no sense for a chip which was intended to
    681  * be used in phones, not voice recorders); we cheat by keeping one
    682  * output source enabled, but with the output gain forced to minus
    683  * infinity to mute it.
    684  *
    685  * The truth table is thus:
    686  *
    687  *	MIC	LS out	H out	AFEC
    688  *	off	off	off	POR
    689  *	off	off	on	MUTE
    690  *	off	on	off	LH1
    691  *	off	on	on	LH3, X input enabled
    692  *	on	off	off	RDY, GX forced to minus infinity
    693  *	on	off	on	RDY
    694  *	on	on	off	LH2
    695  *	on	on	on	LH3
    696  */
    697 
    698 /*
    699  * Convert logical port enable settings to a valid CR3 value.
    700  */
    701 static uint
    702 arcofi_portmask_to_cr3(int mask)
    703 {
    704 
    705 	switch (mask) {
    706 	default:
    707 	case 0:
    708 		return CR3_MIC_G_17 | CR3_AFEC_POR;
    709 	case AUDIO_LINE_OUT:
    710 		return CR3_MIC_G_17 | CR3_AFEC_MUTE;
    711 	case AUDIO_SPEAKER:
    712 		return CR3_MIC_G_17 | CR3_AFEC_LH1;
    713 	case AUDIO_SPEAKER | AUDIO_LINE_OUT:
    714 		return CR3_MIC_X_INPUT | CR3_AFEC_LH3;
    715 	case AUDIO_LINE_IN:
    716 		/* since we can't do this, just... */
    717 		/* FALLTHROUGH */
    718 	case AUDIO_LINE_IN | AUDIO_LINE_OUT:
    719 		return CR3_MIC_G_17 | CR3_AFEC_RDY;
    720 	case AUDIO_LINE_IN | AUDIO_SPEAKER:
    721 		return CR3_MIC_G_17 | CR3_AFEC_LH2;
    722 	case AUDIO_LINE_IN | AUDIO_SPEAKER | AUDIO_LINE_OUT:
    723 		return CR3_MIC_G_17 | CR3_AFEC_LH3;
    724 	}
    725 }
    726 
    727 /*
    728  * Convert CR3 to an enabled ports mask.
    729  */
    730 static int
    731 arcofi_cr3_to_portmask(uint cr3, int output_mute)
    732 {
    733 
    734 	switch (cr3 & CR3_AFEC_MASK) {
    735 	default:
    736 	case CR3_AFEC_POR:
    737 		return 0;
    738 	case CR3_AFEC_RDY:
    739 		return output_mute ?
    740 		    AUDIO_LINE_IN : AUDIO_LINE_IN | AUDIO_LINE_OUT;
    741 	case CR3_AFEC_HFS:
    742 	case CR3_AFEC_LH1:
    743 		return AUDIO_SPEAKER;
    744 	case CR3_AFEC_LH2:
    745 		return AUDIO_LINE_IN | AUDIO_SPEAKER;
    746 	case CR3_AFEC_LH3:
    747 		if ((cr3 & CR3_MIC_G_MASK) == CR3_MIC_X_INPUT)
    748 			return AUDIO_SPEAKER | AUDIO_LINE_OUT;
    749 		else
    750 			return AUDIO_LINE_IN | AUDIO_SPEAKER | AUDIO_LINE_OUT;
    751 	case CR3_AFEC_MUTE:
    752 		return AUDIO_LINE_OUT;
    753 	}
    754 }
    755 
    756 static int
    757 arcofi_set_port(void *v, mixer_ctrl_t *mc)
    758 {
    759 	struct arcofi_softc *sc = (struct arcofi_softc *)v;
    760 	int portmask = 0;
    761 
    762 #ifdef ARCOFI_DEBUG
    763 	printf("%s: %s, mode %d\n",
    764 	    device_xname(sc->sc_dev), __func__, sc->sc_mode);
    765 #endif
    766 	/* check for proper type */
    767 	switch (mc->dev) {
    768 	/* volume settings */
    769 	case ARCOFI_PORT_AUDIO_IN_VOLUME:
    770 	case ARCOFI_PORT_AUDIO_OUT_VOLUME:
    771 	case ARCOFI_PORT_AUDIO_SPKR_VOLUME:
    772 		if (mc->un.value.num_channels != 1)
    773 			return EINVAL;
    774 		break;
    775 	/* mute settings */
    776 	case ARCOFI_PORT_AUDIO_IN_MUTE:
    777 	case ARCOFI_PORT_AUDIO_OUT_MUTE:
    778 	case ARCOFI_PORT_AUDIO_SPKR_MUTE:
    779 		if (mc->type != AUDIO_MIXER_ENUM)
    780 			return EINVAL;
    781 		portmask = arcofi_cr3_to_portmask(sc->sc_shadow.cr3,
    782 		    sc->sc_shadow.output_mute);
    783 #ifdef ARCOFI_DEBUG
    784 		printf("%s: %s cr3 %02x -> mask %02x\n",
    785 		    device_xname(sc->sc_dev), __func__,
    786 		    sc->sc_shadow.cr3, portmask);
    787 #endif
    788 		break;
    789 	default:
    790 		return EINVAL;
    791 	}
    792 
    793 	switch (mc->dev) {
    794 	/* volume settings */
    795 	case ARCOFI_PORT_AUDIO_IN_VOLUME:
    796 		sc->sc_shadow.gr_idx =
    797 		    arcofi_mi_to_gain(mc->un.value.level[AUDIO_MIXER_LEVEL_MONO]);
    798 		return 0;
    799 	case ARCOFI_PORT_AUDIO_OUT_VOLUME:
    800 	case ARCOFI_PORT_AUDIO_SPKR_VOLUME:
    801 		sc->sc_shadow.gx_idx =
    802 		    arcofi_mi_to_gain(mc->un.value.level[AUDIO_MIXER_LEVEL_MONO]);
    803 		return 0;
    804 
    805 	/* mute settings */
    806 	case ARCOFI_PORT_AUDIO_IN_MUTE:
    807 		if (mc->un.ord)
    808 			portmask &= ~AUDIO_LINE_IN;
    809 		else
    810 			portmask |= AUDIO_LINE_IN;
    811 		break;
    812 	case ARCOFI_PORT_AUDIO_OUT_MUTE:
    813 		if (mc->un.ord)
    814 			portmask &= ~AUDIO_LINE_OUT;
    815 		else
    816 			portmask |= AUDIO_LINE_OUT;
    817 		break;
    818 	case ARCOFI_PORT_AUDIO_SPKR_MUTE:
    819 		if (mc->un.ord)
    820 			portmask &= ~AUDIO_SPEAKER;
    821 		else
    822 			portmask |= AUDIO_SPEAKER;
    823 		break;
    824 	}
    825 
    826 	sc->sc_shadow.cr3 = (sc->sc_shadow.cr3 & CR3_OPMODE_MASK) |
    827 	    arcofi_portmask_to_cr3(portmask);
    828 	sc->sc_shadow.output_mute = (portmask == AUDIO_LINE_IN);
    829 #ifdef ARCOFI_DEBUG
    830 	printf("%s: %s mask %02x -> cr3 %02x m %d\n",
    831 	    device_xname(sc->sc_dev), __func__,
    832 	    portmask, sc->sc_shadow.cr3, sc->sc_shadow.output_mute);
    833 #endif
    834 
    835 	return 0;
    836 }
    837 
    838 static int
    839 arcofi_get_port(void *v, mixer_ctrl_t *mc)
    840 {
    841 	struct arcofi_softc *sc = (struct arcofi_softc *)v;
    842 	int portmask = 0;
    843 
    844 #ifdef ARCOFI_DEBUG
    845 	printf("%s: %s, mode %d\n",
    846 	    device_xname(sc->sc_dev), __func__, sc->sc_mode);
    847 #endif
    848 	/* check for proper type */
    849 	switch (mc->dev) {
    850 	/* volume settings */
    851 	case ARCOFI_PORT_AUDIO_IN_VOLUME:
    852 	case ARCOFI_PORT_AUDIO_OUT_VOLUME:
    853 	case ARCOFI_PORT_AUDIO_SPKR_VOLUME:
    854 		if (mc->un.value.num_channels != 1)
    855 			return EINVAL;
    856 		break;
    857 
    858 	/* mute settings */
    859 	case ARCOFI_PORT_AUDIO_IN_MUTE:
    860 	case ARCOFI_PORT_AUDIO_OUT_MUTE:
    861 	case ARCOFI_PORT_AUDIO_SPKR_MUTE:
    862 		if (mc->type != AUDIO_MIXER_ENUM)
    863 			return EINVAL;
    864 		portmask = arcofi_cr3_to_portmask(sc->sc_shadow.cr3,
    865 		    sc->sc_shadow.output_mute);
    866 #ifdef ARCOFI_DEBUG
    867 		printf("%s: %s cr3 %02x -> mask %02x\n",
    868 		    device_xname(sc->sc_dev), __func__,
    869 		    sc->sc_shadow.cr3, portmask);
    870 #endif
    871 		break;
    872 	default:
    873 		return EINVAL;
    874 	}
    875 
    876 	switch (mc->dev) {
    877 	/* volume settings */
    878 	case ARCOFI_PORT_AUDIO_IN_VOLUME:
    879 		mc->un.value.level[AUDIO_MIXER_LEVEL_MONO] =
    880 		    arcofi_gain_to_mi(sc->sc_shadow.gr_idx);
    881 		break;
    882 	case ARCOFI_PORT_AUDIO_OUT_VOLUME:
    883 	case ARCOFI_PORT_AUDIO_SPKR_VOLUME:
    884 		mc->un.value.level[AUDIO_MIXER_LEVEL_MONO] =
    885 		    arcofi_gain_to_mi(sc->sc_shadow.gx_idx);
    886 		break;
    887 
    888 	/* mute settings */
    889 	case ARCOFI_PORT_AUDIO_IN_MUTE:
    890 		mc->un.ord = portmask & AUDIO_LINE_IN ? 0 : 1;
    891 		break;
    892 	case ARCOFI_PORT_AUDIO_OUT_MUTE:
    893 		mc->un.ord = portmask & AUDIO_LINE_OUT ? 0 : 1;
    894 		break;
    895 	case ARCOFI_PORT_AUDIO_SPKR_MUTE:
    896 		mc->un.ord = portmask & AUDIO_SPEAKER ? 0 : 1;
    897 		break;
    898 	}
    899 
    900 	return 0;
    901 }
    902 
    903 static int
    904 arcofi_query_devinfo(void *v, mixer_devinfo_t *md)
    905 {
    906 
    907 	switch (md->index) {
    908 	default:
    909 		return ENXIO;
    910 
    911 	/* items */
    912 	case ARCOFI_PORT_AUDIO_IN_VOLUME:
    913 		md->type = AUDIO_MIXER_VALUE;
    914 		md->mixer_class = ARCOFI_CLASS_INPUT;
    915 		md->prev = AUDIO_MIXER_LAST;
    916 		md->next = ARCOFI_PORT_AUDIO_IN_MUTE;
    917 		strlcpy(md->label.name, AudioNline,
    918 		    sizeof md->label.name);
    919 		goto mono_volume;
    920 	case ARCOFI_PORT_AUDIO_OUT_VOLUME:
    921 		md->type = AUDIO_MIXER_VALUE;
    922 		md->mixer_class = ARCOFI_CLASS_OUTPUT;
    923 		md->prev = AUDIO_MIXER_LAST;
    924 		md->next = ARCOFI_PORT_AUDIO_OUT_MUTE;
    925 		strlcpy(md->label.name, AudioNline,
    926 		    sizeof md->label.name);
    927 		goto mono_volume;
    928 	case ARCOFI_PORT_AUDIO_SPKR_VOLUME:
    929 		md->type = AUDIO_MIXER_VALUE;
    930 		md->mixer_class = ARCOFI_CLASS_OUTPUT;
    931 		md->prev = AUDIO_MIXER_LAST;
    932 		md->next = ARCOFI_PORT_AUDIO_SPKR_MUTE;
    933 		strlcpy(md->label.name, AudioNspeaker,
    934 		    sizeof md->label.name);
    935 		/* goto mono_volume; */
    936  mono_volume:
    937 		md->un.v.num_channels = 1;
    938 		strlcpy(md->un.v.units.name, AudioNvolume,
    939 		    sizeof md->un.v.units.name);
    940 		break;
    941 
    942 	case ARCOFI_PORT_AUDIO_IN_MUTE:
    943 		md->type = AUDIO_MIXER_ENUM;
    944 		md->mixer_class = ARCOFI_CLASS_INPUT;
    945 		md->prev = ARCOFI_PORT_AUDIO_IN_VOLUME;
    946 		md->next = AUDIO_MIXER_LAST;
    947 		goto mute;
    948 	case ARCOFI_PORT_AUDIO_OUT_MUTE:
    949 		md->type = AUDIO_MIXER_ENUM;
    950 		md->mixer_class = ARCOFI_CLASS_OUTPUT;
    951 		md->prev = ARCOFI_PORT_AUDIO_OUT_VOLUME;
    952 		md->next = AUDIO_MIXER_LAST;
    953 		goto mute;
    954 	case ARCOFI_PORT_AUDIO_SPKR_MUTE:
    955 		md->type = AUDIO_MIXER_ENUM;
    956 		md->mixer_class = ARCOFI_CLASS_OUTPUT;
    957 		md->prev = ARCOFI_PORT_AUDIO_SPKR_VOLUME;
    958 		md->next = AUDIO_MIXER_LAST;
    959 		/* goto mute; */
    960  mute:
    961 		strlcpy(md->label.name, AudioNmute, sizeof md->label.name);
    962 		md->un.e.num_mem = 2;
    963 		strlcpy(md->un.e.member[0].label.name, AudioNoff,
    964 		    sizeof md->un.e.member[0].label.name);
    965 		md->un.e.member[0].ord = 0;
    966 		strlcpy(md->un.e.member[1].label.name, AudioNon,
    967 		    sizeof md->un.e.member[1].label.name);
    968 		md->un.e.member[1].ord = 1;
    969 		break;
    970 
    971 	/* classes */
    972 	case ARCOFI_CLASS_INPUT:
    973 		md->type = AUDIO_MIXER_CLASS;
    974 		md->mixer_class = ARCOFI_CLASS_INPUT;
    975 		md->prev = AUDIO_MIXER_LAST;
    976 		md->next = AUDIO_MIXER_LAST;
    977 		strlcpy(md->label.name, AudioCinputs,
    978 		    sizeof md->label.name);
    979 		break;
    980 	case ARCOFI_CLASS_OUTPUT:
    981 		md->type = AUDIO_MIXER_CLASS;
    982 		md->mixer_class = ARCOFI_CLASS_OUTPUT;
    983 		md->prev = AUDIO_MIXER_LAST;
    984 		md->next = AUDIO_MIXER_LAST;
    985 		strlcpy(md->label.name, AudioCoutputs,
    986 		    sizeof md->label.name);
    987 		break;
    988 	}
    989 
    990 	return 0;
    991 }
    992 
    993 static int
    994 arcofi_get_props(void *v)
    995 {
    996 
    997 	return 0;
    998 }
    999 
   1000 static void
   1001 arcofi_get_locks(void *v, kmutex_t **intr, kmutex_t **thread)
   1002 {
   1003 	struct arcofi_softc *sc = (struct arcofi_softc *)v;
   1004 
   1005 	*intr = &sc->sc_intr_lock;
   1006 	*thread = &sc->sc_lock;
   1007 }
   1008 
   1009 int
   1010 arcofi_hwintr(void *v)
   1011 {
   1012 	struct arcofi_softc *sc = (struct arcofi_softc *)v;
   1013 	uint8_t csr, fir;
   1014 	int rc = 0;
   1015 
   1016 	csr = arcofi_read(sc, ARCOFI_CSR);
   1017 	if ((csr & CSR_INTR_REQUEST) == 0)
   1018 		return 0;
   1019 
   1020 	fir = arcofi_read(sc, ARCOFI_FIFO_IR);
   1021 
   1022 	/* receive */
   1023 	if ((sc->sc_mode & AUMODE_RECORD) &&
   1024 	    (fir & FIFO_IR_EVENT(FIFO_IR_IN_HALF_EMPTY))) {
   1025 		rc = 1;
   1026 
   1027 		if (arcofi_recv_data(sc) == 0) {
   1028 			/* disable further interrupts */
   1029 			arcofi_write(sc, ARCOFI_FIFO_IR,
   1030 			    arcofi_read(sc, ARCOFI_FIFO_IR) &
   1031 			    ~FIFO_IR_ENABLE(FIFO_IR_IN_HALF_EMPTY));
   1032 
   1033 			/* callback */
   1034 			sc->sc_recv.cb(sc->sc_recv.cbarg);
   1035 		}
   1036 	}
   1037 
   1038 	/* xmit */
   1039 	if ((sc->sc_mode & AUMODE_PLAY) &&
   1040 	    (fir & FIFO_IR_EVENT(FIFO_IR_OUT_HALF_EMPTY))) {
   1041 		rc = 1;
   1042 
   1043 		if (arcofi_xmit_data(sc) == 0) {
   1044 			/* disable further interrupts */
   1045 			arcofi_write(sc, ARCOFI_FIFO_IR,
   1046 			    arcofi_read(sc, ARCOFI_FIFO_IR) &
   1047 			    ~FIFO_IR_ENABLE(FIFO_IR_OUT_HALF_EMPTY));
   1048 
   1049 			/* callback */
   1050 			sc->sc_xmit.cb(sc->sc_xmit.cbarg);
   1051 		}
   1052 	}
   1053 
   1054 #ifdef ARCOFI_DEBUG
   1055 	if (rc == 0)
   1056 		printf("%s: unclaimed interrupt, csr %02x fir %02x fsr %02x\n",
   1057 		    device_xname(sc->sc_dev), csr, fir,
   1058 		    arcofi_read(sc, ARCOFI_FIFO_SR));
   1059 #endif
   1060 
   1061 	return rc;
   1062 }
   1063 
   1064 static int
   1065 arcofi_cmd(struct arcofi_softc *sc, uint8_t cmd, const uint8_t *data)
   1066 {
   1067 	size_t len;
   1068 	uint8_t csr;
   1069 	int cnt;
   1070 	static const uint8_t cmdlen[] = {
   1071 	    [SOP_0] = 4,
   1072 	    [COP_1] = 4,
   1073 	    [COP_2] = 2,
   1074 	    [COP_3] = 2,
   1075 	    [SOP_4] = 1,
   1076 	    [SOP_5] = 1,
   1077 	    [SOP_6] = 1,
   1078 	    [SOP_7] = 1,
   1079 	    [COP_8] = 2,
   1080 	    [COP_9] = 4,
   1081 	    [COP_A] = 8,
   1082 	    [COP_B] = 2,
   1083 	    [COP_C] = 8,
   1084 	    [COP_D] = 4,
   1085 	    [COP_E] = 4
   1086 	};
   1087 
   1088 	/*
   1089 	 * Compute command length.
   1090 	 */
   1091 	if (cmd >= __arraycount(cmdlen))
   1092 		return EINVAL;
   1093 	len = cmdlen[cmd];
   1094 
   1095 	KASSERT(cold || mutex_owned(&sc->sc_intr_lock));
   1096 
   1097 	/*
   1098 	 * Disable all FIFO processing.
   1099 	 */
   1100 	csr = arcofi_read(sc, ARCOFI_CSR);
   1101 	arcofi_write(sc, ARCOFI_CSR,
   1102 	    csr & ~(CSR_DATA_FIFO_ENABLE | CSR_CTRL_FIFO_ENABLE));
   1103 
   1104 	/*
   1105 	 * Fill the FIFO with the command bytes.
   1106 	 */
   1107 	arcofi_write(sc, ARCOFI_FIFO_CTRL, CMDR_PU | CMDR_WRITE | cmd);
   1108 	for (; len != 0; len--)
   1109 		arcofi_write(sc, ARCOFI_FIFO_CTRL, *data++);
   1110 
   1111 	/*
   1112 	 * Enable command processing.
   1113 	 */
   1114 	arcofi_write(sc, ARCOFI_CSR,
   1115 	    (csr & ~CSR_DATA_FIFO_ENABLE) | CSR_CTRL_FIFO_ENABLE);
   1116 
   1117 	/*
   1118 	 * Wait for the command FIFO to be empty.
   1119 	 */
   1120 	cnt = 100;
   1121 	while ((arcofi_read(sc, ARCOFI_FIFO_SR) & FIFO_SR_CTRL_EMPTY) == 0) {
   1122 		if (cnt-- == 0) {
   1123 			return EBUSY;
   1124 		}
   1125 		delay(10);
   1126 	}
   1127 
   1128 	arcofi_write(sc, ARCOFI_CSR, csr);
   1129 
   1130 	return 0;
   1131 }
   1132 
   1133 void
   1134 arcofi_attach(struct arcofi_softc *sc, const char *versionstr)
   1135 {
   1136 	device_t self;
   1137 	int rc;
   1138 	uint8_t op, cmd[4];
   1139 
   1140 	self = sc->sc_dev;
   1141 	mutex_init(&sc->sc_lock, MUTEX_DEFAULT, IPL_NONE);
   1142 	mutex_init(&sc->sc_intr_lock, MUTEX_DEFAULT, IPL_AUDIO);
   1143 
   1144 	/*
   1145 	 * Reset logic.
   1146 	 */
   1147 	arcofi_write(sc, ARCOFI_ID, 0);
   1148 	delay(100000);
   1149 	arcofi_write(sc, ARCOFI_CSR, 0);
   1150 
   1151 	/*
   1152 	 * Initialize the chip to default settings (8 bit, u-Law).
   1153 	 */
   1154 	sc->sc_active.cr3 =
   1155 	    arcofi_portmask_to_cr3(AUDIO_SPEAKER) | CR3_OPMODE_NORMAL;
   1156 	sc->sc_active.cr4 = CR4_TM | CR4_ULAW;
   1157 	sc->sc_active.gr_idx = sc->sc_active.gx_idx = 1 + NEGATIVE_GAINS;
   1158 	sc->sc_active.output_mute = 0;
   1159 	memcpy(&sc->sc_shadow, &sc->sc_active, sizeof(sc->sc_active));
   1160 
   1161 	/* clear CRAM */
   1162 	op = SOP_4;
   1163 	cmd[0] = CR1_IDR;
   1164 	if ((rc = arcofi_cmd(sc, op, cmd)) != 0)
   1165 		goto error;
   1166 	delay(1000);
   1167 
   1168 	/* set gain values before enabling them in CR1 */
   1169 	op = COP_2;
   1170 	cmd[0] = arcofi_gains[sc->sc_active.gr_idx] >> 8;
   1171 	cmd[1] = arcofi_gains[sc->sc_active.gr_idx];
   1172 	if ((rc = arcofi_cmd(sc, op, cmd)) != 0)
   1173 		goto error;
   1174 	/* same value for gx... */
   1175 	op = COP_B;
   1176 	if ((rc = arcofi_cmd(sc, op, cmd)) != 0)
   1177 		goto error;
   1178 
   1179 	/* set all CR registers at once */
   1180 	op = SOP_0;
   1181 	cmd[0] = sc->sc_active.cr4;
   1182 	cmd[1] = sc->sc_active.cr3;
   1183 	cmd[2] = CR2_SD | CR2_SC | CR2_SB | CR2_SA | CR2_ELS | CR2_AM | CR2_EFC;
   1184 	cmd[3] = CR1_GR | CR1_GX;
   1185 	if ((rc = arcofi_cmd(sc, op, cmd)) != 0)
   1186 		goto error;
   1187 
   1188 	arcofi_write(sc, ARCOFI_FIFO_IR, 0);
   1189 	arcofi_write(sc, ARCOFI_CSR, CSR_INTR_ENABLE);
   1190 
   1191 	strlcpy(sc->sc_audio_device.name, arcofi_cd.cd_name,
   1192 	    sizeof(sc->sc_audio_device.name));
   1193 	strlcpy(sc->sc_audio_device.version, versionstr,
   1194 	    sizeof(sc->sc_audio_device.version));
   1195 	strlcpy(sc->sc_audio_device.config, device_xname(self),
   1196 	    sizeof(sc->sc_audio_device.config));
   1197 
   1198 	audio_attach_mi(&arcofi_hw_if, sc, self);
   1199 	return;
   1200 
   1201  error:
   1202 	arcofi_write(sc, ARCOFI_ID, 0);
   1203 	aprint_error("%s: %02x command failed, error %d\n",
   1204 	    __func__, op, rc);
   1205 	mutex_destroy(&sc->sc_intr_lock);
   1206 	mutex_destroy(&sc->sc_lock);
   1207 }
   1208