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