Expand PMF_FN_* macros.
[netbsd-mini2440.git] / sys / arch / sgimips / mace / mavb.c
bloba96639fabc46a934080f08a105b731784a5601d5
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 $ */
4 /*
5 * Copyright (c) 2005 Mark Kettenis
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.
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.
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>
27 #include <machine/bus.h>
28 #include <machine/intr.h>
29 #include <machine/autoconf.h>
31 #include <sys/audioio.h>
32 #include <dev/auconv.h>
33 #include <dev/audio_if.h>
35 #include <arch/sgimips/mace/macevar.h>
36 #include <arch/sgimips/mace/macereg.h>
37 #include <arch/sgimips/mace/mavbreg.h>
39 #include <dev/ic/ad1843reg.h>
41 #undef MAVB_DEBUG
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
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 */
55 /* XXX We need access to some of the MACE ISA registers. */
56 #define MAVB_ISA_NREGS 0x20
59 * AD1843 Mixer.
62 enum {
63 AD1843_RECORD_CLASS,
64 AD1843_ADC_SOURCE, /* ADC Source Select */
65 AD1843_ADC_GAIN, /* ADC Input Gain */
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 */
84 AD1843_OUTPUT_CLASS,
85 AD1843_MNO_MUTE, /* Mono Output Mute */
86 AD1843_HPO_MUTE /* Headphone Output Mute */
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"
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 */
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 } },
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;
126 /* XXX We need access to some of the MACE ISA registers. */
127 bus_space_handle_t sc_isash;
129 #define MAVB_ISA_RING_SIZE 0x1000
130 uint8_t *sc_ring;
132 uint8_t *sc_start, *sc_end;
133 int sc_blksize;
134 void (*sc_intr)(void *);
135 void *sc_intrarg;
137 void *sc_get;
138 int sc_count;
140 u_long sc_play_rate;
141 u_int sc_play_format;
143 struct callout sc_volume_button_ch;
145 struct audio_format sc_formats[MAVB_NFORMATS];
146 struct audio_encoding_set *sc_encodings;
149 struct mavb_codecvar {
150 stream_filter_t base;
153 static stream_filter_t *mavb_factory
154 (int (*)(stream_fetcher_t *, audio_stream_t *, int));
155 static void mavb_dtor(stream_filter_t *);
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) \
167 return mavb_factory(name##_fetch_to); \
169 static int \
170 name##_fetch_to(stream_fetcher_t *self, audio_stream_t *dst, \
171 int max_used)
173 DEFINE_FILTER(mavb_16to24)
175 stream_filter_t *this;
176 int m, err;
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);
191 return 0;
194 DEFINE_FILTER(mavb_mts)
196 stream_filter_t *this;
197 int m, err;
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);
212 return 0;
215 static stream_filter_t *
216 mavb_factory(int (*fetch_to)(stream_fetcher_t *, audio_stream_t *, int))
218 struct mavb_codecvar *this;
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;
226 return &this->base;
229 static void
230 mavb_dtor(stream_filter_t *this)
233 if (this != NULL)
234 free(this, M_DEVBUF);
237 typedef uint64_t ad1843_addr_t;
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 *);
243 int mavb_match(struct device *, struct cfdata *, void *);
244 void mavb_attach(struct device *, struct device *, void *);
246 CFATTACH_DECL(mavb, sizeof(struct mavb_softc),
247 mavb_match, mavb_attach, NULL, NULL);
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 *);
269 struct audio_hw_if mavb_sa_hw_if = {
270 mavb_open,
271 mavb_close,
273 mavb_query_encoding,
274 mavb_set_params,
275 mavb_round_blocksize,
281 mavb_halt_output,
282 mavb_halt_input,
284 mavb_getdev,
286 mavb_set_port,
287 mavb_get_port,
288 mavb_query_devinfo,
291 mavb_round_buffersize,
293 mavb_get_props,
294 mavb_trigger_output,
295 mavb_trigger_input,
296 NULL,
299 struct audio_device mavb_device = {
300 "A3",
302 "mavb"
306 mavb_open(void *hdl, int flags)
309 return 0;
312 void
313 mavb_close(void *hdl)
318 mavb_query_encoding(void *hdl, struct audio_encoding *ae)
320 struct mavb_softc *sc = (struct mavb_softc *)hdl;
322 return auconv_query_encoding(sc->sc_encodings, ae);
325 static int
326 mavb_set_play_rate(struct mavb_softc *sc, u_long sample_rate)
329 if (sample_rate < 4000 || sample_rate > 48000)
330 return EINVAL;
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;
336 return 0;
339 static int
340 mavb_set_play_format(struct mavb_softc *sc, u_int encoding)
342 uint16_t value;
343 u_int format;
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;
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;
369 return 0;
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)
377 struct mavb_softc *sc = (struct mavb_softc *)hdl;
378 struct audio_params *p;
379 stream_filter_list_t *fil;
380 int error;
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));
386 if (setmode & AUMODE_PLAY) {
387 if (play->sample_rate < 4000 || play->sample_rate > 48000)
388 return EINVAL;
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;
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;
402 error = mavb_set_play_rate(sc, p->sample_rate);
403 if (error)
404 return error;
406 error = mavb_set_play_format(sc, p->encoding);
407 if (error)
408 return error;
411 #if 0
412 if (setmode & AUMODE_RECORD) {
413 if (rec->sample_rate < 4000 || rec->sample_rate > 48000)
414 return EINVAL;
416 #endif
418 return 0;
422 mavb_round_blocksize(void *hdl, int bs, int mode, const audio_params_t *p)
425 /* Block size should be a multiple of 32. */
426 return (bs + 0x1f) & ~0x1f;
430 mavb_halt_output(void *hdl)
432 struct mavb_softc *sc = (struct mavb_softc *)hdl;
434 DPRINTF(1, ("%s: mavb_halt_output called\n", sc->sc_dev.dv_xname));
436 bus_space_write_8(sc->sc_st, sc->sc_sh, MAVB_CHANNEL2_CONTROL, 0);
437 return 0;
441 mavb_halt_input(void *hdl)
444 return 0;
448 mavb_getdev(void *hdl, struct audio_device *ret)
451 *ret = mavb_device;
452 return 0;
456 mavb_set_port(void *hdl, struct mixer_ctrl *mc)
458 struct mavb_softc *sc = (struct mavb_softc *)hdl;
459 u_char left, right;
460 ad1843_addr_t reg;
461 uint16_t value;
463 DPRINTF(1, ("%s: mavb_set_port: dev=%d\n", sc->sc_dev.dv_xname,
464 mc->dev));
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;
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;
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;
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;
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;
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;
571 default:
572 return EINVAL;
575 return 0;
579 mavb_get_port(void *hdl, struct mixer_ctrl *mc)
581 struct mavb_softc *sc = (struct mavb_softc *)hdl;
582 u_char left, right;
583 ad1843_addr_t reg;
584 uint16_t value;
586 DPRINTF(1, ("%s: mavb_get_port: dev=%d\n", sc->sc_dev.dv_xname,
587 mc->dev));
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;
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;
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;
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;
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;
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;
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;
667 default:
668 return EINVAL;
671 return 0;
675 mavb_query_devinfo(void *hdl, struct mixer_devinfo *di)
677 int i;
679 di->prev = di->next = AUDIO_MIXER_LAST;
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;
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;
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;
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;
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;
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;
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;
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;
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;
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;
827 default:
828 return EINVAL;
831 return 0;
834 size_t
835 mavb_round_buffersize(void *hdl, int dir, size_t bufsize)
838 return bufsize;
842 mavb_get_props(void *hdl)
845 return AUDIO_PROP_FULLDUPLEX | AUDIO_PROP_INDEPENDENT;
848 static void
849 mavb_dma_output(struct mavb_softc *sc)
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;
858 write_ptr = bus_space_read_8(st, sh, MAVB_CHANNEL2_WRITE_PTR);
859 depth = bus_space_read_8(st, sh, MAVB_CHANNEL2_DEPTH);
861 dst = sc->sc_ring + write_ptr;
862 src = sc->sc_get;
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;
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;
884 mavb_trigger_output(void *hdl, void *start, void *end, int blksize,
885 void (*intr)(void *), void *intrarg,
886 const audio_params_t *param)
888 struct mavb_softc *sc = (struct mavb_softc *)hdl;
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));
894 sc->sc_blksize = blksize;
895 sc->sc_intr = intr;
896 sc->sc_intrarg = intrarg;
898 sc->sc_start = sc->sc_get = start;
899 sc->sc_end = end;
901 sc->sc_count = 0;
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);
908 mavb_dma_output(sc);
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;
916 mavb_trigger_input(void *hdl, void *start, void *end, int blksize,
917 void (*intr)(void *), void *intrarg,
918 const audio_params_t *param)
921 return 0;
924 static void
925 mavb_button_repeat(void *hdl)
927 struct mavb_softc *sc = (struct mavb_softc *)hdl;
928 uint64_t intmask, control;
929 uint16_t value, left, right;
931 DPRINTF(1, ("%s: mavb_repeat called\n", sc->sc_dev.dv_xname));
933 #define MAVB_CONTROL_VOLUME_BUTTONS \
934 (MAVB_CONTROL_VOLUME_BUTTON_UP | MAVB_CONTROL_VOLUME_BUTTON_DOWN)
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--;
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++;
955 bus_space_write_8(sc->sc_st, sc->sc_sh, MAVB_CONTROL, control);
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);
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);
974 static int
975 mavb_intr(void *arg)
977 struct mavb_softc *sc = arg;
978 uint64_t stat, intmask;
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));
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);
991 callout_reset(&sc->sc_volume_button_ch,
992 (hz * MAVB_VOLUME_BUTTON_REPEAT_DEL1) / 1000,
993 mavb_button_repeat, sc);
996 if (stat & MACE_ISA_INT_AUDIO_DMA2)
997 mavb_dma_output(sc);
999 return 1;
1003 mavb_match(struct device *parent, struct cfdata *match, void *aux)
1006 return 1;
1009 void
1010 mavb_attach(struct device *parent, struct device *self, void *aux)
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;
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;
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;
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;
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;
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;
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;
1059 sc->sc_ring += MAVB_ISA_RING_SIZE; /* XXX */
1061 bus_space_write_8(sc->sc_st, sc->sc_isash, MACE_ISA_RINGBASE,
1062 sc->sc_dmamap->dm_segs[0].ds_addr);
1064 /* Establish interrupt. */
1065 cpu_intr_establish(maa->maa_intr, maa->maa_intrmask,
1066 mavb_intr, sc);
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;
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 */
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;
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;
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);
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));
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));
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));
1124 value = ad1843_reg_read(sc, AD1843_CODEC_STATUS);
1125 printf(": AD1843 rev %d\n", (u_int)value & AD1843_REVISION_MASK);
1127 sc->sc_play_rate = 48000;
1128 sc->sc_play_format = AD1843_PCM8;
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;
1139 callout_init(&sc->sc_volume_button_ch, 0);
1141 audio_attach_mi(&mavb_sa_hw_if, sc, &sc->sc_dev);
1143 return;
1146 uint16_t
1147 ad1843_reg_read(struct mavb_softc *sc, ad1843_addr_t addr)
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);
1156 uint16_t
1157 ad1843_reg_write(struct mavb_softc *sc, ad1843_addr_t addr, uint16_t value)
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);
1166 void
1167 ad1843_dump_regs(struct mavb_softc *sc)
1169 uint16_t addr;
1171 for (addr = 0; addr < AD1843_NREGS; addr++)
1172 printf("%d: 0x%04x\n", addr, ad1843_reg_read(sc, addr));