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