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 $ */
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>
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
;
48 #define DPRINTF(l,x) /* nothing */
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
64 AD1843_ADC_SOURCE
, /* ADC Source Select */
65 AD1843_ADC_GAIN
, /* ADC Input Gain */
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 */
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
[] = {
101 /* Mix Control. The order matches the hardware register numbering. */
102 const char *ad1843_input
[] = {
103 AudioNdac
"2", /* AD1843_DAC2__TO_MIXER */
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 } },
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
132 uint8_t *sc_start
, *sc_end
;
134 void (*sc_intr
)(void *);
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) \
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 *); \
164 name(struct audio_softc *sc, const audio_params_t *from, \
165 const audio_params_t *to) \
167 return mavb_factory(name##_fetch_to); \
170 name##_fetch_to(stream_fetcher_t *self, audio_stream_t *dst, \
173 DEFINE_FILTER(mavb_16to24
)
175 stream_filter_t
*this;
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
)))
182 m
= (dst
->end
- dst
->start
) & ~1;
183 m
= min(m
, max_used
);
184 FILTER_LOOP_PROLOGUE(this->src
, 2, dst
, 4, m
) {
188 d
[0] = (s
[0] & 0x80) ? 0xff : 0;
189 } FILTER_LOOP_EPILOGUE(this->src
, dst
);
194 DEFINE_FILTER(mavb_mts
)
196 stream_filter_t
*this;
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
)))
203 m
= (dst
->end
- dst
->start
) & ~1;
204 m
= min(m
, max_used
);
205 FILTER_LOOP_PROLOGUE(this->src
, 4, dst
, 8, m
) {
210 } FILTER_LOOP_EPILOGUE(this->src
, dst
);
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
;
230 mavb_dtor(stream_filter_t
*this)
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
= {
275 mavb_round_blocksize
,
291 mavb_round_buffersize
,
299 struct audio_device mavb_device
= {
306 mavb_open(void *hdl
, int flags
)
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
);
326 mavb_set_play_rate(struct mavb_softc
*sc
, u_long sample_rate
)
329 if (sample_rate
< 4000 || sample_rate
> 48000)
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
;
340 mavb_set_play_format(struct mavb_softc
*sc
, u_int encoding
)
346 case AUDIO_ENCODING_ULINEAR_BE
:
347 format
= AD1843_PCM8
;
349 case AUDIO_ENCODING_SLINEAR_BE
:
350 format
= AD1843_PCM16
;
352 case AUDIO_ENCODING_ULAW
:
353 format
= AD1843_ULAW
;
355 case AUDIO_ENCODING_ALAW
:
356 format
= AD1843_ALAW
;
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
;
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
;
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)
392 if (auconv_set_converter(sc
->sc_formats
, MAVB_NFORMATS
,
393 AUMODE_PLAY
, p
, TRUE
, fil
) < 0)
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
);
406 error
= mavb_set_play_format(sc
, p
->encoding
);
412 if (setmode
& AUMODE_RECORD
) {
413 if (rec
->sample_rate
< 4000 || rec
->sample_rate
> 48000)
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);
441 mavb_halt_input(void *hdl
)
448 mavb_getdev(void *hdl
, struct audio_device
*ret
)
456 mavb_set_port(void *hdl
, struct mixer_ctrl
*mc
)
458 struct mavb_softc
*sc
= (struct mavb_softc
*)hdl
;
463 DPRINTF(1, ("%s: mavb_set_port: dev=%d\n", sc
->sc_dev
.dv_xname
,
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
);
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
);
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
);
495 case AD1843_DAC1_MUTE
:
496 value
= ad1843_reg_read(sc
, AD1843_DAC1_ANALOG_GAIN
);
498 value
&= ~(AD1843_LDA1GM
| AD1843_RDA1GM
);
500 value
|= (AD1843_LDA1GM
| AD1843_RDA1GM
);
501 ad1843_reg_write(sc
, AD1843_DAC1_ANALOG_GAIN
, value
);
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
);
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
);
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
);
537 value
&= ~(AD1843_LD2MM
| AD1843_RD2MM
);
539 value
|= (AD1843_LD2MM
| AD1843_RD2MM
);
540 ad1843_reg_write(sc
, reg
, value
);
543 case AD1843_SUM_MUTE
:
544 value
= ad1843_reg_read(sc
, AD1843_MISC_SETTINGS
);
546 value
&= ~AD1843_SUMM
;
548 value
|= AD1843_SUMM
;
549 ad1843_reg_write(sc
, AD1843_MISC_SETTINGS
, value
);
552 case AD1843_MNO_MUTE
:
553 value
= ad1843_reg_read(sc
, AD1843_MISC_SETTINGS
);
555 value
&= ~AD1843_MNOM
;
557 value
|= AD1843_MNOM
;
558 ad1843_reg_write(sc
, AD1843_MISC_SETTINGS
, value
);
561 case AD1843_HPO_MUTE
:
562 value
= ad1843_reg_read(sc
, AD1843_MISC_SETTINGS
);
564 value
&= ~AD1843_HPOM
;
566 value
|= AD1843_HPOM
;
567 ad1843_reg_write(sc
, AD1843_MISC_SETTINGS
, value
);
568 value
= ad1843_reg_read(sc
, AD1843_MISC_SETTINGS
);
579 mavb_get_port(void *hdl
, struct mixer_ctrl
*mc
)
581 struct mavb_softc
*sc
= (struct mavb_softc
*)hdl
;
586 DPRINTF(1, ("%s: mavb_get_port: dev=%d\n", sc
->sc_dev
.dv_xname
,
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
;
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
] =
600 mc
->un
.value
.level
[AUDIO_MIXER_LEVEL_RIGHT
] =
601 (right
<< 2) | right
;
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);
613 case AD1843_DAC1_MUTE
:
614 value
= ad1843_reg_read(sc
, AD1843_DAC1_ANALOG_GAIN
);
615 mc
->un
.ord
= (value
& AD1843_LDA1GM
) ? 1 : 0;
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);
632 case AD1843_MONO_GAIN
:
633 if (mc
->un
.value
.num_channels
!= 1)
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);
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;
652 case AD1843_SUM_MUTE
:
653 value
= ad1843_reg_read(sc
, AD1843_MISC_SETTINGS
);
654 mc
->un
.ord
= (value
& AD1843_SUMM
) ? 1 : 0;
657 case AD1843_MNO_MUTE
:
658 value
= ad1843_reg_read(sc
, AD1843_MISC_SETTINGS
);
659 mc
->un
.ord
= (value
& AD1843_MNOM
) ? 1 : 0;
662 case AD1843_HPO_MUTE
:
663 value
= ad1843_reg_read(sc
, AD1843_MISC_SETTINGS
);
664 mc
->un
.ord
= (value
& AD1843_HPOM
) ? 1 : 0;
675 mavb_query_devinfo(void *hdl
, struct mixer_devinfo
*di
)
679 di
->prev
= di
->next
= AUDIO_MIXER_LAST
;
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
);
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
);
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
,
698 sizeof di
->un
.e
.member
[0].label
.name
);
699 di
->un
.e
.member
[i
].ord
= i
;
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
);
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
);
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
);
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;
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;
756 di
->un
.v
.num_channels
= 2;
757 strlcpy(di
->un
.v
.units
.name
, AudioNvolume
,
758 sizeof di
->un
.v
.units
.name
);
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;
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;
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
);
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;
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;
835 mavb_round_buffersize(void *hdl
, int dir
, size_t bufsize
)
842 mavb_get_props(void *hdl
)
845 return AUDIO_PROP_FULLDUPLEX
| AUDIO_PROP_INDEPENDENT
;
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
;
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
;
864 count
= (MAVB_ISA_RING_SIZE
- depth
- 32);
865 while (--count
>= 0) {
867 if (dst
>= sc
->sc_ring
+ MAVB_ISA_RING_SIZE
)
869 if (src
>= sc
->sc_end
)
871 if (++sc
->sc_count
>= sc
->sc_blksize
) {
873 sc
->sc_intr(sc
->sc_intrarg
);
878 write_ptr
= dst
- sc
->sc_ring
;
879 bus_space_write_8(st
, sh
, MAVB_CHANNEL2_WRITE_PTR
, write_ptr
);
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
;
896 sc
->sc_intrarg
= intrarg
;
898 sc
->sc_start
= sc
->sc_get
= start
;
903 bus_space_write_8(sc
->sc_st
, sc
->sc_sh
, MAVB_CHANNEL2_CONTROL
,
906 bus_space_write_8(sc
->sc_st
, sc
->sc_sh
, MAVB_CHANNEL2_CONTROL
, 0);
910 bus_space_write_8(sc
->sc_st
, sc
->sc_sh
, MAVB_CHANNEL2_CONTROL
,
911 MAVB_CHANNEL_DMA_ENABLE
| MAVB_CHANNEL_INT_50
);
916 mavb_trigger_input(void *hdl
, void *start
, void *end
, int blksize
,
917 void (*intr
)(void *), void *intrarg
,
918 const audio_params_t
*param
)
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
;
944 left
--; /* attenuation! */
948 if (control
& MAVB_CONTROL_VOLUME_BUTTON_DOWN
) {
949 control
&= ~MAVB_CONTROL_VOLUME_BUTTON_DOWN
;
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
);
966 /* Enable volume button interrupts again. */
967 intmask
= bus_space_read_8(sc
->sc_st
, sc
->sc_isash
,
969 bus_space_write_8(sc
->sc_st
, sc
->sc_isash
, MACE_ISA_INT_MASK
,
970 intmask
| MACE_ISA_INT_AUDIO_SC
);
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
,
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
)
1003 mavb_match(struct device
*parent
, struct cfdata
*match
, void *aux
)
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
;
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");
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");
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");
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");
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");
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");
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
,
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");
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");
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");
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
,
1134 printf("%s: couldn't create encodings: %d\n",
1135 device_xname(self
), err
);
1139 callout_init(&sc
->sc_volume_button_ch
, 0);
1141 audio_attach_mi(&mavb_sa_hw_if
, sc
, &sc
->sc_dev
);
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
|
1153 return bus_space_read_8(sc
->sc_st
, sc
->sc_sh
, MAVB_CODEC_STATUS
);
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
);
1163 return bus_space_read_8(sc
->sc_st
, sc
->sc_sh
, MAVB_CODEC_STATUS
);
1167 ad1843_dump_regs(struct mavb_softc
*sc
)
1171 for (addr
= 0; addr
< AD1843_NREGS
; addr
++)
1172 printf("%d: 0x%04x\n", addr
, ad1843_reg_read(sc
, addr
));