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