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