Home | History | Annotate | Line # | Download | only in mace
mavb.c revision 1.13
      1 /* $NetBSD: mavb.c,v 1.13 2019/05/08 13:40:16 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 	    AUDIO_PROP_FULLDUPLEX | AUDIO_PROP_INDEPENDENT;
    716 }
    717 
    718 static void
    719 mavb_dma_output(struct mavb_softc *sc)
    720 {
    721 	bus_space_tag_t st = sc->sc_st;
    722 	bus_space_handle_t sh = sc->sc_sh;
    723 	uint64_t write_ptr;
    724 	uint64_t depth;
    725 	uint8_t *src, *dst;
    726 	int count;
    727 
    728 	KASSERT(mutex_owned(&sc->sc_intr_lock));
    729 
    730 	write_ptr = bus_space_read_8(st, sh, MAVB_CHANNEL2_WRITE_PTR);
    731 	depth = bus_space_read_8(st, sh, MAVB_CHANNEL2_DEPTH);
    732 
    733 	dst = sc->sc_ring + write_ptr;
    734 	src = sc->sc_get;
    735 
    736 	count = (MAVB_ISA_RING_SIZE - depth - 32);
    737 	while (--count >= 0) {
    738 		*dst++ = *src++;
    739 		if (dst >= sc->sc_ring + MAVB_ISA_RING_SIZE)
    740 			dst = sc->sc_ring;
    741 		if (src >= sc->sc_end)
    742 			src = sc->sc_start;
    743 		if (++sc->sc_count >= sc->sc_blksize) {
    744 			if (sc->sc_intr)
    745 				sc->sc_intr(sc->sc_intrarg);
    746 			sc->sc_count = 0;
    747 		}
    748 	}
    749 
    750 	write_ptr = dst - sc->sc_ring;
    751 	bus_space_write_8(st, sh, MAVB_CHANNEL2_WRITE_PTR, write_ptr);
    752 	sc->sc_get = src;
    753 }
    754 
    755 int
    756 mavb_trigger_output(void *hdl, void *start, void *end, int blksize,
    757 		    void (*intr)(void *), void *intrarg,
    758 		    const audio_params_t *param)
    759 {
    760 	struct mavb_softc *sc = (struct mavb_softc *)hdl;
    761 
    762 	DPRINTF(1, ("%s: mavb_trigger_output: start=%p end=%p "
    763 	    "blksize=%d intr=%p(%p)\n", device_xname(sc->sc_dev),
    764 	    start, end, blksize, intr, intrarg));
    765 
    766 	sc->sc_blksize = blksize;
    767 	sc->sc_intr = intr;
    768 	sc->sc_intrarg = intrarg;
    769 
    770 	sc->sc_start = sc->sc_get = start;
    771 	sc->sc_end = end;
    772 
    773 	sc->sc_count = 0;
    774 
    775 	bus_space_write_8(sc->sc_st, sc->sc_sh, MAVB_CHANNEL2_CONTROL,
    776 	    MAVB_CHANNEL_RESET);
    777 	delay(1000);
    778 	bus_space_write_8(sc->sc_st, sc->sc_sh, MAVB_CHANNEL2_CONTROL, 0);
    779 
    780 	mavb_dma_output(sc);
    781 
    782 	bus_space_write_8(sc->sc_st, sc->sc_sh, MAVB_CHANNEL2_CONTROL,
    783 	    MAVB_CHANNEL_DMA_ENABLE | MAVB_CHANNEL_INT_50);
    784 
    785 	return 0;
    786 }
    787 
    788 int
    789 mavb_trigger_input(void *hdl, void *start, void *end, int blksize,
    790 		   void (*intr)(void *), void *intrarg,
    791 		   const audio_params_t *param)
    792 {
    793 
    794 	return 0;
    795 }
    796 
    797 void
    798 mavb_get_locks(void *hdl, kmutex_t **intr, kmutex_t **thread)
    799 {
    800 	struct mavb_softc *sc = (struct mavb_softc *)hdl;
    801 
    802 	*intr = &sc->sc_intr_lock;
    803 	*thread = &sc->sc_lock;
    804 }
    805 
    806 static void
    807 mavb_button_repeat(void *hdl)
    808 {
    809 	struct mavb_softc *sc = (struct mavb_softc *)hdl;
    810 	uint64_t intmask, control;
    811 	uint16_t value, left, right;
    812 
    813 	DPRINTF(1, ("%s: mavb_repeat called\n", device_xname(sc->sc_dev)));
    814 
    815 #define  MAVB_CONTROL_VOLUME_BUTTONS \
    816     (MAVB_CONTROL_VOLUME_BUTTON_UP | MAVB_CONTROL_VOLUME_BUTTON_DOWN)
    817 
    818 	control = bus_space_read_8(sc->sc_st, sc->sc_sh, MAVB_CONTROL);
    819 	if (control & MAVB_CONTROL_VOLUME_BUTTONS) {
    820 		value = ad1843_reg_read(sc, AD1843_DAC1_ANALOG_GAIN);
    821 		left = (value & AD1843_LDA1G_MASK) >> AD1843_LDA1G_SHIFT;
    822 		right = (value & AD1843_RDA1G_MASK) >> AD1843_RDA1G_SHIFT;
    823 		if (control & MAVB_CONTROL_VOLUME_BUTTON_UP) {
    824 			control &= ~MAVB_CONTROL_VOLUME_BUTTON_UP;
    825 			if (left > 0)
    826 				left--;		/* attenuation! */
    827 			if (right > 0)
    828 				right--;
    829 		}
    830 		if (control & MAVB_CONTROL_VOLUME_BUTTON_DOWN) {
    831 			control &= ~MAVB_CONTROL_VOLUME_BUTTON_DOWN;
    832 			if (left < 63)
    833 				left++;
    834 			if (right < 63)
    835 				right++;
    836 		}
    837 		bus_space_write_8(sc->sc_st, sc->sc_sh, MAVB_CONTROL, control);
    838 
    839 		value &= ~(AD1843_LDA1G_MASK | AD1843_RDA1G_MASK);
    840 		value |= (left << AD1843_LDA1G_SHIFT);
    841 		value |= (right << AD1843_RDA1G_SHIFT);
    842 		ad1843_reg_write(sc, AD1843_DAC1_ANALOG_GAIN, value);
    843 
    844 		callout_reset(&sc->sc_volume_button_ch,
    845 		    (hz * MAVB_VOLUME_BUTTON_REPEAT_DELN) / 1000,
    846 		    mavb_button_repeat, sc);
    847 	} else {
    848 		/* Enable volume button interrupts again.  */
    849 		intmask = bus_space_read_8(sc->sc_st, sc->sc_isash,
    850 		     MACE_ISA_INT_MASK);
    851 		bus_space_write_8(sc->sc_st, sc->sc_isash, MACE_ISA_INT_MASK,
    852 		     intmask | MACE_ISA_INT_AUDIO_SC);
    853 	}
    854 }
    855 
    856 static int
    857 mavb_intr(void *arg)
    858 {
    859 	struct mavb_softc *sc = arg;
    860 	uint64_t stat, intmask;
    861 
    862 	mutex_spin_enter(&sc->sc_intr_lock);
    863 
    864 	stat = bus_space_read_8(sc->sc_st, sc->sc_isash, MACE_ISA_INT_STATUS);
    865 	DPRINTF(MAVB_DEBUG_INTR, ("%s: mavb_intr: stat = 0x%llx\n",
    866             device_xname(sc->sc_dev), stat));
    867 
    868 	if (stat & MACE_ISA_INT_AUDIO_SC) {
    869 		/* Disable volume button interrupts.  */
    870 		intmask = bus_space_read_8(sc->sc_st, sc->sc_isash,
    871 		     MACE_ISA_INT_MASK);
    872 		bus_space_write_8(sc->sc_st, sc->sc_isash, MACE_ISA_INT_MASK,
    873 		     intmask & ~MACE_ISA_INT_AUDIO_SC);
    874 
    875 		callout_reset(&sc->sc_volume_button_ch,
    876 		    (hz * MAVB_VOLUME_BUTTON_REPEAT_DEL1) / 1000,
    877 		    mavb_button_repeat, sc);
    878 	}
    879 
    880 	if (stat & MACE_ISA_INT_AUDIO_DMA2)
    881 		mavb_dma_output(sc);
    882 
    883 	mutex_spin_exit(&sc->sc_intr_lock);
    884 
    885 	return 1;
    886 }
    887 
    888 int
    889 mavb_match(device_t parent, cfdata_t match, void *aux)
    890 {
    891 
    892 	return 1;
    893 }
    894 
    895 void
    896 mavb_attach(device_t parent, device_t self, void *aux)
    897 {
    898 	struct mavb_softc *sc = device_private(self);
    899 	struct mace_attach_args *maa = aux;
    900 	bus_dma_segment_t seg;
    901 	uint64_t control;
    902 	uint16_t value;
    903 	int rseg;
    904 
    905 	sc->sc_dev = self;
    906 
    907 	mutex_init(&sc->sc_lock, MUTEX_DEFAULT, IPL_NONE);
    908 	mutex_init(&sc->sc_intr_lock, MUTEX_DEFAULT, IPL_SCHED);
    909 
    910 	sc->sc_st = maa->maa_st;
    911 	if (bus_space_subregion(sc->sc_st, maa->maa_sh, maa->maa_offset,
    912 	    0, &sc->sc_sh) != 0) {
    913 		printf(": can't map i/o space\n");
    914 		return;
    915 	}
    916 
    917 	/* XXX We need access to some of the MACE ISA registers.  */
    918 	if (bus_space_subregion(sc->sc_st, maa->maa_sh, 0, 0,
    919 	    &sc->sc_isash) != 0) {
    920 		printf(": can't map isa i/o space\n");
    921 		return;
    922 	}
    923 
    924 	/* Set up DMA structures.  */
    925 	sc->sc_dmat = maa->maa_dmat;
    926 	if (bus_dmamap_create(sc->sc_dmat, 4 * MAVB_ISA_RING_SIZE, 1,
    927 	    4 * MAVB_ISA_RING_SIZE, 0, 0, &sc->sc_dmamap)) {
    928 		printf(": can't create MACE ISA DMA map\n");
    929 		return;
    930 	}
    931 
    932 	if (bus_dmamem_alloc(sc->sc_dmat, 4 * MAVB_ISA_RING_SIZE,
    933 	    MACE_ISA_RING_ALIGN, 0, &seg, 1, &rseg, BUS_DMA_NOWAIT)) {
    934 		printf(": can't allocate ring buffer\n");
    935 		return;
    936 	}
    937 
    938 	if (bus_dmamem_map(sc->sc_dmat, &seg, rseg, 4 * MAVB_ISA_RING_SIZE,
    939 	    (void *)&sc->sc_ring, BUS_DMA_COHERENT)) {
    940 		printf(": can't map ring buffer\n");
    941 		return;
    942 	}
    943 
    944 	if (bus_dmamap_load(sc->sc_dmat, sc->sc_dmamap, sc->sc_ring,
    945 	    4 * MAVB_ISA_RING_SIZE, NULL, BUS_DMA_NOWAIT)) {
    946 		printf(": can't load MACE ISA DMA map\n");
    947 		return;
    948 	}
    949 
    950 	sc->sc_ring += MAVB_ISA_RING_SIZE; /* XXX */
    951 
    952 	bus_space_write_8(sc->sc_st, sc->sc_isash, MACE_ISA_RINGBASE,
    953 	    sc->sc_dmamap->dm_segs[0].ds_addr);
    954 
    955 	/* Establish interrupt.  */
    956 	cpu_intr_establish(maa->maa_intr, maa->maa_intrmask,
    957 	    mavb_intr, sc);
    958 
    959 	control = bus_space_read_8(sc->sc_st, sc->sc_sh, MAVB_CONTROL);
    960 	if (!(control & MAVB_CONTROL_CODEC_PRESENT)) {
    961 		printf(": no codec present\n");
    962 		return;
    963 	}
    964 
    965 	/* 2. Assert the RESET signal.  */
    966 	bus_space_write_8(sc->sc_st, sc->sc_sh, MAVB_CONTROL,
    967 	    MAVB_CONTROL_RESET);
    968 	delay(1);		/* at least 100 ns */
    969 
    970 	/* 3. Deassert the RESET signal and enter a wait period to
    971               allow the AD1843 internal clocks and the external
    972               crystal oscillator to stabilize.  */
    973 	bus_space_write_8(sc->sc_st, sc->sc_sh, MAVB_CONTROL, 0);
    974 	delay(800);		/* typically 400 us to 800 us */
    975 	if (ad1843_reg_read(sc, AD1843_CODEC_STATUS) & AD1843_INIT) {
    976 		printf(": codec not ready\n");
    977 		return;
    978 	}
    979 
    980 	/* 4. Put the conversion sources into standby.  */
    981 	value = ad1843_reg_read(sc, AD1843_FUNDAMENTAL_SETTINGS);
    982 	ad1843_reg_write(sc, AD1843_FUNDAMENTAL_SETTINGS,
    983 	    value & ~AD1843_PDNI);
    984 	delay (500000);		/* approximately 474 ms */
    985 	if (ad1843_reg_read(sc, AD1843_CODEC_STATUS) & AD1843_PDNO) {
    986 		printf(": can't power up conversion resources\n");
    987 		return;
    988 	}
    989 
    990 	/* 5. Power up the clock generators and enable clock output pins.  */
    991 	value = ad1843_reg_read(sc, AD1843_FUNDAMENTAL_SETTINGS);
    992 	ad1843_reg_write(sc, AD1843_FUNDAMENTAL_SETTINGS, value | AD1843_C2EN);
    993 
    994 	/* 6. Configure conversion resources while they are in standby.  */
    995 	value = ad1843_reg_read(sc, AD1843_CHANNEL_SAMPLE_RATE);
    996 	ad1843_reg_write(sc, AD1843_CHANNEL_SAMPLE_RATE,
    997 	     value | (2 << AD1843_DA1C_SHIFT));
    998 
    999 	/* 7. Enable conversion resources.  */
   1000 	value = ad1843_reg_read(sc, AD1843_CHANNEL_POWER_DOWN);
   1001 	ad1843_reg_write(sc, AD1843_CHANNEL_POWER_DOWN,
   1002 	     value | (AD1843_DA1EN | AD1843_AAMEN));
   1003 
   1004 	/* 8. Configure conversion resources while they are enabled.  */
   1005 	value = ad1843_reg_read(sc, AD1843_DAC1_ANALOG_GAIN);
   1006 	ad1843_reg_write(sc, AD1843_DAC1_ANALOG_GAIN,
   1007             value & ~(AD1843_LDA1GM | AD1843_RDA1GM));
   1008 	value = ad1843_reg_read(sc, AD1843_DAC1_DIGITAL_GAIN);
   1009 	ad1843_reg_write(sc, AD1843_DAC1_DIGITAL_GAIN,
   1010             value & ~(AD1843_LDA1AM | AD1843_RDA1AM));
   1011 	value = ad1843_reg_read(sc, AD1843_MISC_SETTINGS);
   1012 	ad1843_reg_write(sc, AD1843_MISC_SETTINGS,
   1013             value & ~(AD1843_HPOM | AD1843_MNOM));
   1014 
   1015 	value = ad1843_reg_read(sc, AD1843_CODEC_STATUS);
   1016 	printf(": AD1843 rev %d\n", (u_int)value & AD1843_REVISION_MASK);
   1017 
   1018 	sc->sc_play_rate = 48000;
   1019 	sc->sc_play_format = AD1843_PCM8;
   1020 
   1021 	callout_init(&sc->sc_volume_button_ch, 0);
   1022 
   1023 	audio_attach_mi(&mavb_sa_hw_if, sc, self);
   1024 
   1025 	return;
   1026 }
   1027 
   1028 uint16_t
   1029 ad1843_reg_read(struct mavb_softc *sc, ad1843_addr_t addr)
   1030 {
   1031 	bus_space_write_8(sc->sc_st, sc->sc_sh, MAVB_CODEC_CONTROL,
   1032             (addr & MAVB_CODEC_ADDRESS_MASK) << MAVB_CODEC_ADDRESS_SHIFT |
   1033 	    MAVB_CODEC_READ);
   1034 	delay(200);
   1035 	return bus_space_read_8(sc->sc_st, sc->sc_sh, MAVB_CODEC_STATUS);
   1036 }
   1037 
   1038 uint16_t
   1039 ad1843_reg_write(struct mavb_softc *sc, ad1843_addr_t addr, uint16_t value)
   1040 {
   1041 	bus_space_write_8(sc->sc_st, sc->sc_sh, MAVB_CODEC_CONTROL,
   1042 	    (addr & MAVB_CODEC_ADDRESS_MASK) << MAVB_CODEC_ADDRESS_SHIFT |
   1043 	    (value & MAVB_CODEC_WORD_MASK) << MAVB_CODEC_WORD_SHIFT);
   1044 	delay(200);
   1045 	return bus_space_read_8(sc->sc_st, sc->sc_sh, MAVB_CODEC_STATUS);
   1046 }
   1047 
   1048 void
   1049 ad1843_dump_regs(struct mavb_softc *sc)
   1050 {
   1051 	uint16_t addr;
   1052 
   1053 	for (addr = 0; addr < AD1843_NREGS; addr++)
   1054 		printf("%d: 0x%04x\n", addr, ad1843_reg_read(sc, addr));
   1055 }
   1056