Home | History | Annotate | Line # | Download | only in mace
      1 /* $NetBSD: mavb.c,v 1.14 2019/06/07 13:24:21 isaki Exp $ */
      2 /* $OpenBSD: mavb.c,v 1.6 2005/04/15 13:05:14 mickey Exp $ */
      3 
      4 /*
      5  * Copyright (c) 2005 Mark Kettenis
      6  *
      7  * Permission to use, copy, modify, and distribute this software for any
      8  * purpose with or without fee is hereby granted, provided that the above
      9  * copyright notice and this permission notice appear in all copies.
     10  *
     11  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
     12  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
     13  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
     14  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
     15  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
     16  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
     17  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
     18  */
     19 
     20 #include <sys/param.h>
     21 #include <sys/systm.h>
     22 #include <sys/device.h>
     23 #include <sys/kernel.h>
     24 #include <sys/kmem.h>
     25 #include <sys/callout.h>
     26 
     27 #include <sys/bus.h>
     28 #include <machine/intr.h>
     29 #include <machine/autoconf.h>
     30 
     31 #include <sys/audioio.h>
     32 #include <dev/audio/audio_if.h>
     33 
     34 #include <arch/sgimips/mace/macevar.h>
     35 #include <arch/sgimips/mace/macereg.h>
     36 #include <arch/sgimips/mace/mavbreg.h>
     37 
     38 #include <dev/ic/ad1843reg.h>
     39 
     40 #undef MAVB_DEBUG
     41 
     42 #ifdef MAVB_DEBUG
     43 #define DPRINTF(l,x)	do { if (mavb_debug & (l)) printf x; } while (0)
     44 #define MAVB_DEBUG_INTR		0x0100
     45 int mavb_debug = ~MAVB_DEBUG_INTR;
     46 #else
     47 #define DPRINTF(l,x)	/* nothing */
     48 #endif
     49 
     50 /* Repeat delays for volume buttons.  */
     51 #define MAVB_VOLUME_BUTTON_REPEAT_DEL1	400	/* 400ms to start repeating */
     52 #define MAVB_VOLUME_BUTTON_REPEAT_DELN  100	/* 100ms between repeats */
     53 
     54 /* XXX We need access to some of the MACE ISA registers.  */
     55 #define MAVB_ISA_NREGS				0x20
     56 
     57 /*
     58  * AD1843 Mixer.
     59  */
     60 
     61 enum {
     62 	AD1843_RECORD_CLASS,
     63 	AD1843_ADC_SOURCE,	/* ADC Source Select */
     64 	AD1843_ADC_GAIN,	/* ADC Input Gain */
     65 
     66 	AD1843_INPUT_CLASS,
     67 	AD1843_DAC1_GAIN,	/* DAC1 Analog/Digital Gain/Attenuation */
     68 	AD1843_DAC1_MUTE,	/* DAC1 Analog Mute */
     69 	AD1843_DAC2_GAIN,	/* DAC2 Mix Gain */
     70 	AD1843_AUX1_GAIN,	/* Auxilliary 1 Mix Gain */
     71 	AD1843_AUX2_GAIN,	/* Auxilliary 2 Mix Gain */
     72 	AD1843_AUX3_GAIN,	/* Auxilliary 3 Mix Gain */
     73 	AD1843_MIC_GAIN,	/* Microphone Mix Gain */
     74 	AD1843_MONO_GAIN,	/* Mono Mix Gain */
     75 	AD1843_DAC2_MUTE,	/* DAC2 Mix Mute */
     76 	AD1843_AUX1_MUTE,	/* Auxilliary 1 Mix Mute */
     77 	AD1843_AUX2_MUTE,	/* Auxilliary 2 Mix Mute */
     78 	AD1843_AUX3_MUTE,	/* Auxilliary 3 Mix Mute */
     79 	AD1843_MIC_MUTE,	/* Microphone Mix Mute */
     80 	AD1843_MONO_MUTE,	/* Mono Mix Mute */
     81 	AD1843_SUM_MUTE,	/* Sum Mute */
     82 
     83 	AD1843_OUTPUT_CLASS,
     84 	AD1843_MNO_MUTE,	/* Mono Output Mute */
     85 	AD1843_HPO_MUTE		/* Headphone Output Mute */
     86 };
     87 
     88 /* ADC Source Select.  The order matches the hardware bits.  */
     89 const char *ad1843_source[] = {
     90 	AudioNline,
     91 	AudioNmicrophone,
     92 	AudioNaux "1",
     93 	AudioNaux "2",
     94 	AudioNaux "3",
     95 	AudioNmono,
     96 	AudioNdac "1",
     97 	AudioNdac "2"
     98 };
     99 
    100 /* Mix Control.  The order matches the hardware register numbering.  */
    101 const char *ad1843_input[] = {
    102 	AudioNdac "2",		/* AD1843_DAC2__TO_MIXER */
    103 	AudioNaux "1",
    104 	AudioNaux "2",
    105 	AudioNaux "3",
    106 	AudioNmicrophone,
    107 	AudioNmono		/* AD1843_MISC_SETTINGS */
    108 };
    109 
    110 static const struct audio_format mavb_formats[] = {
    111 	{
    112 		.mode		= AUMODE_PLAY,
    113 		.encoding	= AUDIO_ENCODING_SLINEAR_BE,
    114 		.validbits	= 24,
    115 		.precision	= 32,
    116 		.channels	= 2,
    117 		.channel_mask	= AUFMT_STEREO,
    118 		.frequency_type	= 0,
    119 		.frequency	= { 8000, 48000 },
    120 	},
    121 };
    122 #define MAVB_NFORMATS __arraycount(mavb_formats)
    123 
    124 struct mavb_softc {
    125 	device_t sc_dev;
    126 	kmutex_t sc_lock;
    127 	kmutex_t sc_intr_lock;
    128 	bus_space_tag_t sc_st;
    129 	bus_space_handle_t sc_sh;
    130 	bus_dma_tag_t sc_dmat;
    131 	bus_dmamap_t sc_dmamap;
    132 
    133 	/* XXX We need access to some of the MACE ISA registers.  */
    134 	bus_space_handle_t sc_isash;
    135 
    136 #define MAVB_ISA_RING_SIZE		0x1000
    137 	uint8_t *sc_ring;
    138 
    139 	uint8_t *sc_start, *sc_end;
    140 	int sc_blksize;
    141 	void (*sc_intr)(void *);
    142 	void *sc_intrarg;
    143 
    144 	void *sc_get;
    145 	int sc_count;
    146 
    147 	u_long sc_play_rate;
    148 	u_int sc_play_format;
    149 
    150 	struct callout sc_volume_button_ch;
    151 };
    152 
    153 typedef uint64_t ad1843_addr_t;
    154 
    155 uint16_t ad1843_reg_read(struct mavb_softc *, ad1843_addr_t);
    156 uint16_t ad1843_reg_write(struct mavb_softc *, ad1843_addr_t, uint16_t);
    157 void ad1843_dump_regs(struct mavb_softc *);
    158 
    159 int mavb_match(device_t, cfdata_t, void *);
    160 void mavb_attach(device_t, device_t, void *);
    161 
    162 CFATTACH_DECL_NEW(mavb, sizeof(struct mavb_softc),
    163     mavb_match, mavb_attach, NULL, NULL);
    164 
    165 int mavb_query_format(void *, audio_format_query_t *);
    166 int mavb_set_format(void *, int,
    167 		    const audio_params_t *, const audio_params_t *,
    168 		    audio_filter_reg_t *, audio_filter_reg_t *);
    169 int mavb_round_blocksize(void *hdl, int, int, const audio_params_t *);
    170 int mavb_halt_output(void *);
    171 int mavb_halt_input(void *);
    172 int mavb_getdev(void *, struct audio_device *);
    173 int mavb_set_port(void *, struct mixer_ctrl *);
    174 int mavb_get_port(void *, struct mixer_ctrl *);
    175 int mavb_query_devinfo(void *, struct mixer_devinfo *);
    176 int mavb_get_props(void *);
    177 int mavb_trigger_output(void *, void *, void *, int, void (*)(void *),
    178 			void *, const audio_params_t *);
    179 int mavb_trigger_input(void *, void *, void *, int, void (*)(void *),
    180 		       void *, const audio_params_t *);
    181 void mavb_get_locks(void *, kmutex_t **, kmutex_t **);
    182 
    183 struct audio_hw_if mavb_sa_hw_if = {
    184 	.query_format		= mavb_query_format,
    185 	.set_format		= mavb_set_format,
    186 	.round_blocksize	= mavb_round_blocksize,
    187 	.halt_output		= mavb_halt_output,
    188 	.halt_input		= mavb_halt_input,
    189 	.getdev			= mavb_getdev,
    190 	.set_port		= mavb_set_port,
    191 	.get_port		= mavb_get_port,
    192 	.query_devinfo		= mavb_query_devinfo,
    193 	.get_props		= mavb_get_props,
    194 	.trigger_output		= mavb_trigger_output,
    195 	.trigger_input		= mavb_trigger_input,
    196 	.get_locks		= mavb_get_locks,
    197 };
    198 
    199 struct audio_device mavb_device = {
    200 	"A3",
    201 	"",
    202 	"mavb"
    203 };
    204 
    205 static void
    206 mavb_internal_to_slinear24_32(audio_filter_arg_t *arg)
    207 {
    208 	const aint_t *src;
    209 	uint32_t *dst;
    210 	u_int sample_count;
    211 	u_int i;
    212 
    213 	src = arg->src;
    214 	dst = arg->dst;
    215 	sample_count = arg->count * arg->srcfmt->channels;
    216 	for (i = 0; i < sample_count; i++) {
    217 		*dst++ = (*src++) << 8;
    218 	}
    219 }
    220 
    221 int
    222 mavb_query_format(void *hdl, audio_format_query_t *afp)
    223 {
    224 
    225 	return audio_query_format(mavb_formats, MAVB_NFORMATS, afp);
    226 }
    227 
    228 static int
    229 mavb_set_play_rate(struct mavb_softc *sc, u_long sample_rate)
    230 {
    231 
    232 	KASSERT((4000 <= sample_rate && sample_rate <= 48000));
    233 
    234 	if (sc->sc_play_rate != sample_rate) {
    235 		ad1843_reg_write(sc, AD1843_CLOCK2_SAMPLE_RATE, sample_rate);
    236 		sc->sc_play_rate = sample_rate;
    237 	}
    238 	return 0;
    239 }
    240 
    241 static int
    242 mavb_set_play_format(struct mavb_softc *sc, u_int encoding)
    243 {
    244 	uint16_t value;
    245 	u_int format;
    246 
    247 	switch(encoding) {
    248 	case AUDIO_ENCODING_SLINEAR_BE:
    249 		format = AD1843_PCM16;
    250 		break;
    251 	default:
    252 		return EINVAL;
    253 	}
    254 
    255 	if (sc->sc_play_format != format) {
    256 		value = ad1843_reg_read(sc, AD1843_SERIAL_INTERFACE);
    257 		value &= ~AD1843_DA1F_MASK;
    258 		value |= (format << AD1843_DA1F_SHIFT);
    259 		ad1843_reg_write(sc, AD1843_SERIAL_INTERFACE, value);
    260 		sc->sc_play_format = format;
    261 	}
    262 	return 0;
    263 }
    264 
    265 int
    266 mavb_set_format(void *hdl, int setmode,
    267     const audio_params_t *play, const audio_params_t *rec,
    268     audio_filter_reg_t *pfil, audio_filter_reg_t *rfil)
    269 {
    270 	struct mavb_softc *sc = (struct mavb_softc *)hdl;
    271 	int error;
    272 
    273 	DPRINTF(1, ("%s: %s: sample=%u precision=%d channels=%d\n",
    274 	    device_xname(sc->sc_dev), __func__,
    275 	    play->sample_rate, play->precision, play->channels));
    276 
    277 	if (setmode & AUMODE_PLAY) {
    278 		pfil->codec = mavb_internal_to_slinear24_32;
    279 
    280 		error = mavb_set_play_rate(sc, play->sample_rate);
    281 		if (error)
    282 			return error;
    283 
    284 		error = mavb_set_play_format(sc, play->encoding);
    285 		if (error)
    286 			return error;
    287 	}
    288 
    289 #if 0
    290 	if (setmode & AUMODE_RECORD) {
    291 	}
    292 #endif
    293 
    294 	return 0;
    295 }
    296 
    297 int
    298 mavb_round_blocksize(void *hdl, int bs, int mode, const audio_params_t *p)
    299 {
    300 
    301 	/* Block size should be a multiple of 32.  */
    302 	return (bs + 0x1f) & ~0x1f;
    303 }
    304 
    305 int
    306 mavb_halt_output(void *hdl)
    307 {
    308 	struct mavb_softc *sc = (struct mavb_softc *)hdl;
    309 
    310 	DPRINTF(1, ("%s: mavb_halt_output called\n", device_xname(sc->sc_dev)));
    311 
    312 	bus_space_write_8(sc->sc_st, sc->sc_sh, MAVB_CHANNEL2_CONTROL, 0);
    313 	return 0;
    314 }
    315 
    316 int
    317 mavb_halt_input(void *hdl)
    318 {
    319 
    320 	return 0;
    321 }
    322 
    323 int
    324 mavb_getdev(void *hdl, struct audio_device *ret)
    325 {
    326 
    327 	*ret = mavb_device;
    328 	return 0;
    329 }
    330 
    331 int
    332 mavb_set_port(void *hdl, struct mixer_ctrl *mc)
    333 {
    334 	struct mavb_softc *sc = (struct mavb_softc *)hdl;
    335 	u_char left, right;
    336 	ad1843_addr_t reg;
    337 	uint16_t value;
    338 
    339 	DPRINTF(1, ("%s: mavb_set_port: dev=%d\n", device_xname(sc->sc_dev),
    340 	    mc->dev));
    341 
    342 	switch (mc->dev) {
    343 	case AD1843_ADC_SOURCE:
    344 		value = ad1843_reg_read(sc, AD1843_ADC_SOURCE_GAIN);
    345 		value &= ~(AD1843_LSS_MASK | AD1843_RSS_MASK);
    346 		value |= ((mc->un.ord << AD1843_LSS_SHIFT) & AD1843_LSS_MASK);
    347 		value |= ((mc->un.ord << AD1843_RSS_SHIFT) & AD1843_RSS_MASK);
    348 		ad1843_reg_write(sc, AD1843_ADC_SOURCE_GAIN, value);
    349 		break;
    350 	case AD1843_ADC_GAIN:
    351 		left = mc->un.value.level[AUDIO_MIXER_LEVEL_LEFT];
    352 		right = mc->un.value.level[AUDIO_MIXER_LEVEL_RIGHT];
    353 		value = ad1843_reg_read(sc, AD1843_ADC_SOURCE_GAIN);
    354 		value &= ~(AD1843_LIG_MASK | AD1843_RIG_MASK);
    355 		value |= ((left >> 4) << AD1843_LIG_SHIFT);
    356 		value |= ((right >> 4) << AD1843_RIG_SHIFT);
    357 		ad1843_reg_write(sc, AD1843_ADC_SOURCE_GAIN, value);
    358 		break;
    359 
    360 	case AD1843_DAC1_GAIN:
    361 		left = AUDIO_MAX_GAIN -
    362 		    mc->un.value.level[AUDIO_MIXER_LEVEL_LEFT];
    363 		right = AUDIO_MAX_GAIN -
    364                     mc->un.value.level[AUDIO_MIXER_LEVEL_RIGHT];
    365 		value = ad1843_reg_read(sc, AD1843_DAC1_ANALOG_GAIN);
    366 		value &= ~(AD1843_LDA1G_MASK | AD1843_RDA1G_MASK);
    367 		value |= ((left >> 2) << AD1843_LDA1G_SHIFT);
    368 		value |= ((right >> 2) << AD1843_RDA1G_SHIFT);
    369 		ad1843_reg_write(sc, AD1843_DAC1_ANALOG_GAIN, value);
    370 		break;
    371 	case AD1843_DAC1_MUTE:
    372 		value = ad1843_reg_read(sc, AD1843_DAC1_ANALOG_GAIN);
    373 		if (mc->un.ord == 0)
    374 			value &= ~(AD1843_LDA1GM | AD1843_RDA1GM);
    375 		else
    376 			value |= (AD1843_LDA1GM | AD1843_RDA1GM);
    377 		ad1843_reg_write(sc, AD1843_DAC1_ANALOG_GAIN, value);
    378 		break;
    379 
    380 	case AD1843_DAC2_GAIN:
    381 	case AD1843_AUX1_GAIN:
    382 	case AD1843_AUX2_GAIN:
    383 	case AD1843_AUX3_GAIN:
    384 	case AD1843_MIC_GAIN:
    385 		left = AUDIO_MAX_GAIN -
    386 		    mc->un.value.level[AUDIO_MIXER_LEVEL_LEFT];
    387 		right = AUDIO_MAX_GAIN -
    388                     mc->un.value.level[AUDIO_MIXER_LEVEL_RIGHT];
    389 		reg = AD1843_DAC2_TO_MIXER + mc->dev - AD1843_DAC2_GAIN;
    390 		value = ad1843_reg_read(sc, reg);
    391 		value &= ~(AD1843_LD2M_MASK | AD1843_RD2M_MASK);
    392 		value |= ((left >> 3) << AD1843_LD2M_SHIFT);
    393 		value |= ((right >> 3) << AD1843_RD2M_SHIFT);
    394 		ad1843_reg_write(sc, reg, value);
    395 		break;
    396 	case AD1843_MONO_GAIN:
    397 		left = AUDIO_MAX_GAIN -
    398 		    mc->un.value.level[AUDIO_MIXER_LEVEL_MONO];
    399 		value = ad1843_reg_read(sc, AD1843_MISC_SETTINGS);
    400 		value &= ~AD1843_MNM_MASK;
    401 		value |= ((left >> 3) << AD1843_MNM_SHIFT);
    402 		ad1843_reg_write(sc, AD1843_MISC_SETTINGS, value);
    403 		break;
    404 	case AD1843_DAC2_MUTE:
    405 	case AD1843_AUX1_MUTE:
    406 	case AD1843_AUX2_MUTE:
    407 	case AD1843_AUX3_MUTE:
    408 	case AD1843_MIC_MUTE:
    409 	case AD1843_MONO_MUTE:	/* matches left channel */
    410 		reg = AD1843_DAC2_TO_MIXER + mc->dev - AD1843_DAC2_MUTE;
    411 		value = ad1843_reg_read(sc, reg);
    412 		if (mc->un.ord == 0)
    413 			value &= ~(AD1843_LD2MM | AD1843_RD2MM);
    414 		else
    415 			value |= (AD1843_LD2MM | AD1843_RD2MM);
    416 		ad1843_reg_write(sc, reg, value);
    417 		break;
    418 
    419 	case AD1843_SUM_MUTE:
    420 		value = ad1843_reg_read(sc, AD1843_MISC_SETTINGS);
    421 		if (mc->un.ord == 0)
    422 			value &= ~AD1843_SUMM;
    423 		else
    424 			value |= AD1843_SUMM;
    425 		ad1843_reg_write(sc, AD1843_MISC_SETTINGS, value);
    426 		break;
    427 
    428 	case AD1843_MNO_MUTE:
    429 		value = ad1843_reg_read(sc, AD1843_MISC_SETTINGS);
    430 		if (mc->un.ord == 0)
    431 			value &= ~AD1843_MNOM;
    432 		else
    433 			value |= AD1843_MNOM;
    434 		ad1843_reg_write(sc, AD1843_MISC_SETTINGS, value);
    435 		break;
    436 
    437 	case AD1843_HPO_MUTE:
    438 		value = ad1843_reg_read(sc, AD1843_MISC_SETTINGS);
    439 		if (mc->un.ord == 0)
    440 			value &= ~AD1843_HPOM;
    441 		else
    442 			value |= AD1843_HPOM;
    443 		ad1843_reg_write(sc, AD1843_MISC_SETTINGS, value);
    444 		value = ad1843_reg_read(sc, AD1843_MISC_SETTINGS);
    445 		break;
    446 
    447 	default:
    448 		return EINVAL;
    449 	}
    450 
    451 	return 0;
    452 }
    453 
    454 int
    455 mavb_get_port(void *hdl, struct mixer_ctrl *mc)
    456 {
    457 	struct mavb_softc *sc = (struct mavb_softc *)hdl;
    458 	u_char left, right;
    459 	ad1843_addr_t reg;
    460 	uint16_t value;
    461 
    462 	DPRINTF(1, ("%s: mavb_get_port: dev=%d\n", device_xname(sc->sc_dev),
    463 	    mc->dev));
    464 
    465 	switch (mc->dev) {
    466 	case AD1843_ADC_SOURCE:
    467 		value = ad1843_reg_read(sc, AD1843_ADC_SOURCE_GAIN);
    468 		mc->un.ord = (value & AD1843_LSS_MASK) >> AD1843_LSS_SHIFT;
    469 		break;
    470 	case AD1843_ADC_GAIN:
    471 		value = ad1843_reg_read(sc, AD1843_ADC_SOURCE_GAIN);
    472 		left = (value & AD1843_LIG_MASK) >> AD1843_LIG_SHIFT;
    473 		right = (value & AD1843_RIG_MASK) >> AD1843_RIG_SHIFT;
    474 		mc->un.value.level[AUDIO_MIXER_LEVEL_LEFT] =
    475 		    (left << 4) | left;
    476 		mc->un.value.level[AUDIO_MIXER_LEVEL_RIGHT] =
    477 		    (right << 2) | right;
    478 		break;
    479 
    480 	case AD1843_DAC1_GAIN:
    481 		value = ad1843_reg_read(sc, AD1843_DAC1_ANALOG_GAIN);
    482 		left = (value & AD1843_LDA1G_MASK) >> AD1843_LDA1G_SHIFT;
    483 		right = (value & AD1843_RDA1G_MASK) >> AD1843_RDA1G_SHIFT;
    484 		mc->un.value.level[AUDIO_MIXER_LEVEL_LEFT] =
    485 		    AUDIO_MAX_GAIN - (left << 2);
    486 		mc->un.value.level[AUDIO_MIXER_LEVEL_RIGHT] =
    487 		    AUDIO_MAX_GAIN - (right << 2);
    488 		break;
    489 	case AD1843_DAC1_MUTE:
    490 		value = ad1843_reg_read(sc, AD1843_DAC1_ANALOG_GAIN);
    491 		mc->un.ord = (value & AD1843_LDA1GM) ? 1 : 0;
    492 		break;
    493 
    494 	case AD1843_DAC2_GAIN:
    495 	case AD1843_AUX1_GAIN:
    496 	case AD1843_AUX2_GAIN:
    497 	case AD1843_AUX3_GAIN:
    498 	case AD1843_MIC_GAIN:
    499 		reg = AD1843_DAC2_TO_MIXER + mc->dev - AD1843_DAC2_GAIN;
    500 		value = ad1843_reg_read(sc, reg);
    501 		left = (value & AD1843_LD2M_MASK) >> AD1843_LD2M_SHIFT;
    502 		right = (value & AD1843_RD2M_MASK) >> AD1843_RD2M_SHIFT;
    503 		mc->un.value.level[AUDIO_MIXER_LEVEL_LEFT] =
    504 		    AUDIO_MAX_GAIN - (left << 3);
    505 		mc->un.value.level[AUDIO_MIXER_LEVEL_RIGHT] =
    506 		    AUDIO_MAX_GAIN - (right << 3);
    507 		break;
    508 	case AD1843_MONO_GAIN:
    509 		if (mc->un.value.num_channels != 1)
    510 			return EINVAL;
    511 
    512 		value = ad1843_reg_read(sc, AD1843_MISC_SETTINGS);
    513 		left = (value & AD1843_MNM_MASK) >> AD1843_MNM_SHIFT;
    514 		mc->un.value.level[AUDIO_MIXER_LEVEL_MONO] =
    515 		    AUDIO_MAX_GAIN - (left << 3);
    516 		break;
    517 	case AD1843_DAC2_MUTE:
    518 	case AD1843_AUX1_MUTE:
    519 	case AD1843_AUX2_MUTE:
    520 	case AD1843_AUX3_MUTE:
    521 	case AD1843_MIC_MUTE:
    522 	case AD1843_MONO_MUTE:	/* matches left channel */
    523 		reg = AD1843_DAC2_TO_MIXER + mc->dev - AD1843_DAC2_MUTE;
    524 		value = ad1843_reg_read(sc, reg);
    525 		mc->un.ord = (value & AD1843_LD2MM) ? 1 : 0;
    526 		break;
    527 
    528 	case AD1843_SUM_MUTE:
    529 		value = ad1843_reg_read(sc, AD1843_MISC_SETTINGS);
    530 		mc->un.ord = (value & AD1843_SUMM) ? 1 : 0;
    531 		break;
    532 
    533 	case AD1843_MNO_MUTE:
    534 		value = ad1843_reg_read(sc, AD1843_MISC_SETTINGS);
    535 		mc->un.ord = (value & AD1843_MNOM) ? 1 : 0;
    536 		break;
    537 
    538 	case AD1843_HPO_MUTE:
    539 		value = ad1843_reg_read(sc, AD1843_MISC_SETTINGS);
    540 		mc->un.ord = (value & AD1843_HPOM) ? 1 : 0;
    541 		break;
    542 
    543 	default:
    544 		return EINVAL;
    545 	}
    546 
    547 	return 0;
    548 }
    549 
    550 int
    551 mavb_query_devinfo(void *hdl, struct mixer_devinfo *di)
    552 {
    553 	int i;
    554 
    555 	di->prev = di->next = AUDIO_MIXER_LAST;
    556 
    557 	switch (di->index) {
    558 	case AD1843_RECORD_CLASS:
    559 		di->type = AUDIO_MIXER_CLASS;
    560 		di->mixer_class = AD1843_RECORD_CLASS;
    561 		strlcpy(di->label.name, AudioCrecord, sizeof di->label.name);
    562 		break;
    563 
    564 	case AD1843_ADC_SOURCE:
    565 		di->type = AUDIO_MIXER_ENUM;
    566 		di->mixer_class = AD1843_RECORD_CLASS;
    567 		di->next = AD1843_ADC_GAIN;
    568 		strlcpy(di->label.name, AudioNsource, sizeof di->label.name);
    569 		di->un.e.num_mem =
    570 			sizeof ad1843_source / sizeof ad1843_source[1];
    571 		for (i = 0; i < di->un.e.num_mem; i++) {
    572 			strlcpy(di->un.e.member[i].label.name,
    573                             ad1843_source[i],
    574 			    sizeof di->un.e.member[0].label.name);
    575 			di->un.e.member[i].ord = i;
    576 		}
    577 		break;
    578 	case AD1843_ADC_GAIN:
    579 		di->type = AUDIO_MIXER_VALUE;
    580 		di->mixer_class = AD1843_RECORD_CLASS;
    581 		di->prev = AD1843_ADC_SOURCE;
    582 		strlcpy(di->label.name, AudioNvolume, sizeof di->label.name);
    583 		di->un.v.num_channels = 2;
    584 		strlcpy(di->un.v.units.name, AudioNvolume,
    585 		    sizeof di->un.v.units.name);
    586 		break;
    587 
    588 	case AD1843_INPUT_CLASS:
    589 		di->type = AUDIO_MIXER_CLASS;
    590 		di->mixer_class = AD1843_INPUT_CLASS;
    591 		strlcpy(di->label.name, AudioCinputs, sizeof di->label.name);
    592 		break;
    593 
    594 	case AD1843_DAC1_GAIN:
    595 		di->type = AUDIO_MIXER_VALUE;
    596 		di->mixer_class = AD1843_OUTPUT_CLASS;
    597 		di->next = AD1843_DAC1_MUTE;
    598 		strlcpy(di->label.name, AudioNmaster, sizeof di->label.name);
    599 		di->un.v.num_channels = 2;
    600 		strlcpy(di->un.v.units.name, AudioNvolume,
    601 		    sizeof di->un.v.units.name);
    602 		break;
    603 	case AD1843_DAC1_MUTE:
    604 		di->type = AUDIO_MIXER_ENUM;
    605 		di->mixer_class = AD1843_OUTPUT_CLASS;
    606 		di->prev = AD1843_DAC1_GAIN;
    607 		strlcpy(di->label.name, AudioNmute, sizeof di->label.name);
    608 		di->un.e.num_mem = 2;
    609 		strlcpy(di->un.e.member[0].label.name, AudioNoff,
    610 		    sizeof di->un.e.member[0].label.name);
    611 		di->un.e.member[0].ord = 0;
    612 		strlcpy(di->un.e.member[1].label.name, AudioNon,
    613 		    sizeof di->un.e.member[1].label.name);
    614 		di->un.e.member[1].ord = 1;
    615 		break;
    616 
    617 	case AD1843_DAC2_GAIN:
    618 	case AD1843_AUX1_GAIN:
    619 	case AD1843_AUX2_GAIN:
    620 	case AD1843_AUX3_GAIN:
    621 	case AD1843_MIC_GAIN:
    622 	case AD1843_MONO_GAIN:
    623 		di->type = AUDIO_MIXER_VALUE;
    624 		di->mixer_class = AD1843_INPUT_CLASS;
    625 		di->next = di->index + AD1843_DAC2_MUTE - AD1843_DAC2_GAIN;
    626 		strlcpy(di->label.name,
    627                     ad1843_input[di->index - AD1843_DAC2_GAIN],
    628 		    sizeof di->label.name);
    629 		if (di->index == AD1843_MONO_GAIN)
    630 			di->un.v.num_channels = 1;
    631 		else
    632 			di->un.v.num_channels = 2;
    633 		strlcpy(di->un.v.units.name, AudioNvolume,
    634 		    sizeof di->un.v.units.name);
    635 		break;
    636 	case AD1843_DAC2_MUTE:
    637 	case AD1843_AUX1_MUTE:
    638 	case AD1843_AUX2_MUTE:
    639 	case AD1843_AUX3_MUTE:
    640 	case AD1843_MIC_MUTE:
    641 	case AD1843_MONO_MUTE:
    642 		di->type = AUDIO_MIXER_ENUM;
    643 		di->mixer_class = AD1843_INPUT_CLASS;
    644 		di->prev = di->index + AD1843_DAC2_GAIN - AD1843_DAC2_MUTE;
    645 		strlcpy(di->label.name, AudioNmute, sizeof di->label.name);
    646 		di->un.e.num_mem = 2;
    647 		strlcpy(di->un.e.member[0].label.name, AudioNoff,
    648 		    sizeof di->un.e.member[0].label.name);
    649 		di->un.e.member[0].ord = 0;
    650 		strlcpy(di->un.e.member[1].label.name, AudioNon,
    651 		    sizeof di->un.e.member[1].label.name);
    652 		di->un.e.member[1].ord = 1;
    653 		break;
    654 
    655 	case AD1843_SUM_MUTE:
    656 		di->type = AUDIO_MIXER_ENUM;
    657 		di->mixer_class = AD1843_INPUT_CLASS;
    658 		strlcpy(di->label.name, "sum." AudioNmute,
    659 		    sizeof di->label.name);
    660 		di->un.e.num_mem = 2;
    661 		strlcpy(di->un.e.member[0].label.name, AudioNoff,
    662 		    sizeof di->un.e.member[0].label.name);
    663 		di->un.e.member[0].ord = 0;
    664 		strlcpy(di->un.e.member[1].label.name, AudioNon,
    665 		    sizeof di->un.e.member[1].label.name);
    666 		di->un.e.member[1].ord = 1;
    667 		break;
    668 
    669 	case AD1843_OUTPUT_CLASS:
    670 		di->type = AUDIO_MIXER_CLASS;
    671 		di->mixer_class = AD1843_OUTPUT_CLASS;
    672 		strlcpy(di->label.name, AudioCoutputs, sizeof di->label.name);
    673 		break;
    674 
    675 	case AD1843_MNO_MUTE:
    676 		di->type = AUDIO_MIXER_ENUM;
    677 		di->mixer_class = AD1843_OUTPUT_CLASS;
    678 		strlcpy(di->label.name, AudioNmono "." AudioNmute,
    679 		    sizeof di->label.name);
    680 		di->un.e.num_mem = 2;
    681 		strlcpy(di->un.e.member[0].label.name, AudioNoff,
    682 		    sizeof di->un.e.member[0].label.name);
    683 		di->un.e.member[0].ord = 0;
    684 		strlcpy(di->un.e.member[1].label.name, AudioNon,
    685 		    sizeof di->un.e.member[1].label.name);
    686 		di->un.e.member[1].ord = 1;
    687 		break;
    688 
    689 	case AD1843_HPO_MUTE:
    690 		di->type = AUDIO_MIXER_ENUM;
    691 		di->mixer_class = AD1843_OUTPUT_CLASS;
    692 		strlcpy(di->label.name, AudioNheadphone "." AudioNmute,
    693 		    sizeof di->label.name);
    694 		di->un.e.num_mem = 2;
    695 		strlcpy(di->un.e.member[0].label.name, AudioNoff,
    696 		    sizeof di->un.e.member[0].label.name);
    697 		di->un.e.member[0].ord = 0;
    698 		strlcpy(di->un.e.member[1].label.name, AudioNon,
    699 		    sizeof di->un.e.member[1].label.name);
    700 		di->un.e.member[1].ord = 1;
    701 		break;
    702 
    703 	default:
    704 		return EINVAL;
    705 	}
    706 
    707 	return 0;
    708 }
    709 
    710 int
    711 mavb_get_props(void *hdl)
    712 {
    713 
    714 	return AUDIO_PROP_PLAYBACK;
    715 }
    716 
    717 static void
    718 mavb_dma_output(struct mavb_softc *sc)
    719 {
    720 	bus_space_tag_t st = sc->sc_st;
    721 	bus_space_handle_t sh = sc->sc_sh;
    722 	uint64_t write_ptr;
    723 	uint64_t depth;
    724 	uint8_t *src, *dst;
    725 	int count;
    726 
    727 	KASSERT(mutex_owned(&sc->sc_intr_lock));
    728 
    729 	write_ptr = bus_space_read_8(st, sh, MAVB_CHANNEL2_WRITE_PTR);
    730 	depth = bus_space_read_8(st, sh, MAVB_CHANNEL2_DEPTH);
    731 
    732 	dst = sc->sc_ring + write_ptr;
    733 	src = sc->sc_get;
    734 
    735 	count = (MAVB_ISA_RING_SIZE - depth - 32);
    736 	while (--count >= 0) {
    737 		*dst++ = *src++;
    738 		if (dst >= sc->sc_ring + MAVB_ISA_RING_SIZE)
    739 			dst = sc->sc_ring;
    740 		if (src >= sc->sc_end)
    741 			src = sc->sc_start;
    742 		if (++sc->sc_count >= sc->sc_blksize) {
    743 			if (sc->sc_intr)
    744 				sc->sc_intr(sc->sc_intrarg);
    745 			sc->sc_count = 0;
    746 		}
    747 	}
    748 
    749 	write_ptr = dst - sc->sc_ring;
    750 	bus_space_write_8(st, sh, MAVB_CHANNEL2_WRITE_PTR, write_ptr);
    751 	sc->sc_get = src;
    752 }
    753 
    754 int
    755 mavb_trigger_output(void *hdl, void *start, void *end, int blksize,
    756 		    void (*intr)(void *), void *intrarg,
    757 		    const audio_params_t *param)
    758 {
    759 	struct mavb_softc *sc = (struct mavb_softc *)hdl;
    760 
    761 	DPRINTF(1, ("%s: mavb_trigger_output: start=%p end=%p "
    762 	    "blksize=%d intr=%p(%p)\n", device_xname(sc->sc_dev),
    763 	    start, end, blksize, intr, intrarg));
    764 
    765 	sc->sc_blksize = blksize;
    766 	sc->sc_intr = intr;
    767 	sc->sc_intrarg = intrarg;
    768 
    769 	sc->sc_start = sc->sc_get = start;
    770 	sc->sc_end = end;
    771 
    772 	sc->sc_count = 0;
    773 
    774 	bus_space_write_8(sc->sc_st, sc->sc_sh, MAVB_CHANNEL2_CONTROL,
    775 	    MAVB_CHANNEL_RESET);
    776 	delay(1000);
    777 	bus_space_write_8(sc->sc_st, sc->sc_sh, MAVB_CHANNEL2_CONTROL, 0);
    778 
    779 	mavb_dma_output(sc);
    780 
    781 	bus_space_write_8(sc->sc_st, sc->sc_sh, MAVB_CHANNEL2_CONTROL,
    782 	    MAVB_CHANNEL_DMA_ENABLE | MAVB_CHANNEL_INT_50);
    783 
    784 	return 0;
    785 }
    786 
    787 int
    788 mavb_trigger_input(void *hdl, void *start, void *end, int blksize,
    789 		   void (*intr)(void *), void *intrarg,
    790 		   const audio_params_t *param)
    791 {
    792 
    793 	return 0;
    794 }
    795 
    796 void
    797 mavb_get_locks(void *hdl, kmutex_t **intr, kmutex_t **thread)
    798 {
    799 	struct mavb_softc *sc = (struct mavb_softc *)hdl;
    800 
    801 	*intr = &sc->sc_intr_lock;
    802 	*thread = &sc->sc_lock;
    803 }
    804 
    805 static void
    806 mavb_button_repeat(void *hdl)
    807 {
    808 	struct mavb_softc *sc = (struct mavb_softc *)hdl;
    809 	uint64_t intmask, control;
    810 	uint16_t value, left, right;
    811 
    812 	DPRINTF(1, ("%s: mavb_repeat called\n", device_xname(sc->sc_dev)));
    813 
    814 #define  MAVB_CONTROL_VOLUME_BUTTONS \
    815     (MAVB_CONTROL_VOLUME_BUTTON_UP | MAVB_CONTROL_VOLUME_BUTTON_DOWN)
    816 
    817 	control = bus_space_read_8(sc->sc_st, sc->sc_sh, MAVB_CONTROL);
    818 	if (control & MAVB_CONTROL_VOLUME_BUTTONS) {
    819 		value = ad1843_reg_read(sc, AD1843_DAC1_ANALOG_GAIN);
    820 		left = (value & AD1843_LDA1G_MASK) >> AD1843_LDA1G_SHIFT;
    821 		right = (value & AD1843_RDA1G_MASK) >> AD1843_RDA1G_SHIFT;
    822 		if (control & MAVB_CONTROL_VOLUME_BUTTON_UP) {
    823 			control &= ~MAVB_CONTROL_VOLUME_BUTTON_UP;
    824 			if (left > 0)
    825 				left--;		/* attenuation! */
    826 			if (right > 0)
    827 				right--;
    828 		}
    829 		if (control & MAVB_CONTROL_VOLUME_BUTTON_DOWN) {
    830 			control &= ~MAVB_CONTROL_VOLUME_BUTTON_DOWN;
    831 			if (left < 63)
    832 				left++;
    833 			if (right < 63)
    834 				right++;
    835 		}
    836 		bus_space_write_8(sc->sc_st, sc->sc_sh, MAVB_CONTROL, control);
    837 
    838 		value &= ~(AD1843_LDA1G_MASK | AD1843_RDA1G_MASK);
    839 		value |= (left << AD1843_LDA1G_SHIFT);
    840 		value |= (right << AD1843_RDA1G_SHIFT);
    841 		ad1843_reg_write(sc, AD1843_DAC1_ANALOG_GAIN, value);
    842 
    843 		callout_reset(&sc->sc_volume_button_ch,
    844 		    (hz * MAVB_VOLUME_BUTTON_REPEAT_DELN) / 1000,
    845 		    mavb_button_repeat, sc);
    846 	} else {
    847 		/* Enable volume button interrupts again.  */
    848 		intmask = bus_space_read_8(sc->sc_st, sc->sc_isash,
    849 		     MACE_ISA_INT_MASK);
    850 		bus_space_write_8(sc->sc_st, sc->sc_isash, MACE_ISA_INT_MASK,
    851 		     intmask | MACE_ISA_INT_AUDIO_SC);
    852 	}
    853 }
    854 
    855 static int
    856 mavb_intr(void *arg)
    857 {
    858 	struct mavb_softc *sc = arg;
    859 	uint64_t stat, intmask;
    860 
    861 	mutex_spin_enter(&sc->sc_intr_lock);
    862 
    863 	stat = bus_space_read_8(sc->sc_st, sc->sc_isash, MACE_ISA_INT_STATUS);
    864 	DPRINTF(MAVB_DEBUG_INTR, ("%s: mavb_intr: stat = 0x%llx\n",
    865             device_xname(sc->sc_dev), stat));
    866 
    867 	if (stat & MACE_ISA_INT_AUDIO_SC) {
    868 		/* Disable volume button interrupts.  */
    869 		intmask = bus_space_read_8(sc->sc_st, sc->sc_isash,
    870 		     MACE_ISA_INT_MASK);
    871 		bus_space_write_8(sc->sc_st, sc->sc_isash, MACE_ISA_INT_MASK,
    872 		     intmask & ~MACE_ISA_INT_AUDIO_SC);
    873 
    874 		callout_reset(&sc->sc_volume_button_ch,
    875 		    (hz * MAVB_VOLUME_BUTTON_REPEAT_DEL1) / 1000,
    876 		    mavb_button_repeat, sc);
    877 	}
    878 
    879 	if (stat & MACE_ISA_INT_AUDIO_DMA2)
    880 		mavb_dma_output(sc);
    881 
    882 	mutex_spin_exit(&sc->sc_intr_lock);
    883 
    884 	return 1;
    885 }
    886 
    887 int
    888 mavb_match(device_t parent, cfdata_t match, void *aux)
    889 {
    890 
    891 	return 1;
    892 }
    893 
    894 void
    895 mavb_attach(device_t parent, device_t self, void *aux)
    896 {
    897 	struct mavb_softc *sc = device_private(self);
    898 	struct mace_attach_args *maa = aux;
    899 	bus_dma_segment_t seg;
    900 	uint64_t control;
    901 	uint16_t value;
    902 	int rseg;
    903 
    904 	sc->sc_dev = self;
    905 
    906 	mutex_init(&sc->sc_lock, MUTEX_DEFAULT, IPL_NONE);
    907 	mutex_init(&sc->sc_intr_lock, MUTEX_DEFAULT, IPL_SCHED);
    908 
    909 	sc->sc_st = maa->maa_st;
    910 	if (bus_space_subregion(sc->sc_st, maa->maa_sh, maa->maa_offset,
    911 	    0, &sc->sc_sh) != 0) {
    912 		printf(": can't map i/o space\n");
    913 		return;
    914 	}
    915 
    916 	/* XXX We need access to some of the MACE ISA registers.  */
    917 	if (bus_space_subregion(sc->sc_st, maa->maa_sh, 0, 0,
    918 	    &sc->sc_isash) != 0) {
    919 		printf(": can't map isa i/o space\n");
    920 		return;
    921 	}
    922 
    923 	/* Set up DMA structures.  */
    924 	sc->sc_dmat = maa->maa_dmat;
    925 	if (bus_dmamap_create(sc->sc_dmat, 4 * MAVB_ISA_RING_SIZE, 1,
    926 	    4 * MAVB_ISA_RING_SIZE, 0, 0, &sc->sc_dmamap)) {
    927 		printf(": can't create MACE ISA DMA map\n");
    928 		return;
    929 	}
    930 
    931 	if (bus_dmamem_alloc(sc->sc_dmat, 4 * MAVB_ISA_RING_SIZE,
    932 	    MACE_ISA_RING_ALIGN, 0, &seg, 1, &rseg, BUS_DMA_NOWAIT)) {
    933 		printf(": can't allocate ring buffer\n");
    934 		return;
    935 	}
    936 
    937 	if (bus_dmamem_map(sc->sc_dmat, &seg, rseg, 4 * MAVB_ISA_RING_SIZE,
    938 	    (void *)&sc->sc_ring, BUS_DMA_COHERENT)) {
    939 		printf(": can't map ring buffer\n");
    940 		return;
    941 	}
    942 
    943 	if (bus_dmamap_load(sc->sc_dmat, sc->sc_dmamap, sc->sc_ring,
    944 	    4 * MAVB_ISA_RING_SIZE, NULL, BUS_DMA_NOWAIT)) {
    945 		printf(": can't load MACE ISA DMA map\n");
    946 		return;
    947 	}
    948 
    949 	sc->sc_ring += MAVB_ISA_RING_SIZE; /* XXX */
    950 
    951 	bus_space_write_8(sc->sc_st, sc->sc_isash, MACE_ISA_RINGBASE,
    952 	    sc->sc_dmamap->dm_segs[0].ds_addr);
    953 
    954 	/* Establish interrupt.  */
    955 	cpu_intr_establish(maa->maa_intr, maa->maa_intrmask,
    956 	    mavb_intr, sc);
    957 
    958 	control = bus_space_read_8(sc->sc_st, sc->sc_sh, MAVB_CONTROL);
    959 	if (!(control & MAVB_CONTROL_CODEC_PRESENT)) {
    960 		printf(": no codec present\n");
    961 		return;
    962 	}
    963 
    964 	/* 2. Assert the RESET signal.  */
    965 	bus_space_write_8(sc->sc_st, sc->sc_sh, MAVB_CONTROL,
    966 	    MAVB_CONTROL_RESET);
    967 	delay(1);		/* at least 100 ns */
    968 
    969 	/* 3. Deassert the RESET signal and enter a wait period to
    970               allow the AD1843 internal clocks and the external
    971               crystal oscillator to stabilize.  */
    972 	bus_space_write_8(sc->sc_st, sc->sc_sh, MAVB_CONTROL, 0);
    973 	delay(800);		/* typically 400 us to 800 us */
    974 	if (ad1843_reg_read(sc, AD1843_CODEC_STATUS) & AD1843_INIT) {
    975 		printf(": codec not ready\n");
    976 		return;
    977 	}
    978 
    979 	/* 4. Put the conversion sources into standby.  */
    980 	value = ad1843_reg_read(sc, AD1843_FUNDAMENTAL_SETTINGS);
    981 	ad1843_reg_write(sc, AD1843_FUNDAMENTAL_SETTINGS,
    982 	    value & ~AD1843_PDNI);
    983 	delay (500000);		/* approximately 474 ms */
    984 	if (ad1843_reg_read(sc, AD1843_CODEC_STATUS) & AD1843_PDNO) {
    985 		printf(": can't power up conversion resources\n");
    986 		return;
    987 	}
    988 
    989 	/* 5. Power up the clock generators and enable clock output pins.  */
    990 	value = ad1843_reg_read(sc, AD1843_FUNDAMENTAL_SETTINGS);
    991 	ad1843_reg_write(sc, AD1843_FUNDAMENTAL_SETTINGS, value | AD1843_C2EN);
    992 
    993 	/* 6. Configure conversion resources while they are in standby.  */
    994 	value = ad1843_reg_read(sc, AD1843_CHANNEL_SAMPLE_RATE);
    995 	ad1843_reg_write(sc, AD1843_CHANNEL_SAMPLE_RATE,
    996 	     value | (2 << AD1843_DA1C_SHIFT));
    997 
    998 	/* 7. Enable conversion resources.  */
    999 	value = ad1843_reg_read(sc, AD1843_CHANNEL_POWER_DOWN);
   1000 	ad1843_reg_write(sc, AD1843_CHANNEL_POWER_DOWN,
   1001 	     value | (AD1843_DA1EN | AD1843_AAMEN));
   1002 
   1003 	/* 8. Configure conversion resources while they are enabled.  */
   1004 	value = ad1843_reg_read(sc, AD1843_DAC1_ANALOG_GAIN);
   1005 	ad1843_reg_write(sc, AD1843_DAC1_ANALOG_GAIN,
   1006             value & ~(AD1843_LDA1GM | AD1843_RDA1GM));
   1007 	value = ad1843_reg_read(sc, AD1843_DAC1_DIGITAL_GAIN);
   1008 	ad1843_reg_write(sc, AD1843_DAC1_DIGITAL_GAIN,
   1009             value & ~(AD1843_LDA1AM | AD1843_RDA1AM));
   1010 	value = ad1843_reg_read(sc, AD1843_MISC_SETTINGS);
   1011 	ad1843_reg_write(sc, AD1843_MISC_SETTINGS,
   1012             value & ~(AD1843_HPOM | AD1843_MNOM));
   1013 
   1014 	value = ad1843_reg_read(sc, AD1843_CODEC_STATUS);
   1015 	printf(": AD1843 rev %d\n", (u_int)value & AD1843_REVISION_MASK);
   1016 
   1017 	sc->sc_play_rate = 48000;
   1018 	sc->sc_play_format = AD1843_PCM8;
   1019 
   1020 	callout_init(&sc->sc_volume_button_ch, 0);
   1021 
   1022 	audio_attach_mi(&mavb_sa_hw_if, sc, self);
   1023 
   1024 	return;
   1025 }
   1026 
   1027 uint16_t
   1028 ad1843_reg_read(struct mavb_softc *sc, ad1843_addr_t addr)
   1029 {
   1030 	bus_space_write_8(sc->sc_st, sc->sc_sh, MAVB_CODEC_CONTROL,
   1031             (addr & MAVB_CODEC_ADDRESS_MASK) << MAVB_CODEC_ADDRESS_SHIFT |
   1032 	    MAVB_CODEC_READ);
   1033 	delay(200);
   1034 	return bus_space_read_8(sc->sc_st, sc->sc_sh, MAVB_CODEC_STATUS);
   1035 }
   1036 
   1037 uint16_t
   1038 ad1843_reg_write(struct mavb_softc *sc, ad1843_addr_t addr, uint16_t value)
   1039 {
   1040 	bus_space_write_8(sc->sc_st, sc->sc_sh, MAVB_CODEC_CONTROL,
   1041 	    (addr & MAVB_CODEC_ADDRESS_MASK) << MAVB_CODEC_ADDRESS_SHIFT |
   1042 	    (value & MAVB_CODEC_WORD_MASK) << MAVB_CODEC_WORD_SHIFT);
   1043 	delay(200);
   1044 	return bus_space_read_8(sc->sc_st, sc->sc_sh, MAVB_CODEC_STATUS);
   1045 }
   1046 
   1047 void
   1048 ad1843_dump_regs(struct mavb_softc *sc)
   1049 {
   1050 	uint16_t addr;
   1051 
   1052 	for (addr = 0; addr < AD1843_NREGS; addr++)
   1053 		printf("%d: 0x%04x\n", addr, ad1843_reg_read(sc, addr));
   1054 }
   1055