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