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