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