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