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