Home | History | Annotate | Line # | Download | only in gsc
harmony.c revision 1.5
      1 /*	$NetBSD: harmony.c,v 1.5 2019/03/16 12:09:56 isaki Exp $	*/
      2 
      3 /*	$OpenBSD: harmony.c,v 1.23 2004/02/13 21:28:19 mickey Exp $	*/
      4 
      5 /*-
      6  * Copyright (c) 2009 The NetBSD Foundation, Inc.
      7  * All rights reserved.
      8  *
      9  * This code is derived from software contributed to The NetBSD Foundation
     10  * by Matt Fleming.
     11  *
     12  * Redistribution and use in source and binary forms, with or without
     13  * modification, are permitted provided that the following conditions
     14  * are met:
     15  * 1. Redistributions of source code must retain the above copyright
     16  *    notice, this list of conditions and the following disclaimer.
     17  * 2. Redistributions in binary form must reproduce the above copyright
     18  *    notice, this list of conditions and the following disclaimer in the
     19  *    documentation and/or other materials provided with the distribution.
     20  *
     21  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
     22  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
     23  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     24  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
     25  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
     26  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
     27  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
     28  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
     29  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
     30  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
     31  * POSSIBILITY OF SUCH DAMAGE.
     32  */
     33 
     34 /*
     35  * Copyright (c) 2003 Jason L. Wright (jason (at) thought.net)
     36  * All rights reserved.
     37  *
     38  * Redistribution and use in source and binary forms, with or without
     39  * modification, are permitted provided that the following conditions
     40  * are met:
     41  * 1. Redistributions of source code must retain the above copyright
     42  *    notice, this list of conditions and the following disclaimer.
     43  * 2. Redistributions in binary form must reproduce the above copyright
     44  *    notice, this list of conditions and the following disclaimer in the
     45  *    documentation and/or other materials provided with the distribution.
     46  *
     47  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
     48  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
     49  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
     50  * DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
     51  * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
     52  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
     53  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     54  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
     55  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
     56  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
     57  * POSSIBILITY OF SUCH DAMAGE.
     58  */
     59 
     60 /*
     61  * Harmony (CS4215/AD1849 LASI) audio interface.
     62  */
     63 
     64 
     65 
     66 #include <sys/param.h>
     67 #include <sys/kernel.h>
     68 #include <sys/systm.h>
     69 #include <sys/errno.h>
     70 #include <sys/ioctl.h>
     71 #include <sys/device.h>
     72 #include <sys/proc.h>
     73 #include <sys/kmem.h>
     74 #include <uvm/uvm_extern.h>
     75 
     76 #include <sys/rndsource.h>
     77 
     78 #include <sys/audioio.h>
     79 #include <dev/audio_if.h>
     80 #include <dev/auconv.h>
     81 
     82 #include <machine/cpu.h>
     83 #include <machine/intr.h>
     84 #include <machine/iomod.h>
     85 #include <machine/autoconf.h>
     86 #include <sys/bus.h>
     87 
     88 #include <hppa/dev/cpudevs.h>
     89 #include <hppa/gsc/gscbusvar.h>
     90 #include <hppa/gsc/harmonyreg.h>
     91 #include <hppa/gsc/harmonyvar.h>
     92 
     93 int	harmony_open(void *, int);
     94 void	harmony_close(void *);
     95 int	harmony_query_encoding(void *, struct audio_encoding *);
     96 int	harmony_set_params(void *, int, int, audio_params_t *,
     97     audio_params_t *, stream_filter_list_t *, stream_filter_list_t *);
     98 int	harmony_round_blocksize(void *, int, int, const audio_params_t *);
     99 
    100 int	harmony_control_wait(struct harmony_softc *);
    101 int	harmony_commit_settings(void *);
    102 
    103 int	harmony_halt_output(void *);
    104 int	harmony_halt_input(void *);
    105 int	harmony_getdev(void *, struct audio_device *);
    106 int	harmony_set_port(void *, mixer_ctrl_t *);
    107 int	harmony_get_port(void *, mixer_ctrl_t *);
    108 int	harmony_query_devinfo(void *, mixer_devinfo_t *);
    109 void *	harmony_allocm(void *, int, size_t);
    110 void	harmony_freem(void *, void *, size_t);
    111 size_t	harmony_round_buffersize(void *, int, size_t);
    112 int	harmony_get_props(void *);
    113 int	harmony_trigger_output(void *, void *, void *, int,
    114     void (*)(void *), void *, const audio_params_t *);
    115 int	harmony_trigger_input(void *, void *, void *, int,
    116     void (*)(void *), void *, const audio_params_t *);
    117 void	harmony_get_locks(void *, kmutex_t **, kmutex_t **);
    118 
    119 const struct audio_hw_if harmony_sa_hw_if = {
    120 	.open			= harmony_open,
    121 	.close			= harmony_close,
    122 	.query_encoding		= harmony_query_encoding,
    123 	.set_params		= harmony_set_params,
    124 	.round_blocksize	= harmony_round_blocksize,
    125 	.commit_settings	= harmony_commit_settings,
    126 	.halt_output		= harmony_halt_output,
    127 	.halt_input		= harmony_halt_input,
    128 	.getdev			= harmony_getdev,
    129 	.set_port		= harmony_set_port,
    130 	.get_port		= harmony_get_port,
    131 	.query_devinfo		= harmony_query_devinfo,
    132 	.allocm			= harmony_allocm,
    133 	.freem			= harmony_freem,
    134 	.round_buffersize	= harmony_round_buffersize,
    135 	.get_props		= harmony_get_props,
    136 	.trigger_output		= harmony_trigger_output,
    137 	.trigger_input		= harmony_trigger_input,
    138 	.get_locks		= harmony_get_locks,
    139 };
    140 
    141 int harmony_match(device_t, struct cfdata *, void *);
    142 void harmony_attach(device_t, device_t, void *);
    143 
    144 
    145 CFATTACH_DECL_NEW(harmony, sizeof(struct harmony_softc),
    146     harmony_match, harmony_attach, NULL, NULL);
    147 
    148 int harmony_intr(void *);
    149 void harmony_intr_enable(struct harmony_softc *);
    150 void harmony_intr_disable(struct harmony_softc *);
    151 uint32_t harmony_speed_bits(struct harmony_softc *, u_int *);
    152 int harmony_set_gainctl(struct harmony_softc *);
    153 void harmony_reset_codec(struct harmony_softc *);
    154 void harmony_start_cp(struct harmony_softc *, int);
    155 void harmony_start_pp(struct harmony_softc *, int);
    156 void harmony_tick_pb(void *);
    157 void harmony_tick_cp(void *);
    158 void harmony_try_more(struct harmony_softc *, int, int,
    159 	struct harmony_channel *);
    160 static void harmony_empty_input(struct harmony_softc *);
    161 static void harmony_empty_output(struct harmony_softc *);
    162 
    163 void harmony_acc_tmo(void *);
    164 #define	ADD_CLKALLICA(sc) do {						\
    165 	(sc)->sc_acc <<= 1;						\
    166 	(sc)->sc_acc |= READ_REG((sc), HARMONY_DIAG) & DIAG_CO;		\
    167 	if ((sc)->sc_acc_cnt++ && !((sc)->sc_acc_cnt % 32))		\
    168 		rnd_add_uint32(&(sc)->sc_rnd_source,			\
    169 			       (sc)->sc_acc_num ^= (sc)->sc_acc);	\
    170 } while(0)
    171 
    172 int
    173 harmony_match(device_t parent, struct cfdata *match, void *aux)
    174 {
    175 	struct gsc_attach_args *ga;
    176 
    177 	ga = aux;
    178 	if (ga->ga_type.iodc_type == HPPA_TYPE_FIO) {
    179 		if (ga->ga_type.iodc_sv_model == HPPA_FIO_A1 ||
    180 		    ga->ga_type.iodc_sv_model == HPPA_FIO_A2NB ||
    181 		    ga->ga_type.iodc_sv_model == HPPA_FIO_A1NB ||
    182 		    ga->ga_type.iodc_sv_model == HPPA_FIO_A2)
    183 			return 1;
    184 	}
    185 	return 0;
    186 }
    187 
    188 void
    189 harmony_attach(device_t parent, device_t self, void *aux)
    190 {
    191 	struct harmony_softc *sc = device_private(self);
    192 	struct gsc_attach_args *ga;
    193 	uint8_t rev;
    194 	uint32_t cntl;
    195 	int i;
    196 
    197 	sc->sc_dv = self;
    198 	ga = aux;
    199 	sc->sc_bt = ga->ga_iot;
    200 	sc->sc_dmat = ga->ga_dmatag;
    201 
    202 	mutex_init(&sc->sc_lock, MUTEX_DEFAULT, IPL_NONE);
    203 	mutex_init(&sc->sc_intr_lock, MUTEX_DEFAULT, IPL_AUDIO);
    204 
    205 	if (bus_space_map(sc->sc_bt, ga->ga_hpa, HARMONY_NREGS, 0,
    206 	    &sc->sc_bh) != 0) {
    207 		aprint_error(": couldn't map registers\n");
    208 		return;
    209 	}
    210 
    211 	cntl = READ_REG(sc, HARMONY_ID);
    212 	switch ((cntl & ID_REV_MASK)) {
    213 	case ID_REV_TS:
    214 		sc->sc_teleshare = 1;
    215 	case ID_REV_NOTS:
    216 		break;
    217 	default:
    218 		aprint_error(": unknown id == 0x%02x\n",
    219 		    (cntl & ID_REV_MASK) >> ID_REV_SHIFT);
    220 		bus_space_unmap(sc->sc_bt, sc->sc_bh, HARMONY_NREGS);
    221 		return;
    222 	}
    223 
    224 	if (bus_dmamem_alloc(sc->sc_dmat, sizeof(struct harmony_empty),
    225 	    PAGE_SIZE, 0, &sc->sc_empty_seg, 1, &sc->sc_empty_rseg,
    226 	    BUS_DMA_WAITOK) != 0) {
    227 		aprint_error(": could not alloc DMA memory\n");
    228 		bus_space_unmap(sc->sc_bt, sc->sc_bh, HARMONY_NREGS);
    229 		return;
    230 	}
    231 	if (bus_dmamem_map(sc->sc_dmat, &sc->sc_empty_seg, 1,
    232 	    sizeof(struct harmony_empty), (void **)&sc->sc_empty_kva,
    233 	    BUS_DMA_WAITOK) != 0) {
    234 		aprint_error(": couldn't map DMA memory\n");
    235 		bus_dmamem_free(sc->sc_dmat, &sc->sc_empty_seg,
    236 		    sc->sc_empty_rseg);
    237 		bus_space_unmap(sc->sc_bt, sc->sc_bh, HARMONY_NREGS);
    238 		return;
    239 	}
    240 	if (bus_dmamap_create(sc->sc_dmat, sizeof(struct harmony_empty), 1,
    241 	    sizeof(struct harmony_empty), 0, BUS_DMA_WAITOK,
    242 	    &sc->sc_empty_map) != 0) {
    243 		aprint_error(": can't create DMA map\n");
    244 		bus_dmamem_unmap(sc->sc_dmat, (void *)sc->sc_empty_kva,
    245 		    sizeof(struct harmony_empty));
    246 		bus_dmamem_free(sc->sc_dmat, &sc->sc_empty_seg,
    247 		    sc->sc_empty_rseg);
    248 		bus_space_unmap(sc->sc_bt, sc->sc_bh, HARMONY_NREGS);
    249 		return;
    250 	}
    251 	if (bus_dmamap_load(sc->sc_dmat, sc->sc_empty_map, sc->sc_empty_kva,
    252 	    sizeof(struct harmony_empty), NULL, BUS_DMA_WAITOK) != 0) {
    253 		aprint_error(": can't load DMA map\n");
    254 		bus_dmamap_destroy(sc->sc_dmat, sc->sc_empty_map);
    255 		bus_dmamem_unmap(sc->sc_dmat, (void *)sc->sc_empty_kva,
    256 		    sizeof(struct harmony_empty));
    257 		bus_dmamem_free(sc->sc_dmat, &sc->sc_empty_seg,
    258 		    sc->sc_empty_rseg);
    259 		bus_space_unmap(sc->sc_bt, sc->sc_bh, HARMONY_NREGS);
    260 		return;
    261 	}
    262 
    263 	sc->sc_playback_empty = 0;
    264 	for (i = 0; i < PLAYBACK_EMPTYS; i++)
    265 		sc->sc_playback_paddrs[i] =
    266 		    sc->sc_empty_map->dm_segs[0].ds_addr +
    267 		    offsetof(struct harmony_empty, playback[i][0]);
    268 
    269 	sc->sc_capture_empty = 0;
    270 	for (i = 0; i < CAPTURE_EMPTYS; i++)
    271 		sc->sc_capture_paddrs[i] =
    272 		    sc->sc_empty_map->dm_segs[0].ds_addr +
    273 		    offsetof(struct harmony_empty, capture[i][0]);
    274 
    275 	bus_dmamap_sync(sc->sc_dmat, sc->sc_empty_map,
    276 	    offsetof(struct harmony_empty, playback[0][0]),
    277 	    PLAYBACK_EMPTYS * HARMONY_BUFSIZE, BUS_DMASYNC_PREWRITE);
    278 
    279 	(void) hppa_intr_establish(IPL_AUDIO, harmony_intr, sc, ga->ga_ir,
    280 	     ga->ga_irq);
    281 
    282 	/* set defaults */
    283 	sc->sc_in_port = HARMONY_IN_LINE;
    284 	sc->sc_out_port = HARMONY_OUT_SPEAKER;
    285 	sc->sc_input_lvl.left = sc->sc_input_lvl.right = 240;
    286 	sc->sc_output_lvl.left = sc->sc_output_lvl.right = 244;
    287 	sc->sc_monitor_lvl.left = sc->sc_monitor_lvl.right = 208;
    288 	sc->sc_outputgain = 0;
    289 
    290 	/* reset chip, and push default gain controls */
    291 	harmony_reset_codec(sc);
    292 
    293 	cntl = READ_REG(sc, HARMONY_CNTL);
    294 	rev = (cntl & CNTL_CODEC_REV_MASK) >> CNTL_CODEC_REV_SHIFT;
    295 	aprint_normal(": rev %u", rev);
    296 
    297 	if (sc->sc_teleshare)
    298 		printf(", teleshare");
    299 	aprint_normal("\n");
    300 
    301 	if ((rev & CS4215_REV_VER) >= CS4215_REV_VER_E)
    302 		sc->sc_hasulinear8 = 1;
    303 
    304 	strlcpy(sc->sc_audev.name, ga->ga_name, sizeof(sc->sc_audev.name));
    305 	snprintf(sc->sc_audev.version, sizeof sc->sc_audev.version,
    306 	    "%u.%u;%u", ga->ga_type.iodc_sv_rev,
    307 	    ga->ga_type.iodc_model, ga->ga_type.iodc_revision);
    308 	strlcpy(sc->sc_audev.config, device_xname(sc->sc_dv),
    309 	    sizeof(sc->sc_audev.config));
    310 
    311 	audio_attach_mi(&harmony_sa_hw_if, sc, sc->sc_dv);
    312 
    313 	rnd_attach_source(&sc->sc_rnd_source, device_xname(sc->sc_dv),
    314 	    RND_TYPE_UNKNOWN, RND_FLAG_DEFAULT);
    315 
    316 	callout_init(&sc->sc_acc_tmo, 0);
    317 	callout_setfunc(&sc->sc_acc_tmo, harmony_acc_tmo, sc);
    318 	sc->sc_acc_num = 0xa5a5a5a5;
    319 }
    320 
    321 void
    322 harmony_reset_codec(struct harmony_softc *sc)
    323 {
    324 
    325 	/* silence */
    326 	WRITE_REG(sc, HARMONY_GAINCTL, GAINCTL_OUTPUT_LEFT_M |
    327 	    GAINCTL_OUTPUT_RIGHT_M | GAINCTL_MONITOR_M);
    328 
    329 	/* start reset */
    330 	WRITE_REG(sc, HARMONY_RESET, RESET_RST);
    331 
    332 	DELAY(100000);		/* wait at least 0.05 sec */
    333 
    334 	harmony_set_gainctl(sc);
    335 	WRITE_REG(sc, HARMONY_RESET, 0);
    336 }
    337 
    338 void
    339 harmony_acc_tmo(void *v)
    340 {
    341 	struct harmony_softc *sc;
    342 
    343 	sc = v;
    344 	ADD_CLKALLICA(sc);
    345 	callout_schedule(&sc->sc_acc_tmo, 1);
    346 }
    347 
    348 /*
    349  * interrupt handler
    350  */
    351 int
    352 harmony_intr(void *vsc)
    353 {
    354 	struct harmony_softc *sc;
    355 	uint32_t dstatus;
    356 	int r;
    357 
    358 	sc = vsc;
    359 	r = 0;
    360 	ADD_CLKALLICA(sc);
    361 
    362 	mutex_spin_enter(&sc->sc_intr_lock);
    363 
    364 	harmony_intr_disable(sc);
    365 
    366 	dstatus = READ_REG(sc, HARMONY_DSTATUS);
    367 
    368 	if (dstatus & DSTATUS_PN) {
    369 		r = 1;
    370 		harmony_start_pp(sc, 0);
    371 	}
    372 
    373 	if (dstatus & DSTATUS_RN) {
    374 		r = 1;
    375 		harmony_start_cp(sc, 0);
    376 	}
    377 
    378 	if (READ_REG(sc, HARMONY_OV) & OV_OV) {
    379 		sc->sc_ov = 1;
    380 		WRITE_REG(sc, HARMONY_OV, 0);
    381 	} else
    382 		sc->sc_ov = 0;
    383 
    384 	harmony_intr_enable(sc);
    385 
    386 	mutex_spin_exit(&sc->sc_intr_lock);
    387 
    388 	return r;
    389 }
    390 
    391 void
    392 harmony_intr_enable(struct harmony_softc *sc)
    393 {
    394 
    395 	WRITE_REG(sc, HARMONY_DSTATUS, DSTATUS_IE);
    396 	SYNC_REG(sc, HARMONY_DSTATUS, BUS_SPACE_BARRIER_WRITE);
    397 }
    398 
    399 void
    400 harmony_intr_disable(struct harmony_softc *sc)
    401 {
    402 
    403 	WRITE_REG(sc, HARMONY_DSTATUS, 0);
    404 	SYNC_REG(sc, HARMONY_DSTATUS, BUS_SPACE_BARRIER_WRITE);
    405 }
    406 
    407 int
    408 harmony_open(void *vsc, int flags)
    409 {
    410 	struct harmony_softc *sc;
    411 
    412 	sc = vsc;
    413 	if (sc->sc_open)
    414 		return EBUSY;
    415 	sc->sc_open = 1;
    416 	return 0;
    417 }
    418 
    419 void
    420 harmony_close(void *vsc)
    421 {
    422 	struct harmony_softc *sc;
    423 
    424 	sc = vsc;
    425 	harmony_halt_input(sc);
    426 	harmony_halt_output(sc);
    427 	harmony_intr_disable(sc);
    428 	sc->sc_open = 0;
    429 }
    430 
    431 int
    432 harmony_query_encoding(void *vsc, struct audio_encoding *fp)
    433 {
    434 	struct harmony_softc *sc;
    435 	int err;
    436 
    437 	sc = vsc;
    438 	err = 0;
    439 	switch (fp->index) {
    440 	case 0:
    441 		strlcpy(fp->name, AudioEmulaw, sizeof fp->name);
    442 		fp->encoding = AUDIO_ENCODING_ULAW;
    443 		fp->precision = 8;
    444 		fp->flags = 0;
    445 		break;
    446 	case 1:
    447 		strlcpy(fp->name, AudioEalaw, sizeof fp->name);
    448 		fp->encoding = AUDIO_ENCODING_ALAW;
    449 		fp->precision = 8;
    450 		fp->flags = 0;
    451 		break;
    452 	case 2:
    453 		strlcpy(fp->name, AudioEslinear_be, sizeof fp->name);
    454 		fp->encoding = AUDIO_ENCODING_SLINEAR_BE;
    455 		fp->precision = 16;
    456 		fp->flags = 0;
    457 		break;
    458 	case 3:
    459 		strlcpy(fp->name, AudioEslinear_le, sizeof fp->name);
    460 		fp->encoding = AUDIO_ENCODING_SLINEAR_LE;
    461 		fp->precision = 16;
    462 		fp->flags = AUDIO_ENCODINGFLAG_EMULATED;
    463 		break;
    464 	case 4:
    465 		strlcpy(fp->name, AudioEulinear_be, sizeof fp->name);
    466 		fp->encoding = AUDIO_ENCODING_ULINEAR_BE;
    467 		fp->precision = 16;
    468 		fp->flags = AUDIO_ENCODINGFLAG_EMULATED;
    469 		break;
    470 	case 5:
    471 		strlcpy(fp->name, AudioEulinear_le, sizeof fp->name);
    472 		fp->encoding = AUDIO_ENCODING_ULINEAR_LE;
    473 		fp->precision = 16;
    474 		fp->flags = AUDIO_ENCODINGFLAG_EMULATED;
    475 		break;
    476 	case 6:
    477 		if (sc->sc_hasulinear8) {
    478 			strlcpy(fp->name, AudioEulinear, sizeof fp->name);
    479 			fp->encoding = AUDIO_ENCODING_ULINEAR;
    480 			fp->precision = 8;
    481 			fp->flags = 0;
    482 			break;
    483 		}
    484 		/*FALLTHROUGH*/
    485 	case 7:
    486 		if (sc->sc_hasulinear8) {
    487 			strlcpy(fp->name, AudioEslinear, sizeof fp->name);
    488 			fp->encoding = AUDIO_ENCODING_SLINEAR;
    489 			fp->precision = 8;
    490 			fp->flags = AUDIO_ENCODINGFLAG_EMULATED;
    491 			break;
    492 		}
    493 		/*FALLTHROUGH*/
    494 	default:
    495 		err = EINVAL;
    496 	}
    497 	return err;
    498 }
    499 
    500 int
    501 harmony_set_params(void *vsc, int setmode, int usemode,
    502     audio_params_t *p, audio_params_t *r,
    503     stream_filter_list_t *pfil, stream_filter_list_t *rfil)
    504 {
    505 	audio_params_t hw;
    506 	struct harmony_softc *sc;
    507 	uint32_t bits;
    508 	stream_filter_factory_t *pswcode = NULL;
    509 	stream_filter_factory_t *rswcode = NULL;
    510 
    511 	sc = vsc;
    512 	/* assume p.equals(r) */
    513 	hw = *p;
    514 	switch (p->encoding) {
    515 	case AUDIO_ENCODING_ULAW:
    516 		if (p->precision != 8)
    517 			return EINVAL;
    518 		bits = CNTL_FORMAT_ULAW;
    519 		break;
    520 	case AUDIO_ENCODING_ALAW:
    521 		if (p->precision != 8)
    522 			return EINVAL;
    523 		bits = CNTL_FORMAT_ALAW;
    524 		break;
    525 	case AUDIO_ENCODING_SLINEAR_BE:
    526 		if (p->precision == 8) {
    527 			bits = CNTL_FORMAT_ULINEAR8;
    528 			hw.encoding = AUDIO_ENCODING_ULINEAR_LE;
    529 			rswcode = pswcode = change_sign8;
    530 			break;
    531 		}
    532 		if (p->precision == 16) {
    533 			bits = CNTL_FORMAT_SLINEAR16BE;
    534 			break;
    535 		}
    536 		return EINVAL;
    537 	case AUDIO_ENCODING_ULINEAR:
    538 		if (p->precision != 8)
    539 			return EINVAL;
    540 		bits = CNTL_FORMAT_ULINEAR8;
    541 		break;
    542 	case AUDIO_ENCODING_SLINEAR:
    543 		if (p->precision != 8)
    544 			return EINVAL;
    545 		bits = CNTL_FORMAT_ULINEAR8;
    546 		hw.encoding = AUDIO_ENCODING_ULINEAR_LE;
    547 		rswcode = pswcode = change_sign8;
    548 		break;
    549 	case AUDIO_ENCODING_SLINEAR_LE:
    550 		if (p->precision == 8) {
    551 			bits = CNTL_FORMAT_ULINEAR8;
    552 			hw.encoding = AUDIO_ENCODING_ULINEAR_LE;
    553 			rswcode = pswcode = change_sign8;
    554 			break;
    555 		}
    556 		if (p->precision == 16) {
    557 			bits = CNTL_FORMAT_SLINEAR16BE;
    558 			hw.encoding = AUDIO_ENCODING_SLINEAR_BE;
    559 			rswcode = pswcode = swap_bytes;
    560 			break;
    561 		}
    562 		return EINVAL;
    563 	case AUDIO_ENCODING_ULINEAR_BE:
    564 		if (p->precision == 8) {
    565 			bits = CNTL_FORMAT_ULINEAR8;
    566 			break;
    567 		}
    568 		if (p->precision == 16) {
    569 			bits = CNTL_FORMAT_SLINEAR16BE;
    570 			rswcode = pswcode = change_sign16;
    571 			break;
    572 		}
    573 		return EINVAL;
    574 	case AUDIO_ENCODING_ULINEAR_LE:
    575 		if (p->precision == 8) {
    576 			bits = CNTL_FORMAT_ULINEAR8;
    577 			break;
    578 		}
    579 		if (p->precision == 16) {
    580 			bits = CNTL_FORMAT_SLINEAR16BE;
    581 			hw.encoding = AUDIO_ENCODING_SLINEAR_BE;
    582 			rswcode = pswcode = swap_bytes_change_sign16;
    583 			break;
    584 		}
    585 		return EINVAL;
    586 	default:
    587 		return EINVAL;
    588 	}
    589 
    590 	if (sc->sc_outputgain)
    591 		bits |= CNTL_OLB;
    592 
    593 	if (p->channels == 1)
    594 		bits |= CNTL_CHANS_MONO;
    595 	else if (p->channels == 2)
    596 		bits |= CNTL_CHANS_STEREO;
    597 	else
    598 		return EINVAL;
    599 
    600 	bits |= harmony_speed_bits(sc, &p->sample_rate);
    601 	if (pswcode != NULL)
    602 		pfil->append(pfil, pswcode, &hw);
    603 	if (rswcode != NULL)
    604 		rfil->append(rfil, rswcode, &hw);
    605 	sc->sc_cntlbits = bits;
    606 	sc->sc_need_commit = 1;
    607 
    608 	return 0;
    609 }
    610 
    611 int
    612 harmony_round_blocksize(void *vsc, int blk,
    613     int mode, const audio_params_t *param)
    614 {
    615 
    616 	return HARMONY_BUFSIZE;
    617 }
    618 
    619 int
    620 harmony_control_wait(struct harmony_softc *sc)
    621 {
    622 	uint32_t reg;
    623 	int j = 0;
    624 
    625 	while (j < 10) {
    626 		/* Wait for it to come out of control mode */
    627 		reg = READ_REG(sc, HARMONY_CNTL);
    628 		if ((reg & CNTL_C) == 0)
    629 			return 0;
    630 		DELAY(50000);		/* wait 0.05 */
    631 		j++;
    632 	}
    633 
    634 	return 1;
    635 }
    636 
    637 int
    638 harmony_commit_settings(void *vsc)
    639 {
    640 	struct harmony_softc *sc;
    641 	uint32_t reg;
    642 	uint8_t quietchar;
    643 	int i;
    644 
    645 	sc = vsc;
    646 	if (sc->sc_need_commit == 0)
    647 		return 0;
    648 
    649 	harmony_intr_disable(sc);
    650 
    651 	for (;;) {
    652 		reg = READ_REG(sc, HARMONY_DSTATUS);
    653 		if ((reg & (DSTATUS_PC | DSTATUS_RC)) == 0)
    654 			break;
    655 	}
    656 
    657 	/* Setting some bits in gainctl requires a reset */
    658 	harmony_reset_codec(sc);
    659 
    660 	/* set the silence character based on the encoding type */
    661 	bus_dmamap_sync(sc->sc_dmat, sc->sc_empty_map,
    662 	    offsetof(struct harmony_empty, playback[0][0]),
    663 	    PLAYBACK_EMPTYS * HARMONY_BUFSIZE, BUS_DMASYNC_POSTWRITE);
    664 	switch (sc->sc_cntlbits & CNTL_FORMAT_MASK) {
    665 	case CNTL_FORMAT_ULAW:
    666 		quietchar = 0x7f;
    667 		break;
    668 	case CNTL_FORMAT_ALAW:
    669 		quietchar = 0x55;
    670 		break;
    671 	case CNTL_FORMAT_SLINEAR16BE:
    672 	case CNTL_FORMAT_ULINEAR8:
    673 	default:
    674 		quietchar = 0;
    675 		break;
    676 	}
    677 	for (i = 0; i < PLAYBACK_EMPTYS; i++)
    678 		memset(&sc->sc_empty_kva->playback[i][0],
    679 		    quietchar, HARMONY_BUFSIZE);
    680 	bus_dmamap_sync(sc->sc_dmat, sc->sc_empty_map,
    681 	    offsetof(struct harmony_empty, playback[0][0]),
    682 	    PLAYBACK_EMPTYS * HARMONY_BUFSIZE, BUS_DMASYNC_PREWRITE);
    683 
    684 	harmony_control_wait(sc);
    685 
    686 	bus_space_write_4(sc->sc_bt, sc->sc_bh, HARMONY_CNTL,
    687 	    sc->sc_cntlbits | CNTL_C);
    688 
    689 	harmony_control_wait(sc);
    690 
    691 	sc->sc_need_commit = 0;
    692 
    693 	if (sc->sc_playing || sc->sc_capturing)
    694 		harmony_intr_enable(sc);
    695 
    696 	return 0;
    697 }
    698 
    699 static void
    700 harmony_empty_output(struct harmony_softc *sc)
    701 {
    702 
    703 	WRITE_REG(sc, HARMONY_PNXTADD,
    704 	    sc->sc_playback_paddrs[sc->sc_playback_empty]);
    705 	SYNC_REG(sc, HARMONY_PNXTADD, BUS_SPACE_BARRIER_WRITE);
    706 
    707 	if (++sc->sc_playback_empty == PLAYBACK_EMPTYS)
    708 		sc->sc_playback_empty = 0;
    709 }
    710 
    711 int
    712 harmony_halt_output(void *vsc)
    713 {
    714 	struct harmony_softc *sc;
    715 
    716 	sc = vsc;
    717 	sc->sc_playing = 0;
    718 
    719 	harmony_empty_output(sc);
    720 	return 0;
    721 }
    722 
    723 static void
    724 harmony_empty_input(struct harmony_softc *sc)
    725 {
    726 
    727 	WRITE_REG(sc, HARMONY_RNXTADD,
    728 	    sc->sc_capture_paddrs[sc->sc_capture_empty]);
    729 	SYNC_REG(sc, HARMONY_RNXTADD, BUS_SPACE_BARRIER_WRITE);
    730 
    731 	if (++sc->sc_capture_empty == CAPTURE_EMPTYS)
    732 		sc->sc_capture_empty = 0;
    733 }
    734 
    735 int
    736 harmony_halt_input(void *vsc)
    737 {
    738 	struct harmony_softc *sc;
    739 
    740 	sc = vsc;
    741 	sc->sc_capturing = 0;
    742 
    743 	harmony_empty_input(sc);
    744 	return 0;
    745 }
    746 
    747 int
    748 harmony_getdev(void *vsc, struct audio_device *retp)
    749 {
    750 	struct harmony_softc *sc;
    751 
    752 	sc = vsc;
    753 	*retp = sc->sc_audev;
    754 	return 0;
    755 }
    756 
    757 int
    758 harmony_set_port(void *vsc, mixer_ctrl_t *cp)
    759 {
    760 	struct harmony_softc *sc;
    761 	int err;
    762 
    763 	sc = vsc;
    764 	err = EINVAL;
    765 	switch (cp->dev) {
    766 	case HARMONY_PORT_INPUT_LVL:
    767 		if (cp->type != AUDIO_MIXER_VALUE)
    768 			break;
    769 		if (cp->un.value.num_channels == 1)
    770 			sc->sc_input_lvl.left = sc->sc_input_lvl.right =
    771 			    cp->un.value.level[AUDIO_MIXER_LEVEL_MONO];
    772 		else if (cp->un.value.num_channels == 2) {
    773 			sc->sc_input_lvl.left =
    774 			    cp->un.value.level[AUDIO_MIXER_LEVEL_LEFT];
    775 			sc->sc_input_lvl.right =
    776 			    cp->un.value.level[AUDIO_MIXER_LEVEL_RIGHT];
    777 		} else
    778 			break;
    779 		sc->sc_need_commit = 1;
    780 		err = 0;
    781 		break;
    782 	case HARMONY_PORT_OUTPUT_LVL:
    783 		if (cp->type != AUDIO_MIXER_VALUE)
    784 			break;
    785 		if (cp->un.value.num_channels == 1)
    786 			sc->sc_output_lvl.left = sc->sc_output_lvl.right =
    787 			    cp->un.value.level[AUDIO_MIXER_LEVEL_MONO];
    788 		else if (cp->un.value.num_channels == 2) {
    789 			sc->sc_output_lvl.left =
    790 			    cp->un.value.level[AUDIO_MIXER_LEVEL_LEFT];
    791 			sc->sc_output_lvl.right =
    792 			    cp->un.value.level[AUDIO_MIXER_LEVEL_RIGHT];
    793 		} else
    794 			break;
    795 		sc->sc_need_commit = 1;
    796 		err = 0;
    797 		break;
    798 	case HARMONY_PORT_OUTPUT_GAIN:
    799 		if (cp->type != AUDIO_MIXER_ENUM)
    800 			break;
    801 		sc->sc_outputgain = cp->un.ord ? 1 : 0;
    802 		err = 0;
    803 		break;
    804 	case HARMONY_PORT_MONITOR_LVL:
    805 		if (cp->type != AUDIO_MIXER_VALUE)
    806 			break;
    807 		if (cp->un.value.num_channels != 1)
    808 			break;
    809 		sc->sc_monitor_lvl.left = sc->sc_input_lvl.right =
    810 		    cp->un.value.level[AUDIO_MIXER_LEVEL_MONO];
    811 		sc->sc_need_commit = 1;
    812 		err = 0;
    813 		break;
    814 	case HARMONY_PORT_RECORD_SOURCE:
    815 		if (cp->type != AUDIO_MIXER_ENUM)
    816 			break;
    817 		if (cp->un.ord != HARMONY_IN_LINE &&
    818 		    cp->un.ord != HARMONY_IN_MIC)
    819 			break;
    820 		sc->sc_in_port = cp->un.ord;
    821 		err = 0;
    822 		sc->sc_need_commit = 1;
    823 		break;
    824 	case HARMONY_PORT_OUTPUT_SOURCE:
    825 		if (cp->type != AUDIO_MIXER_ENUM)
    826 			break;
    827 		if (cp->un.ord != HARMONY_OUT_LINE &&
    828 		    cp->un.ord != HARMONY_OUT_SPEAKER &&
    829 		    cp->un.ord != HARMONY_OUT_HEADPHONE)
    830 			break;
    831 		sc->sc_out_port = cp->un.ord;
    832 		err = 0;
    833 		sc->sc_need_commit = 1;
    834 		break;
    835 	}
    836 
    837 	return err;
    838 }
    839 
    840 int
    841 harmony_get_port(void *vsc, mixer_ctrl_t *cp)
    842 {
    843 	struct harmony_softc *sc;
    844 	int err;
    845 
    846 	sc = vsc;
    847 	err = EINVAL;
    848 	switch (cp->dev) {
    849 	case HARMONY_PORT_INPUT_LVL:
    850 		if (cp->type != AUDIO_MIXER_VALUE)
    851 			break;
    852 		if (cp->un.value.num_channels == 1) {
    853 			cp->un.value.level[AUDIO_MIXER_LEVEL_MONO] =
    854 			    sc->sc_input_lvl.left;
    855 		} else if (cp->un.value.num_channels == 2) {
    856 			cp->un.value.level[AUDIO_MIXER_LEVEL_LEFT] =
    857 			    sc->sc_input_lvl.left;
    858 			cp->un.value.level[AUDIO_MIXER_LEVEL_RIGHT] =
    859 			    sc->sc_input_lvl.right;
    860 		} else
    861 			break;
    862 		err = 0;
    863 		break;
    864 	case HARMONY_PORT_INPUT_OV:
    865 		if (cp->type != AUDIO_MIXER_ENUM)
    866 			break;
    867 		cp->un.ord = sc->sc_ov ? 1 : 0;
    868 		err = 0;
    869 		break;
    870 	case HARMONY_PORT_OUTPUT_LVL:
    871 		if (cp->type != AUDIO_MIXER_VALUE)
    872 			break;
    873 		if (cp->un.value.num_channels == 1) {
    874 			cp->un.value.level[AUDIO_MIXER_LEVEL_MONO] =
    875 			    sc->sc_output_lvl.left;
    876 		} else if (cp->un.value.num_channels == 2) {
    877 			cp->un.value.level[AUDIO_MIXER_LEVEL_LEFT] =
    878 			    sc->sc_output_lvl.left;
    879 			cp->un.value.level[AUDIO_MIXER_LEVEL_RIGHT] =
    880 			    sc->sc_output_lvl.right;
    881 		} else
    882 			break;
    883 		err = 0;
    884 		break;
    885 	case HARMONY_PORT_OUTPUT_GAIN:
    886 		if (cp->type != AUDIO_MIXER_ENUM)
    887 			break;
    888 		cp->un.ord = sc->sc_outputgain ? 1 : 0;
    889 		err = 0;
    890 		break;
    891 	case HARMONY_PORT_MONITOR_LVL:
    892 		if (cp->type != AUDIO_MIXER_VALUE)
    893 			break;
    894 		if (cp->un.value.num_channels != 1)
    895 			break;
    896 		cp->un.value.level[AUDIO_MIXER_LEVEL_MONO] =
    897 		    sc->sc_monitor_lvl.left;
    898 		err = 0;
    899 		break;
    900 	case HARMONY_PORT_RECORD_SOURCE:
    901 		if (cp->type != AUDIO_MIXER_ENUM)
    902 			break;
    903 		cp->un.ord = sc->sc_in_port;
    904 		err = 0;
    905 		break;
    906 	case HARMONY_PORT_OUTPUT_SOURCE:
    907 		if (cp->type != AUDIO_MIXER_ENUM)
    908 			break;
    909 		cp->un.ord = sc->sc_out_port;
    910 		err = 0;
    911 		break;
    912 	}
    913 	return err;
    914 }
    915 
    916 int
    917 harmony_query_devinfo(void *vsc, mixer_devinfo_t *dip)
    918 {
    919 	int err;
    920 
    921 	err = 0;
    922 	switch (dip->index) {
    923 	case HARMONY_PORT_INPUT_LVL:
    924 		dip->type = AUDIO_MIXER_VALUE;
    925 		dip->mixer_class = HARMONY_PORT_INPUT_CLASS;
    926 		dip->prev = dip->next = AUDIO_MIXER_LAST;
    927 		strlcpy(dip->label.name, AudioNinput, sizeof dip->label.name);
    928 		dip->un.v.num_channels = 2;
    929 		strlcpy(dip->un.v.units.name, AudioNvolume,
    930 		    sizeof dip->un.v.units.name);
    931 		break;
    932 	case HARMONY_PORT_INPUT_OV:
    933 		dip->type = AUDIO_MIXER_ENUM;
    934 		dip->mixer_class = HARMONY_PORT_INPUT_CLASS;
    935 		dip->prev = dip->next = AUDIO_MIXER_LAST;
    936 		strlcpy(dip->label.name, "overrange", sizeof dip->label.name);
    937 		dip->un.e.num_mem = 2;
    938 		strlcpy(dip->un.e.member[0].label.name, AudioNoff,
    939 		    sizeof dip->un.e.member[0].label.name);
    940 		dip->un.e.member[0].ord = 0;
    941 		strlcpy(dip->un.e.member[1].label.name, AudioNon,
    942 		    sizeof dip->un.e.member[1].label.name);
    943 		dip->un.e.member[1].ord = 1;
    944 		break;
    945 	case HARMONY_PORT_OUTPUT_LVL:
    946 		dip->type = AUDIO_MIXER_VALUE;
    947 		dip->mixer_class = HARMONY_PORT_OUTPUT_CLASS;
    948 		dip->prev = dip->next = AUDIO_MIXER_LAST;
    949 		strlcpy(dip->label.name, AudioNoutput, sizeof dip->label.name);
    950 		dip->un.v.num_channels = 2;
    951 		strlcpy(dip->un.v.units.name, AudioNvolume,
    952 		    sizeof dip->un.v.units.name);
    953 		break;
    954 	case HARMONY_PORT_OUTPUT_GAIN:
    955 		dip->type = AUDIO_MIXER_ENUM;
    956 		dip->mixer_class = HARMONY_PORT_OUTPUT_CLASS;
    957 		dip->prev = dip->next = AUDIO_MIXER_LAST;
    958 		strlcpy(dip->label.name, "gain", sizeof dip->label.name);
    959 		dip->un.e.num_mem = 2;
    960 		strlcpy(dip->un.e.member[0].label.name, AudioNoff,
    961 		    sizeof dip->un.e.member[0].label.name);
    962 		dip->un.e.member[0].ord = 0;
    963 		strlcpy(dip->un.e.member[1].label.name, AudioNon,
    964 		    sizeof dip->un.e.member[1].label.name);
    965 		dip->un.e.member[1].ord = 1;
    966 		break;
    967 	case HARMONY_PORT_MONITOR_LVL:
    968 		dip->type = AUDIO_MIXER_VALUE;
    969 		dip->mixer_class = HARMONY_PORT_MONITOR_CLASS;
    970 		dip->prev = dip->next = AUDIO_MIXER_LAST;
    971 		strlcpy(dip->label.name, AudioNmonitor, sizeof dip->label.name);
    972 		dip->un.v.num_channels = 1;
    973 		strlcpy(dip->un.v.units.name, AudioNvolume,
    974 		    sizeof dip->un.v.units.name);
    975 		break;
    976 	case HARMONY_PORT_RECORD_SOURCE:
    977 		dip->type = AUDIO_MIXER_ENUM;
    978 		dip->mixer_class = HARMONY_PORT_RECORD_CLASS;
    979 		dip->prev = dip->next = AUDIO_MIXER_LAST;
    980 		strlcpy(dip->label.name, AudioNsource, sizeof dip->label.name);
    981 		dip->un.e.num_mem = 2;
    982 		strlcpy(dip->un.e.member[0].label.name, AudioNmicrophone,
    983 		    sizeof dip->un.e.member[0].label.name);
    984 		dip->un.e.member[0].ord = HARMONY_IN_MIC;
    985 		strlcpy(dip->un.e.member[1].label.name, AudioNline,
    986 		    sizeof dip->un.e.member[1].label.name);
    987 		dip->un.e.member[1].ord = HARMONY_IN_LINE;
    988 		break;
    989 	case HARMONY_PORT_OUTPUT_SOURCE:
    990 		dip->type = AUDIO_MIXER_ENUM;
    991 		dip->mixer_class = HARMONY_PORT_MONITOR_CLASS;
    992 		dip->prev = dip->next = AUDIO_MIXER_LAST;
    993 		strlcpy(dip->label.name, AudioNoutput, sizeof dip->label.name);
    994 		dip->un.e.num_mem = 3;
    995 		strlcpy(dip->un.e.member[0].label.name, AudioNline,
    996 		    sizeof dip->un.e.member[0].label.name);
    997 		dip->un.e.member[0].ord = HARMONY_OUT_LINE;
    998 		strlcpy(dip->un.e.member[1].label.name, AudioNspeaker,
    999 		    sizeof dip->un.e.member[1].label.name);
   1000 		dip->un.e.member[1].ord = HARMONY_OUT_SPEAKER;
   1001 		strlcpy(dip->un.e.member[2].label.name, AudioNheadphone,
   1002 		    sizeof dip->un.e.member[2].label.name);
   1003 		dip->un.e.member[2].ord = HARMONY_OUT_HEADPHONE;
   1004 		break;
   1005 	case HARMONY_PORT_INPUT_CLASS:
   1006 		dip->type = AUDIO_MIXER_CLASS;
   1007 		dip->mixer_class = HARMONY_PORT_INPUT_CLASS;
   1008 		dip->prev = dip->next = AUDIO_MIXER_LAST;
   1009 		strlcpy(dip->label.name, AudioCinputs, sizeof dip->label.name);
   1010 		break;
   1011 	case HARMONY_PORT_OUTPUT_CLASS:
   1012 		dip->type = AUDIO_MIXER_CLASS;
   1013 		dip->mixer_class = HARMONY_PORT_INPUT_CLASS;
   1014 		dip->prev = dip->next = AUDIO_MIXER_LAST;
   1015 		strlcpy(dip->label.name, AudioCoutputs, sizeof dip->label.name);
   1016 		break;
   1017 	case HARMONY_PORT_MONITOR_CLASS:
   1018 		dip->type = AUDIO_MIXER_CLASS;
   1019 		dip->mixer_class = HARMONY_PORT_INPUT_CLASS;
   1020 		dip->prev = dip->next = AUDIO_MIXER_LAST;
   1021 		strlcpy(dip->label.name, AudioCmonitor, sizeof dip->label.name);
   1022 		break;
   1023 	case HARMONY_PORT_RECORD_CLASS:
   1024 		dip->type = AUDIO_MIXER_CLASS;
   1025 		dip->mixer_class = HARMONY_PORT_RECORD_CLASS;
   1026 		dip->prev = dip->next = AUDIO_MIXER_LAST;
   1027 		strlcpy(dip->label.name, AudioCrecord, sizeof dip->label.name);
   1028 		break;
   1029 	default:
   1030 		err = ENXIO;
   1031 		break;
   1032 	}
   1033 
   1034 	return err;
   1035 }
   1036 
   1037 void *
   1038 harmony_allocm(void *vsc, int dir, size_t size)
   1039 {
   1040 	struct harmony_softc *sc;
   1041 	struct harmony_dma *d;
   1042 	int rseg;
   1043 
   1044 	sc = vsc;
   1045 	d = kmem_alloc(sizeof(*d), KM_SLEEP);
   1046 
   1047 	if (bus_dmamap_create(sc->sc_dmat, size, 1, size, 0, BUS_DMA_WAITOK,
   1048 	    &d->d_map) != 0)
   1049 		goto fail1;
   1050 
   1051 	if (bus_dmamem_alloc(sc->sc_dmat, size, PAGE_SIZE, 0, &d->d_seg, 1,
   1052 	    &rseg, BUS_DMA_WAITOK) != 0)
   1053 		goto fail2;
   1054 
   1055 	if (bus_dmamem_map(sc->sc_dmat, &d->d_seg, 1, size, &d->d_kva,
   1056 	    BUS_DMA_WAITOK) != 0)
   1057 		goto fail3;
   1058 
   1059 	if (bus_dmamap_load(sc->sc_dmat, d->d_map, d->d_kva, size, NULL,
   1060 	    BUS_DMA_WAITOK) != 0)
   1061 		goto fail4;
   1062 
   1063 	d->d_next = sc->sc_dmas;
   1064 	sc->sc_dmas = d;
   1065 	d->d_size = size;
   1066 	return (d->d_kva);
   1067 
   1068 fail4:
   1069 	bus_dmamem_unmap(sc->sc_dmat, d->d_kva, size);
   1070 fail3:
   1071 	bus_dmamem_free(sc->sc_dmat, &d->d_seg, 1);
   1072 fail2:
   1073 	bus_dmamap_destroy(sc->sc_dmat, d->d_map);
   1074 fail1:
   1075 	kmem_free(d, sizeof(*d));
   1076 	return (NULL);
   1077 }
   1078 
   1079 void
   1080 harmony_freem(void *vsc, void *ptr, size_t size)
   1081 {
   1082 	struct harmony_softc *sc;
   1083 	struct harmony_dma *d, **dd;
   1084 
   1085 	sc = vsc;
   1086 	for (dd = &sc->sc_dmas; (d = *dd) != NULL; dd = &(*dd)->d_next) {
   1087 		if (d->d_kva != ptr)
   1088 			continue;
   1089 		bus_dmamap_unload(sc->sc_dmat, d->d_map);
   1090 		bus_dmamem_unmap(sc->sc_dmat, d->d_kva, d->d_size);
   1091 		bus_dmamem_free(sc->sc_dmat, &d->d_seg, 1);
   1092 		bus_dmamap_destroy(sc->sc_dmat, d->d_map);
   1093 		kmem_free(d, sizeof(*d));
   1094 		return;
   1095 	}
   1096 	printf("%s: free rogue pointer\n", device_xname(sc->sc_dv));
   1097 }
   1098 
   1099 size_t
   1100 harmony_round_buffersize(void *vsc, int direction, size_t size)
   1101 {
   1102 
   1103 	return ((size + HARMONY_BUFSIZE - 1) & (size_t)(-HARMONY_BUFSIZE));
   1104 }
   1105 
   1106 int
   1107 harmony_get_props(void *vsc)
   1108 {
   1109 
   1110 	return AUDIO_PROP_FULLDUPLEX;
   1111 }
   1112 
   1113 void
   1114 harmony_get_locks(void *vsc, kmutex_t **intr, kmutex_t **thread)
   1115 {
   1116 	struct harmony_softc *sc;
   1117 
   1118 	sc = vsc;
   1119 	*intr = &sc->sc_intr_lock;
   1120 	*thread = &sc->sc_lock;
   1121 }
   1122 
   1123 int
   1124 harmony_trigger_output(void *vsc, void *start, void *end, int blksize,
   1125     void (*intr)(void *), void *intrarg, const audio_params_t *param)
   1126 {
   1127 	struct harmony_softc *sc;
   1128 	struct harmony_channel *c;
   1129 	struct harmony_dma *d;
   1130 
   1131 	sc = vsc;
   1132 	c = &sc->sc_playback;
   1133 	for (d = sc->sc_dmas; d->d_kva != start; d = d->d_next)
   1134 		continue;
   1135 	if (d == NULL) {
   1136 		printf("%s: trigger_output: bad addr: %p\n",
   1137 		    device_xname(sc->sc_dv), start);
   1138 		return EINVAL;
   1139 	}
   1140 
   1141 	mutex_spin_enter(&sc->sc_intr_lock);
   1142 
   1143 	c->c_intr = intr;
   1144 	c->c_intrarg = intrarg;
   1145 	c->c_blksz = blksize;
   1146 	c->c_current = d;
   1147 	c->c_segsz = (char *)end - (char *)start;
   1148 	c->c_cnt = 0;
   1149 	c->c_lastaddr = d->d_map->dm_segs[0].ds_addr;
   1150 
   1151 	sc->sc_playing = 1;
   1152 
   1153 	harmony_start_pp(sc, 1);
   1154 	harmony_start_cp(sc, 0);
   1155 	harmony_intr_enable(sc);
   1156 
   1157 	mutex_spin_exit(&sc->sc_intr_lock);
   1158 
   1159 	return 0;
   1160 }
   1161 
   1162 void
   1163 harmony_start_cp(struct harmony_softc *sc, int start)
   1164 {
   1165 	struct harmony_channel *c;
   1166 	struct harmony_dma *d;
   1167 	bus_addr_t nextaddr;
   1168 	bus_size_t togo;
   1169 
   1170 	KASSERT(mutex_owned(&sc->sc_intr_lock));
   1171 
   1172 	c = &sc->sc_capture;
   1173 	if (sc->sc_capturing == 0)
   1174 		harmony_empty_input(sc);
   1175 	else {
   1176 		d = c->c_current;
   1177 		togo = c->c_segsz - c->c_cnt;
   1178 		if (togo == 0) {
   1179 			nextaddr = d->d_map->dm_segs[0].ds_addr;
   1180 			c->c_cnt = togo = c->c_blksz;
   1181 		} else {
   1182 			nextaddr = c->c_lastaddr;
   1183 			if (togo > c->c_blksz)
   1184 				togo = c->c_blksz;
   1185 			c->c_cnt += togo;
   1186 		}
   1187 
   1188 		bus_dmamap_sync(sc->sc_dmat, d->d_map,
   1189 		    nextaddr - d->d_map->dm_segs[0].ds_addr,
   1190 		    c->c_blksz, BUS_DMASYNC_PREWRITE);
   1191 
   1192 		WRITE_REG(sc, HARMONY_RNXTADD, nextaddr);
   1193 		if (start)
   1194 			c->c_theaddr = nextaddr;
   1195 		SYNC_REG(sc, HARMONY_RNXTADD, BUS_SPACE_BARRIER_WRITE);
   1196 		c->c_lastaddr = nextaddr + togo;
   1197 
   1198 		harmony_try_more(sc, HARMONY_RCURADD,
   1199 		    RCURADD_BUFMASK, &sc->sc_capture);
   1200 	}
   1201 
   1202 	callout_schedule(&sc->sc_acc_tmo, 1);
   1203 }
   1204 
   1205 void
   1206 harmony_start_pp(struct harmony_softc *sc, int start)
   1207 {
   1208 	struct harmony_channel *c;
   1209 	struct harmony_dma *d;
   1210 	bus_addr_t nextaddr;
   1211 	bus_size_t togo;
   1212 
   1213 	KASSERT(mutex_owned(&sc->sc_intr_lock));
   1214 
   1215 	c = &sc->sc_playback;
   1216 	if (sc->sc_playing == 0)
   1217 		harmony_empty_output(sc);
   1218 	else {
   1219 		d = c->c_current;
   1220 		togo = c->c_segsz - c->c_cnt;
   1221 		if (togo == 0) {
   1222 			nextaddr = d->d_map->dm_segs[0].ds_addr;
   1223 			c->c_cnt = togo = c->c_blksz;
   1224 		} else {
   1225 			nextaddr = c->c_lastaddr;
   1226 			if (togo > c->c_blksz)
   1227 				togo = c->c_blksz;
   1228 			c->c_cnt += togo;
   1229 		}
   1230 
   1231 		bus_dmamap_sync(sc->sc_dmat, d->d_map,
   1232 		    nextaddr - d->d_map->dm_segs[0].ds_addr,
   1233 		    c->c_blksz, BUS_DMASYNC_PREWRITE);
   1234 
   1235 		WRITE_REG(sc, HARMONY_PNXTADD, nextaddr);
   1236 		if (start)
   1237 			c->c_theaddr = nextaddr;
   1238 		SYNC_REG(sc, HARMONY_PNXTADD, BUS_SPACE_BARRIER_WRITE);
   1239 		c->c_lastaddr = nextaddr + togo;
   1240 
   1241 		harmony_try_more(sc, HARMONY_PCURADD,
   1242 		    PCURADD_BUFMASK, &sc->sc_playback);
   1243 	}
   1244 }
   1245 
   1246 int
   1247 harmony_trigger_input(void *vsc, void *start, void *end, int blksize,
   1248     void (*intr)(void *), void *intrarg, const audio_params_t *param)
   1249 {
   1250 	struct harmony_softc *sc = vsc;
   1251 	struct harmony_channel *c = &sc->sc_capture;
   1252 	struct harmony_dma *d;
   1253 
   1254 	KASSERT(mutex_owned(&sc->sc_intr_lock));
   1255 
   1256 	for (d = sc->sc_dmas; d->d_kva != start; d = d->d_next)
   1257 		continue;
   1258 	if (d == NULL) {
   1259 		printf("%s: trigger_input: bad addr: %p\n",
   1260 		    device_xname(sc->sc_dv), start);
   1261 		return EINVAL;
   1262 	}
   1263 
   1264 	c->c_intr = intr;
   1265 	c->c_intrarg = intrarg;
   1266 	c->c_blksz = blksize;
   1267 	c->c_current = d;
   1268 	c->c_segsz = (char *)end - (char *)start;
   1269 	c->c_cnt = 0;
   1270 	c->c_lastaddr = d->d_map->dm_segs[0].ds_addr;
   1271 
   1272 	sc->sc_capturing = 1;
   1273 
   1274 	harmony_start_cp(sc, 1);
   1275 	harmony_intr_enable(sc);
   1276 
   1277 	return 0;
   1278 }
   1279 
   1280 static const struct speed_struct {
   1281 	uint32_t speed;
   1282 	uint32_t bits;
   1283 } harmony_speeds[] = {
   1284 	{ 5125, CNTL_RATE_5125 },
   1285 	{ 6615, CNTL_RATE_6615 },
   1286 	{ 8000, CNTL_RATE_8000 },
   1287 	{ 9600, CNTL_RATE_9600 },
   1288 	{ 11025, CNTL_RATE_11025 },
   1289 	{ 16000, CNTL_RATE_16000 },
   1290 	{ 18900, CNTL_RATE_18900 },
   1291 	{ 22050, CNTL_RATE_22050 },
   1292 	{ 27428, CNTL_RATE_27428 },
   1293 	{ 32000, CNTL_RATE_32000 },
   1294 	{ 33075, CNTL_RATE_33075 },
   1295 	{ 37800, CNTL_RATE_37800 },
   1296 	{ 44100, CNTL_RATE_44100 },
   1297 	{ 48000, CNTL_RATE_48000 },
   1298 };
   1299 
   1300 uint32_t
   1301 harmony_speed_bits(struct harmony_softc *sc, u_int *speedp)
   1302 {
   1303 	int i, n, selected;
   1304 
   1305 	selected = -1;
   1306 	n = sizeof(harmony_speeds) / sizeof(harmony_speeds[0]);
   1307 
   1308 	if ((*speedp) <= harmony_speeds[0].speed)
   1309 		selected = 0;
   1310 	else if ((*speedp) >= harmony_speeds[n - 1].speed)
   1311 		selected = n - 1;
   1312 	else {
   1313 		for (i = 1; selected == -1 && i < n; i++) {
   1314 			if ((*speedp) == harmony_speeds[i].speed)
   1315 				selected = i;
   1316 			else if ((*speedp) < harmony_speeds[i].speed) {
   1317 				int diff1, diff2;
   1318 
   1319 				diff1 = (*speedp) - harmony_speeds[i - 1].speed;
   1320 				diff2 = harmony_speeds[i].speed - (*speedp);
   1321 				if (diff1 < diff2)
   1322 					selected = i - 1;
   1323 				else
   1324 					selected = i;
   1325 			}
   1326 		}
   1327 	}
   1328 
   1329 	if (selected == -1)
   1330 		selected = 2;
   1331 
   1332 	*speedp = harmony_speeds[selected].speed;
   1333 	return harmony_speeds[selected].bits;
   1334 }
   1335 
   1336 int
   1337 harmony_set_gainctl(struct harmony_softc *sc)
   1338 {
   1339 	uint32_t bits, mask, val, old;
   1340 
   1341 	/* XXX leave these bits alone or the chip will not come out of CNTL */
   1342 	bits = GAINCTL_LE | GAINCTL_HE | GAINCTL_SE | GAINCTL_IS_MASK;
   1343 
   1344 	/* input level */
   1345 	bits |= ((sc->sc_input_lvl.left >> (8 - GAINCTL_INPUT_BITS)) <<
   1346 	    GAINCTL_INPUT_LEFT_S) & GAINCTL_INPUT_LEFT_M;
   1347 	bits |= ((sc->sc_input_lvl.right >> (8 - GAINCTL_INPUT_BITS)) <<
   1348 	    GAINCTL_INPUT_RIGHT_S) & GAINCTL_INPUT_RIGHT_M;
   1349 
   1350 	/* output level (inverted) */
   1351 	mask = (1 << GAINCTL_OUTPUT_BITS) - 1;
   1352 	val = mask - (sc->sc_output_lvl.left >> (8 - GAINCTL_OUTPUT_BITS));
   1353 	bits |= (val << GAINCTL_OUTPUT_LEFT_S) & GAINCTL_OUTPUT_LEFT_M;
   1354 	val = mask - (sc->sc_output_lvl.right >> (8 - GAINCTL_OUTPUT_BITS));
   1355 	bits |= (val << GAINCTL_OUTPUT_RIGHT_S) & GAINCTL_OUTPUT_RIGHT_M;
   1356 
   1357 	/* monitor level (inverted) */
   1358 	mask = (1 << GAINCTL_MONITOR_BITS) - 1;
   1359 	val = mask - (sc->sc_monitor_lvl.left >> (8 - GAINCTL_MONITOR_BITS));
   1360 	bits |= (val << GAINCTL_MONITOR_S) & GAINCTL_MONITOR_M;
   1361 
   1362 	/* XXX messing with these causes CNTL_C to get stuck... grr. */
   1363 	bits &= ~GAINCTL_IS_MASK;
   1364 	if (sc->sc_in_port == HARMONY_IN_MIC)
   1365 		bits |= GAINCTL_IS_LINE;
   1366 	else
   1367 		bits |= GAINCTL_IS_MICROPHONE;
   1368 
   1369 	/* XXX messing with these causes CNTL_C to get stuck... grr. */
   1370 	bits &= ~(GAINCTL_LE | GAINCTL_HE | GAINCTL_SE);
   1371 	if (sc->sc_out_port == HARMONY_OUT_LINE)
   1372 		bits |= GAINCTL_LE;
   1373 	else if (sc->sc_out_port == HARMONY_OUT_SPEAKER)
   1374 		bits |= GAINCTL_SE;
   1375 	else
   1376 		bits |= GAINCTL_HE;
   1377 
   1378 	mask = GAINCTL_LE | GAINCTL_HE | GAINCTL_SE | GAINCTL_IS_MASK;
   1379 	old = bus_space_read_4(sc->sc_bt, sc->sc_bh, HARMONY_GAINCTL);
   1380 	bus_space_write_4(sc->sc_bt, sc->sc_bh, HARMONY_GAINCTL, bits);
   1381 	if ((old & mask) != (bits & mask))
   1382 		return 1;
   1383 	return 0;
   1384 }
   1385 
   1386 void
   1387 harmony_try_more(struct harmony_softc *sc, int curadd, int bufmask,
   1388 	struct harmony_channel *c)
   1389 {
   1390 	struct harmony_dma *d;
   1391 	uint32_t cur;
   1392 	int i, nsegs;
   1393 
   1394 	d = c->c_current;
   1395 	cur = bus_space_read_4(sc->sc_bt, sc->sc_bh, curadd);
   1396 	cur &= bufmask;
   1397 	nsegs = 0;
   1398 
   1399 #ifdef DIAGNOSTIC
   1400 	if (cur < d->d_map->dm_segs[0].ds_addr ||
   1401 	    cur >= (d->d_map->dm_segs[0].ds_addr + c->c_segsz))
   1402 		panic("%s: bad current %x < %lx || %x > %lx",
   1403 		    device_xname(sc->sc_dv), cur,
   1404 		    d->d_map->dm_segs[0].ds_addr, cur,
   1405 		    d->d_map->dm_segs[0].ds_addr + c->c_segsz);
   1406 #endif /* DIAGNOSTIC */
   1407 
   1408 	if (cur > c->c_theaddr) {
   1409 		nsegs = (cur - c->c_theaddr) / HARMONY_BUFSIZE;
   1410 	} else if (cur < c->c_theaddr) {
   1411 		nsegs = (d->d_map->dm_segs[0].ds_addr + c->c_segsz -
   1412 		    c->c_theaddr) / HARMONY_BUFSIZE;
   1413 		nsegs += (cur - d->d_map->dm_segs[0].ds_addr) /
   1414 		    HARMONY_BUFSIZE;
   1415 	}
   1416 
   1417 	if (nsegs != 0 && c->c_intr != NULL) {
   1418 		for (i = 0; i < nsegs; i++)
   1419 			(*c->c_intr)(c->c_intrarg);
   1420 		c->c_theaddr = cur;
   1421 	}
   1422 }
   1423