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