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