xref: /netbsd-src/sys/arch/sgimips/mace/mavb.c (revision 8b0f9554ff8762542c4defc4f70e1eb76fb508fa)
1 /* $NetBSD: mavb.c,v 1.4 2007/10/17 19:57:05 garbled 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