Home | History | Annotate | Line # | Download | only in dev
snapper.c revision 1.2
      1 /*	$NetBSD: snapper.c,v 1.2 2004/10/29 12:57:16 yamt Exp $	*/
      2 /*	Id: snapper.c,v 1.11 2002/10/31 17:42:13 tsubai Exp	*/
      3 
      4 /*-
      5  * Copyright (c) 2002 Tsubai Masanari.  All rights reserved.
      6  *
      7  * Redistribution and use in source and binary forms, with or without
      8  * modification, are permitted provided that the following conditions
      9  * are met:
     10  * 1. Redistributions of source code must retain the above copyright
     11  *    notice, this list of conditions and the following disclaimer.
     12  * 2. Redistributions in binary form must reproduce the above copyright
     13  *    notice, this list of conditions and the following disclaimer in the
     14  *    documentation and/or other materials provided with the distribution.
     15  * 3. The name of the author may not be used to endorse or promote products
     16  *    derived from this software without specific prior written permission.
     17  *
     18  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
     19  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
     20  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
     21  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
     22  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
     23  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
     24  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
     25  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     26  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
     27  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     28  */
     29 
     30 /*
     31  * Datasheet is available from
     32  * http://www.ti.com/sc/docs/products/analog/tas3004.html
     33  */
     34 
     35 #include <sys/param.h>
     36 #include <sys/audioio.h>
     37 #include <sys/device.h>
     38 #include <sys/systm.h>
     39 
     40 #include <dev/auconv.h>
     41 #include <dev/audio_if.h>
     42 #include <dev/mulaw.h>
     43 #include <dev/ofw/openfirm.h>
     44 #include <macppc/dev/dbdma.h>
     45 
     46 #include <uvm/uvm_extern.h>
     47 
     48 #include <machine/autoconf.h>
     49 #include <machine/pio.h>
     50 
     51 #ifdef SNAPPER_DEBUG
     52 # define DPRINTF printf
     53 #else
     54 # define DPRINTF while (0) printf
     55 #endif
     56 
     57 struct snapper_softc {
     58 	struct device sc_dev;
     59 	int sc_flags;
     60 	int sc_node;
     61 
     62 	void (*sc_ointr)(void *);	/* dma completion intr handler */
     63 	void *sc_oarg;			/* arg for sc_ointr() */
     64 	int sc_opages;			/* # of output pages */
     65 
     66 	void (*sc_iintr)(void *);	/* dma completion intr handler */
     67 	void *sc_iarg;			/* arg for sc_iintr() */
     68 
     69 	u_int sc_record_source;		/* recording source mask */
     70 	u_int sc_output_mask;		/* output source mask */
     71 
     72 	u_char *sc_reg;
     73 	struct device *sc_i2c;
     74 
     75 	u_int sc_vol_l;
     76 	u_int sc_vol_r;
     77 
     78 	dbdma_regmap_t *sc_odma;
     79 	dbdma_regmap_t *sc_idma;
     80 	struct dbdma_command sc_odmacmd[20];
     81 	struct dbdma_command sc_idmacmd[20];
     82 };
     83 
     84 int snapper_match(struct device *, struct cfdata *, void *);
     85 void snapper_attach(struct device *, struct device *, void *);
     86 void snapper_defer(struct device *);
     87 int snapper_intr(void *);
     88 int snapper_open(void *, int);
     89 void snapper_close(void *);
     90 int snapper_query_encoding(void *, struct audio_encoding *);
     91 int snapper_set_params(void *, int, int, struct audio_params *,
     92     struct audio_params *);
     93 int snapper_round_blocksize(void *, int);
     94 int snapper_halt_output(void *);
     95 int snapper_halt_input(void *);
     96 int snapper_getdev(void *, struct audio_device *);
     97 int snapper_set_port(void *, mixer_ctrl_t *);
     98 int snapper_get_port(void *, mixer_ctrl_t *);
     99 int snapper_query_devinfo(void *, mixer_devinfo_t *);
    100 size_t snapper_round_buffersize(void *, int, size_t);
    101 paddr_t snapper_mappage(void *, void *, off_t, int);
    102 int snapper_get_props(void *);
    103 int snapper_trigger_output(void *, void *, void *, int, void (*)(void *),
    104     void *, struct audio_params *);
    105 int snapper_trigger_input(void *, void *, void *, int, void (*)(void *),
    106     void *, struct audio_params *);
    107 void snapper_set_volume(struct snapper_softc *, int, int);
    108 int snapper_set_rate(struct snapper_softc *, int);
    109 
    110 int tas3004_write(struct snapper_softc *, u_int, const void *);
    111 static int gpio_read(char *);
    112 static void gpio_write(char *, int);
    113 void snapper_mute_speaker(struct snapper_softc *, int);
    114 void snapper_mute_headphone(struct snapper_softc *, int);
    115 int snapper_cint(void *);
    116 int tas3004_init(struct snapper_softc *);
    117 void snapper_init(struct snapper_softc *, int);
    118 
    119 static void mono16_to_stereo16(void *, u_char *, int);
    120 static void swap_bytes_mono16_to_stereo16(void *, u_char *, int);
    121 
    122 /* XXX */
    123 int ki2c_setmode(struct device *, int);
    124 int ki2c_write(struct device *, int, int, const void *, int);
    125 void ki2c_writereg(struct device *, int, u_int);
    126 
    127 
    128 struct cfattach snapper_ca = {
    129 	"snapper", {}, sizeof(struct snapper_softc),
    130 	snapper_match, snapper_attach
    131 };
    132 
    133 const struct audio_hw_if snapper_hw_if = {
    134 	snapper_open,
    135 	snapper_close,
    136 	NULL,
    137 	snapper_query_encoding,
    138 	snapper_set_params,
    139 	snapper_round_blocksize,
    140 	NULL,
    141 	NULL,
    142 	NULL,
    143 	NULL,
    144 	NULL,
    145 	snapper_halt_output,
    146 	snapper_halt_input,
    147 	NULL,
    148 	snapper_getdev,
    149 	NULL,
    150 	snapper_set_port,
    151 	snapper_get_port,
    152 	snapper_query_devinfo,
    153 	NULL,
    154 	NULL,
    155 	snapper_round_buffersize,
    156 	snapper_mappage,
    157 	snapper_get_props,
    158 	snapper_trigger_output,
    159 	snapper_trigger_input,
    160 	NULL
    161 };
    162 
    163 struct audio_device snapper_device = {
    164 	"SNAPPER",
    165 	"",
    166 	"snapper"
    167 };
    168 
    169 static u_char *amp_mute;
    170 static u_char *headphone_mute;
    171 static u_char *audio_hw_reset;
    172 static u_char *headphone_detect;
    173 static int headphone_detect_active;
    174 
    175 
    176 /* I2S registers */
    177 #define I2S_INT		0x00
    178 #define I2S_FORMAT	0x10
    179 #define I2S_FRAMECOUNT	0x40
    180 #define I2S_FRAMEMATCH	0x50
    181 #define I2S_WORDSIZE	0x60
    182 
    183 /* TAS3004 registers */
    184 #define DEQ_MCR1	0x01	/* Main control register 1 (1byte) */
    185 #define DEQ_DRC		0x02	/* Dynamic range compression (6bytes?) */
    186 #define DEQ_VOLUME	0x04	/* Volume (6bytes) */
    187 #define DEQ_TREBLE	0x05	/* Treble control (1byte) */
    188 #define DEQ_BASS	0x06	/* Bass control (1byte) */
    189 #define DEQ_MIXER_L	0x07	/* Mixer left gain (9bytes) */
    190 #define DEQ_MIXER_R	0x08	/* Mixer right gain (9bytes) */
    191 #define DEQ_LB0		0x0a	/* Left biquad 0 (15bytes) */
    192 #define DEQ_LB1		0x0b	/* Left biquad 1 (15bytes) */
    193 #define DEQ_LB2		0x0c	/* Left biquad 2 (15bytes) */
    194 #define DEQ_LB3		0x0d	/* Left biquad 3 (15bytes) */
    195 #define DEQ_LB4		0x0e	/* Left biquad 4 (15bytes) */
    196 #define DEQ_LB5		0x0f	/* Left biquad 5 (15bytes) */
    197 #define DEQ_LB6		0x10	/* Left biquad 6 (15bytes) */
    198 #define DEQ_RB0		0x13	/* Right biquad 0 (15bytes) */
    199 #define DEQ_RB1		0x14	/* Right biquad 1 (15bytes) */
    200 #define DEQ_RB2		0x15	/* Right biquad 2 (15bytes) */
    201 #define DEQ_RB3		0x16	/* Right biquad 3 (15bytes) */
    202 #define DEQ_RB4		0x17	/* Right biquad 4 (15bytes) */
    203 #define DEQ_RB5		0x18	/* Right biquad 5 (15bytes) */
    204 #define DEQ_RB6		0x19	/* Right biquad 6 (15bytes) */
    205 #define DEQ_LLB		0x21	/* Left loudness biquad (15bytes) */
    206 #define DEQ_RLB		0x22	/* Right loudness biquad (15bytes) */
    207 #define DEQ_LLB_GAIN	0x23	/* Left loudness biquad gain (3bytes) */
    208 #define DEQ_RLB_GAIN	0x24	/* Right loudness biquad gain (3bytes) */
    209 #define DEQ_ACR		0x40	/* Analog control register (1byte) */
    210 #define DEQ_MCR2	0x43	/* Main control register 2 (1byte) */
    211 
    212 #define DEQ_MCR1_FL	0x80	/* Fast load */
    213 #define DEQ_MCR1_SC	0x40	/* SCLK frequency */
    214 #define  DEQ_MCR1_SC_32	0x00	/*  32fs */
    215 #define  DEQ_MCR1_SC_64	0x40	/*  64fs */
    216 #define DEQ_MCR1_SM	0x30	/* Output serial port mode */
    217 #define  DEQ_MCR1_SM_L	0x00	/*  Left justified */
    218 #define  DEQ_MCR1_SM_R	0x10	/*  Right justified */
    219 #define  DEQ_MCR1_SM_I2S 0x20	/*  I2S */
    220 #define DEQ_MCR1_W	0x03	/* Serial port word length */
    221 #define  DEQ_MCR1_W_16	0x00	/*  16 bit */
    222 #define  DEQ_MCR1_W_18	0x01	/*  18 bit */
    223 #define  DEQ_MCR1_W_20	0x02	/*  20 bit */
    224 
    225 #define DEQ_MCR2_DL	0x80	/* Download */
    226 #define DEQ_MCR2_AP	0x02	/* All pass mode */
    227 
    228 #define DEQ_ACR_ADM	0x80	/* ADC output mode */
    229 #define DEQ_ACR_LRB	0x40	/* Select B input */
    230 #define DEQ_ACR_DM	0x0c	/* De-emphasis control */
    231 #define  DEQ_ACR_DM_OFF	0x00	/*  off */
    232 #define  DEQ_ACR_DM_48	0x04	/*  fs = 48kHz */
    233 #define  DEQ_ACR_DM_44	0x08	/*  fs = 44.1kHz */
    234 #define DEQ_ACR_INP	0x02	/* Analog input select */
    235 #define  DEQ_ACR_INP_A	0x00	/*  A */
    236 #define  DEQ_ACR_INP_B	0x02	/*  B */
    237 #define DEQ_ACR_APD	0x01	/* Analog power down */
    238 
    239 struct tas3004_reg {
    240 	u_char MCR1[1];
    241 	u_char DRC[6];
    242 	u_char VOLUME[6];
    243 	u_char TREBLE[1];
    244 	u_char BASS[1];
    245 	u_char MIXER_L[9];
    246 	u_char MIXER_R[9];
    247 	u_char LB0[15];
    248 	u_char LB1[15];
    249 	u_char LB2[15];
    250 	u_char LB3[15];
    251 	u_char LB4[15];
    252 	u_char LB5[15];
    253 	u_char LB6[15];
    254 	u_char RB0[15];
    255 	u_char RB1[15];
    256 	u_char RB2[15];
    257 	u_char RB3[15];
    258 	u_char RB4[15];
    259 	u_char RB5[15];
    260 	u_char RB6[15];
    261 	u_char LLB[15];
    262 	u_char RLB[15];
    263 	u_char LLB_GAIN[3];
    264 	u_char RLB_GAIN[3];
    265 	u_char ACR[1];
    266 	u_char MCR2[1];
    267 };
    268 
    269 #define GPIO_OUTSEL	0xf0	/* Output select */
    270 		/*	0x00	GPIO bit0 is output
    271 			0x10	media-bay power
    272 			0x20	reserved
    273 			0x30	MPIC */
    274 
    275 #define GPIO_ALTOE	0x08	/* Alternate output enable */
    276 		/*	0x00	Use DDR
    277 			0x08	Use output select */
    278 
    279 #define GPIO_DDR	0x04	/* Data direction */
    280 #define GPIO_DDR_OUTPUT	0x04	/* Output */
    281 #define GPIO_DDR_INPUT	0x00	/* Input */
    282 
    283 #define GPIO_LEVEL	0x02	/* Pin level (RO) */
    284 
    285 #define	GPIO_DATA	0x01	/* Data */
    286 
    287 int
    288 snapper_match(parent, match, aux)
    289 	struct device *parent;
    290 	struct cfdata *match;
    291 	void *aux;
    292 {
    293 	struct confargs *ca = aux;
    294 	int soundbus, soundchip;
    295 	char compat[32];
    296 
    297 	if (strcmp(ca->ca_name, "i2s") != 0)
    298 		return 0;
    299 
    300 	if ((soundbus = OF_child(ca->ca_node)) == 0 ||
    301 	    (soundchip = OF_child(soundbus)) == 0)
    302 		return 0;
    303 
    304 	bzero(compat, sizeof compat);
    305 	OF_getprop(soundchip, "compatible", compat, sizeof compat);
    306 
    307 	if (strcmp(compat, "snapper") != 0)
    308 		return 0;
    309 
    310 	return 1;
    311 }
    312 
    313 void
    314 snapper_attach(parent, self, aux)
    315 	struct device *parent;
    316 	struct device *self;
    317 	void *aux;
    318 {
    319 	struct snapper_softc *sc = (struct snapper_softc *)self;
    320 	struct confargs *ca = aux;
    321 	int cirq, oirq, iirq, cirq_type, oirq_type, iirq_type;
    322 	int soundbus, intr[6];
    323 
    324 #ifdef DIAGNOSTIC
    325 	if ((vaddr_t)sc->sc_odmacmd & 0x0f) {
    326 		printf(": bad dbdma alignment\n");
    327 		return;
    328 	}
    329 #endif
    330 
    331 	ca->ca_reg[0] += ca->ca_baseaddr;
    332 	ca->ca_reg[2] += ca->ca_baseaddr;
    333 	ca->ca_reg[4] += ca->ca_baseaddr;
    334 
    335 	sc->sc_node = ca->ca_node;
    336 	sc->sc_reg = (void *)ca->ca_reg[0];
    337 	sc->sc_odma = (void *)ca->ca_reg[2];
    338 	sc->sc_idma = (void *)ca->ca_reg[4];
    339 
    340 	soundbus = OF_child(ca->ca_node);
    341 	OF_getprop(soundbus, "interrupts", intr, sizeof intr);
    342 	cirq = intr[0];
    343 	oirq = intr[2];
    344 	iirq = intr[4];
    345 	cirq_type = intr[1] ? IST_LEVEL : IST_EDGE;
    346 	oirq_type = intr[3] ? IST_LEVEL : IST_EDGE;
    347 	iirq_type = intr[5] ? IST_LEVEL : IST_EDGE;
    348 
    349 	/* intr_establish(cirq, cirq_type, IPL_AUDIO, snapper_intr, sc); */
    350 	intr_establish(oirq, oirq_type, IPL_AUDIO, snapper_intr, sc);
    351 	/* intr_establish(iirq, iirq_type, IPL_AUDIO, snapper_intr, sc); */
    352 
    353 	printf("%s: irq %d,%d,%d\n", sc->sc_dev.dv_xname, cirq, oirq, iirq);
    354 
    355 	config_interrupts(self, snapper_defer);
    356 }
    357 
    358 void
    359 snapper_defer(struct device *dev)
    360 {
    361 	struct snapper_softc *sc = (struct snapper_softc *)dev;
    362 	struct device *dv;
    363 
    364 	for (dv = alldevs.tqh_first; dv; dv=dv->dv_list.tqe_next)
    365 		if (strncmp(dv->dv_xname, "ki2c", 4) == 0 &&
    366 		    strncmp(dv->dv_parent->dv_xname, "obio", 4) == 0)
    367 			sc->sc_i2c = dv;
    368 	if (sc->sc_i2c == NULL) {
    369 		printf("%s: unable to find i2c\n", sc->sc_dev.dv_xname);
    370 		return;
    371 	}
    372 
    373 	/* XXX If i2c was failed to attach, what should we do? */
    374 
    375 	audio_attach_mi(&snapper_hw_if, sc, &sc->sc_dev);
    376 
    377 	/* ki2c_setmode(sc->sc_i2c, I2C_STDSUBMODE); */
    378 	snapper_init(sc, sc->sc_node);
    379 }
    380 
    381 int
    382 snapper_intr(v)
    383 	void *v;
    384 {
    385 	struct snapper_softc *sc = v;
    386 	struct dbdma_command *cmd = sc->sc_odmacmd;
    387 	int count = sc->sc_opages;
    388 	int status;
    389 
    390 	/* Fill used buffer(s). */
    391 	while (count-- > 0) {
    392 		if ((dbdma_ld16(&cmd->d_command) & 0x30) == 0x30) {
    393 			status = dbdma_ld16(&cmd->d_status);
    394 			cmd->d_status = 0;
    395 			if (status)	/* status == 0x8400 */
    396 				if (sc->sc_ointr)
    397 					(*sc->sc_ointr)(sc->sc_oarg);
    398 		}
    399 		cmd++;
    400 	}
    401 
    402 	return 1;
    403 }
    404 
    405 int
    406 snapper_open(h, flags)
    407 	void *h;
    408 	int flags;
    409 {
    410 	return 0;
    411 }
    412 
    413 /*
    414  * Close function is called at splaudio().
    415  */
    416 void
    417 snapper_close(h)
    418 	void *h;
    419 {
    420 	struct snapper_softc *sc = h;
    421 
    422 	snapper_halt_output(sc);
    423 	snapper_halt_input(sc);
    424 
    425 	sc->sc_ointr = 0;
    426 	sc->sc_iintr = 0;
    427 }
    428 
    429 int
    430 snapper_query_encoding(h, ae)
    431 	void *h;
    432 	struct audio_encoding *ae;
    433 {
    434 	ae->flags = AUDIO_ENCODINGFLAG_EMULATED;
    435 
    436 	switch (ae->index) {
    437 	case 0:
    438 		strcpy(ae->name, AudioEslinear);
    439 		ae->encoding = AUDIO_ENCODING_SLINEAR;
    440 		ae->precision = 16;
    441 		ae->flags = 0;
    442 		return 0;
    443 	case 1:
    444 		strcpy(ae->name, AudioEslinear_be);
    445 		ae->encoding = AUDIO_ENCODING_SLINEAR_BE;
    446 		ae->precision = 16;
    447 		ae->flags = 0;
    448 		return 0;
    449 	case 2:
    450 		strcpy(ae->name, AudioEslinear_le);
    451 		ae->encoding = AUDIO_ENCODING_SLINEAR_LE;
    452 		ae->precision = 16;
    453 		return 0;
    454 	case 3:
    455 		strcpy(ae->name, AudioEulinear_be);
    456 		ae->encoding = AUDIO_ENCODING_ULINEAR_BE;
    457 		ae->precision = 16;
    458 		return 0;
    459 	case 4:
    460 		strcpy(ae->name, AudioEulinear_le);
    461 		ae->encoding = AUDIO_ENCODING_ULINEAR_LE;
    462 		ae->precision = 16;
    463 		return 0;
    464 	case 5:
    465 		strcpy(ae->name, AudioEmulaw);
    466 		ae->encoding = AUDIO_ENCODING_ULAW;
    467 		ae->precision = 8;
    468 		return 0;
    469 	case 6:
    470 		strcpy(ae->name, AudioEalaw);
    471 		ae->encoding = AUDIO_ENCODING_ALAW;
    472 		ae->precision = 8;
    473 		return 0;
    474 	default:
    475 		return EINVAL;
    476 	}
    477 }
    478 
    479 static void
    480 mono16_to_stereo16(v, p, cc)
    481 	void *v;
    482 	u_char *p;
    483 	int cc;
    484 {
    485 	int x;
    486 	int16_t *src, *dst;
    487 
    488 	src = (void *)(p + cc);
    489 	dst = (void *)(p + cc * 2);
    490 	while (cc > 0) {
    491 		x = *--src;
    492 		*--dst = x;
    493 		*--dst = x;
    494 		cc -= 2;
    495 	}
    496 }
    497 
    498 static void
    499 swap_bytes_mono16_to_stereo16(v, p, cc)
    500 	void *v;
    501 	u_char *p;
    502 	int cc;
    503 {
    504 	swap_bytes(v, p, cc);
    505 	mono16_to_stereo16(v, p, cc);
    506 }
    507 
    508 int
    509 snapper_set_params(h, setmode, usemode, play, rec)
    510 	void *h;
    511 	int setmode, usemode;
    512 	struct audio_params *play, *rec;
    513 {
    514 	struct snapper_softc *sc = h;
    515 	struct audio_params *p;
    516 	int mode, rate;
    517 
    518 	p = NULL;
    519 
    520 	/*
    521 	 * This device only has one clock, so make the sample rates match.
    522 	 */
    523 	if (play->sample_rate != rec->sample_rate &&
    524 	    usemode == (AUMODE_PLAY | AUMODE_RECORD)) {
    525 		if (setmode == AUMODE_PLAY) {
    526 			rec->sample_rate = play->sample_rate;
    527 			setmode |= AUMODE_RECORD;
    528 		} else if (setmode == AUMODE_RECORD) {
    529 			play->sample_rate = rec->sample_rate;
    530 			setmode |= AUMODE_PLAY;
    531 		} else
    532 			return EINVAL;
    533 	}
    534 
    535 	for (mode = AUMODE_RECORD; mode != -1;
    536 	     mode = mode == AUMODE_RECORD ? AUMODE_PLAY : -1) {
    537 		if ((setmode & mode) == 0)
    538 			continue;
    539 
    540 		p = mode == AUMODE_PLAY ? play : rec;
    541 
    542 		if (p->sample_rate < 4000 || p->sample_rate > 50000 ||
    543 		    (p->precision != 8 && p->precision != 16) ||
    544 		    (p->channels != 1 && p->channels != 2))
    545 			return EINVAL;
    546 
    547 		p->factor = 1;
    548 		p->sw_code = 0;
    549 
    550 		switch (p->encoding) {
    551 
    552 		case AUDIO_ENCODING_SLINEAR_LE:
    553 			if (p->channels == 2 && p->precision == 16) {
    554 				p->sw_code = swap_bytes;
    555 				break;
    556 			}
    557 			if (p->channels == 1 && p->precision == 16) {
    558 				p->factor = 2;
    559 				p->sw_code = swap_bytes_mono16_to_stereo16;
    560 				break;
    561 			}
    562 			return EINVAL;
    563 		case AUDIO_ENCODING_SLINEAR_BE:
    564 			if (p->channels == 1 && p->precision == 16) {
    565 				p->factor = 2;
    566 				p->sw_code = mono16_to_stereo16;
    567 				break;
    568 			}
    569 			if (p->channels == 2 && p->precision == 16)
    570 				break;
    571 
    572 			return EINVAL;
    573 
    574 		case AUDIO_ENCODING_ULINEAR_LE:
    575 			if (p->channels == 2 && p->precision == 16) {
    576 				p->sw_code = swap_bytes_change_sign16_be;
    577 				break;
    578 			}
    579 			return EINVAL;
    580 
    581 		case AUDIO_ENCODING_ULINEAR_BE:
    582 			if (p->channels == 2 && p->precision == 16) {
    583 				p->sw_code = change_sign16_be;
    584 				break;
    585 			}
    586 			return EINVAL;
    587 
    588 		case AUDIO_ENCODING_ULAW:
    589 			if (mode == AUMODE_PLAY) {
    590 				p->factor = 2;
    591 				p->sw_code = mulaw_to_slinear16_be;
    592 				break;
    593 			} else
    594 				break;		/* XXX */
    595 
    596 			return EINVAL;
    597 
    598 		case AUDIO_ENCODING_ALAW:
    599 			if (mode == AUMODE_PLAY) {
    600 				p->factor = 2;
    601 				p->sw_code = alaw_to_slinear16_be;
    602 				break;
    603 			}
    604 			return EINVAL;
    605 
    606 		default:
    607 			return EINVAL;
    608 		}
    609 	}
    610 
    611 	/* Set the speed */
    612 	rate = p->sample_rate;
    613 
    614 	if (snapper_set_rate(sc, rate))
    615 		return EINVAL;
    616 
    617 	return 0;
    618 }
    619 
    620 int
    621 snapper_round_blocksize(h, size)
    622 	void *h;
    623 	int size;
    624 {
    625 	if (size < NBPG)
    626 		size = NBPG;
    627 	return size & ~PGOFSET;
    628 }
    629 
    630 int
    631 snapper_halt_output(h)
    632 	void *h;
    633 {
    634 	struct snapper_softc *sc = h;
    635 
    636 	dbdma_stop(sc->sc_odma);
    637 	dbdma_reset(sc->sc_odma);
    638 	return 0;
    639 }
    640 
    641 int
    642 snapper_halt_input(h)
    643 	void *h;
    644 {
    645 	struct snapper_softc *sc = h;
    646 
    647 	dbdma_stop(sc->sc_idma);
    648 	dbdma_reset(sc->sc_idma);
    649 	return 0;
    650 }
    651 
    652 int
    653 snapper_getdev(h, retp)
    654 	void *h;
    655 	struct audio_device *retp;
    656 {
    657 	*retp = snapper_device;
    658 	return 0;
    659 }
    660 
    661 enum {
    662 	SNAPPER_MONITOR_CLASS,
    663 	SNAPPER_OUTPUT_CLASS,
    664 	SNAPPER_RECORD_CLASS,
    665 	SNAPPER_OUTPUT_SELECT,
    666 	SNAPPER_VOL_OUTPUT,
    667 	SNAPPER_INPUT_SELECT,
    668 	SNAPPER_VOL_INPUT,
    669 	SNAPPER_ENUM_LAST
    670 };
    671 
    672 int
    673 snapper_set_port(h, mc)
    674 	void *h;
    675 	mixer_ctrl_t *mc;
    676 {
    677 	struct snapper_softc *sc = h;
    678 	int l, r;
    679 
    680 	DPRINTF("snapper_set_port dev = %d, type = %d\n", mc->dev, mc->type);
    681 
    682 	l = mc->un.value.level[AUDIO_MIXER_LEVEL_LEFT];
    683 	r = mc->un.value.level[AUDIO_MIXER_LEVEL_RIGHT];
    684 
    685 	switch (mc->dev) {
    686 	case SNAPPER_OUTPUT_SELECT:
    687 		/* No change necessary? */
    688 		if (mc->un.mask == sc->sc_output_mask)
    689 			return 0;
    690 
    691 		snapper_mute_speaker(sc, 1);
    692 		snapper_mute_headphone(sc, 1);
    693 		if (mc->un.mask & 1 << 0)
    694 			snapper_mute_speaker(sc, 0);
    695 		if (mc->un.mask & 1 << 1)
    696 			snapper_mute_headphone(sc, 0);
    697 
    698 		sc->sc_output_mask = mc->un.mask;
    699 		return 0;
    700 
    701 	case SNAPPER_VOL_OUTPUT:
    702 		snapper_set_volume(sc, l, r);
    703 		return 0;
    704 
    705 	case SNAPPER_INPUT_SELECT:
    706 		/* no change necessary? */
    707 		if (mc->un.mask == sc->sc_record_source)
    708 			return 0;
    709 		switch (mc->un.mask) {
    710 		case 1 << 0: /* CD */
    711 		case 1 << 1: /* microphone */
    712 		case 1 << 2: /* line in */
    713 			/* XXX TO BE DONE */
    714 			break;
    715 		default: /* invalid argument */
    716 			return EINVAL;
    717 		}
    718 		sc->sc_record_source = mc->un.mask;
    719 		return 0;
    720 
    721 	case SNAPPER_VOL_INPUT:
    722 		/* XXX TO BE DONE */
    723 		return 0;
    724 	}
    725 
    726 	return ENXIO;
    727 }
    728 
    729 int
    730 snapper_get_port(h, mc)
    731 	void *h;
    732 	mixer_ctrl_t *mc;
    733 {
    734 	struct snapper_softc *sc = h;
    735 
    736 	DPRINTF("snapper_get_port dev = %d, type = %d\n", mc->dev, mc->type);
    737 
    738 	switch (mc->dev) {
    739 	case SNAPPER_OUTPUT_SELECT:
    740 		mc->un.mask = sc->sc_output_mask;
    741 		return 0;
    742 
    743 	case SNAPPER_VOL_OUTPUT:
    744 		mc->un.value.level[AUDIO_MIXER_LEVEL_LEFT] = sc->sc_vol_l;
    745 		mc->un.value.level[AUDIO_MIXER_LEVEL_RIGHT] = sc->sc_vol_r;
    746 		return 0;
    747 
    748 	case SNAPPER_INPUT_SELECT:
    749 		mc->un.mask = sc->sc_record_source;
    750 		return 0;
    751 
    752 	case SNAPPER_VOL_INPUT:
    753 		/* XXX TO BE DONE */
    754 		mc->un.value.level[AUDIO_MIXER_LEVEL_LEFT] = 0;
    755 		mc->un.value.level[AUDIO_MIXER_LEVEL_RIGHT] = 0;
    756 		return 0;
    757 
    758 	default:
    759 		return ENXIO;
    760 	}
    761 
    762 	return 0;
    763 }
    764 
    765 int
    766 snapper_query_devinfo(h, dip)
    767 	void *h;
    768 	mixer_devinfo_t *dip;
    769 {
    770 	switch (dip->index) {
    771 
    772 	case SNAPPER_OUTPUT_SELECT:
    773 		dip->mixer_class = SNAPPER_MONITOR_CLASS;
    774 		strcpy(dip->label.name, AudioNoutput);
    775 		dip->type = AUDIO_MIXER_SET;
    776 		dip->prev = dip->next = AUDIO_MIXER_LAST;
    777 		dip->un.s.num_mem = 2;
    778 		strcpy(dip->un.s.member[0].label.name, AudioNspeaker);
    779 		dip->un.s.member[0].mask = 1 << 0;
    780 		strcpy(dip->un.s.member[1].label.name, AudioNheadphone);
    781 		dip->un.s.member[1].mask = 1 << 1;
    782 		return 0;
    783 
    784 	case SNAPPER_VOL_OUTPUT:
    785 		dip->mixer_class = SNAPPER_MONITOR_CLASS;
    786 		strcpy(dip->label.name, AudioNmaster);
    787 		dip->type = AUDIO_MIXER_VALUE;
    788 		dip->prev = dip->next = AUDIO_MIXER_LAST;
    789 		dip->un.v.num_channels = 2;
    790 		strcpy(dip->un.v.units.name, AudioNvolume);
    791 		return 0;
    792 
    793 	case SNAPPER_INPUT_SELECT:
    794 		dip->mixer_class = SNAPPER_RECORD_CLASS;
    795 		strcpy(dip->label.name, AudioNsource);
    796 		dip->type = AUDIO_MIXER_SET;
    797 		dip->prev = dip->next = AUDIO_MIXER_LAST;
    798 		dip->un.s.num_mem = 3;
    799 		strcpy(dip->un.s.member[0].label.name, AudioNcd);
    800 		dip->un.s.member[0].mask = 1 << 0;
    801 		strcpy(dip->un.s.member[1].label.name, AudioNmicrophone);
    802 		dip->un.s.member[1].mask = 1 << 1;
    803 		strcpy(dip->un.s.member[2].label.name, AudioNline);
    804 		dip->un.s.member[2].mask = 1 << 2;
    805 		return 0;
    806 
    807 	case SNAPPER_VOL_INPUT:
    808 		dip->mixer_class = SNAPPER_RECORD_CLASS;
    809 		strcpy(dip->label.name, AudioNrecord);
    810 		dip->type = AUDIO_MIXER_VALUE;
    811 		dip->prev = dip->next = AUDIO_MIXER_LAST;
    812 		dip->un.v.num_channels = 2;
    813 		strcpy(dip->un.v.units.name, AudioNvolume);
    814 		return 0;
    815 
    816 	case SNAPPER_MONITOR_CLASS:
    817 		dip->mixer_class = SNAPPER_MONITOR_CLASS;
    818 		strcpy(dip->label.name, AudioCmonitor);
    819 		dip->type = AUDIO_MIXER_CLASS;
    820 		dip->next = dip->prev = AUDIO_MIXER_LAST;
    821 		return 0;
    822 
    823 	case SNAPPER_OUTPUT_CLASS:
    824 		dip->mixer_class = SNAPPER_OUTPUT_CLASS;
    825 		strcpy(dip->label.name, AudioCoutputs);
    826 		dip->type = AUDIO_MIXER_CLASS;
    827 		dip->next = dip->prev = AUDIO_MIXER_LAST;
    828 		return 0;
    829 
    830 	case SNAPPER_RECORD_CLASS:
    831 		dip->mixer_class = SNAPPER_RECORD_CLASS;
    832 		strcpy(dip->label.name, AudioCrecord);
    833 		dip->type = AUDIO_MIXER_CLASS;
    834 		dip->next = dip->prev = AUDIO_MIXER_LAST;
    835 		return 0;
    836 	}
    837 
    838 	return ENXIO;
    839 }
    840 
    841 size_t
    842 snapper_round_buffersize(h, dir, size)
    843 	void *h;
    844 	int dir;
    845 	size_t size;
    846 {
    847 	if (size > 65536)
    848 		size = 65536;
    849 	return size;
    850 }
    851 
    852 paddr_t
    853 snapper_mappage(h, mem, off, prot)
    854 	void *h;
    855 	void *mem;
    856 	off_t off;
    857 	int prot;
    858 {
    859 	if (off < 0)
    860 		return -1;
    861 	return -1;	/* XXX */
    862 }
    863 
    864 int
    865 snapper_get_props(h)
    866 	void *h;
    867 {
    868 	return AUDIO_PROP_FULLDUPLEX /* | AUDIO_PROP_MMAP */;
    869 }
    870 
    871 int
    872 snapper_trigger_output(h, start, end, bsize, intr, arg, param)
    873 	void *h;
    874 	void *start, *end;
    875 	int bsize;
    876 	void (*intr)(void *);
    877 	void *arg;
    878 	struct audio_params *param;
    879 {
    880 	struct snapper_softc *sc = h;
    881 	struct dbdma_command *cmd = sc->sc_odmacmd;
    882 	vaddr_t va;
    883 	int i, len, intmode;
    884 
    885 	DPRINTF("trigger_output %p %p 0x%x\n", start, end, bsize);
    886 
    887 	sc->sc_ointr = intr;
    888 	sc->sc_oarg = arg;
    889 	sc->sc_opages = ((char *)end - (char *)start) / NBPG;
    890 
    891 #ifdef DIAGNOSTIC
    892 	if (sc->sc_opages > 16)
    893 		panic("snapper_trigger_output");
    894 #endif
    895 
    896 	va = (vaddr_t)start;
    897 	len = 0;
    898 	for (i = sc->sc_opages; i > 0; i--) {
    899 		len += NBPG;
    900 		if (len < bsize)
    901 			intmode = 0;
    902 		else {
    903 			len = 0;
    904 			intmode = DBDMA_INT_ALWAYS;
    905 		}
    906 
    907 		DBDMA_BUILD(cmd, DBDMA_CMD_OUT_MORE, 0, NBPG, vtophys(va), intmode, DBDMA_WAIT_NEVER, DBDMA_BRANCH_NEVER);
    908 		cmd++;
    909 		va += NBPG;
    910 	}
    911 
    912 	DBDMA_BUILD(cmd, DBDMA_CMD_NOP, 0, 0,
    913 	    0/*vtophys((vaddr_t)sc->sc_odmacmd)*/, 0, DBDMA_WAIT_NEVER, DBDMA_BRANCH_ALWAYS);
    914 
    915 	dbdma_st32(&cmd->d_cmddep, vtophys((vaddr_t)sc->sc_odmacmd));
    916 
    917 	dbdma_start(sc->sc_odma, sc->sc_odmacmd);
    918 
    919 	return 0;
    920 }
    921 
    922 int
    923 snapper_trigger_input(h, start, end, bsize, intr, arg, param)
    924 	void *h;
    925 	void *start, *end;
    926 	int bsize;
    927 	void (*intr)(void *);
    928 	void *arg;
    929 	struct audio_params *param;
    930 {
    931 	printf("snapper_trigger_input called\n");
    932 
    933 	return 1;
    934 }
    935 
    936 void
    937 snapper_set_volume(sc, left, right)
    938 	struct snapper_softc *sc;
    939 	int left, right;
    940 {
    941 	u_char vol[6];
    942 
    943 	sc->sc_vol_l = left;
    944 	sc->sc_vol_r = right;
    945 
    946 	left <<= 8;	/* XXX for now */
    947 	right <<= 8;
    948 
    949 	vol[0] = left >> 16;
    950 	vol[1] = left >> 8;
    951 	vol[2] = left;
    952 	vol[3] = right >> 16;
    953 	vol[4] = right >> 8;
    954 	vol[5] = right;
    955 
    956 	tas3004_write(sc, DEQ_VOLUME, vol);
    957 }
    958 
    959 #define CLKSRC_49MHz	0x80000000	/* Use 49152000Hz Osc. */
    960 #define CLKSRC_45MHz	0x40000000	/* Use 45158400Hz Osc. */
    961 #define CLKSRC_18MHz	0x00000000	/* Use 18432000Hz Osc. */
    962 #define MCLK_DIV	0x1f000000	/* MCLK = SRC / DIV */
    963 #define  MCLK_DIV1	0x14000000	/*  MCLK = SRC */
    964 #define  MCLK_DIV3	0x13000000	/*  MCLK = SRC / 3 */
    965 #define  MCLK_DIV5	0x12000000	/*  MCLK = SRC / 5 */
    966 #define SCLK_DIV	0x00f00000	/* SCLK = MCLK / DIV */
    967 #define  SCLK_DIV1	0x00800000
    968 #define  SCLK_DIV3	0x00900000
    969 #define SCLK_MASTER	0x00080000	/* Master mode */
    970 #define SCLK_SLAVE	0x00000000	/* Slave mode */
    971 #define SERIAL_FORMAT	0x00070000
    972 #define  SERIAL_SONY	0x00000000
    973 #define  SERIAL_64x	0x00010000
    974 #define  SERIAL_32x	0x00020000
    975 #define  SERIAL_DAV	0x00040000
    976 #define  SERIAL_SILICON	0x00050000
    977 
    978 // rate = fs = LRCLK
    979 // SCLK = 64*LRCLK (I2S)
    980 // MCLK = 256fs (typ. -- changeable)
    981 
    982 // MCLK = clksrc / mdiv
    983 // SCLK = MCLK / sdiv
    984 // rate = SCLK / 64    ( = LRCLK = fs)
    985 
    986 int
    987 snapper_set_rate(sc, rate)
    988 	struct snapper_softc *sc;
    989 	int rate;
    990 {
    991 	u_int reg = 0;
    992 	int MCLK;
    993 	int clksrc, mdiv, sdiv;
    994 	int mclk_fs;
    995 
    996 	switch (rate) {
    997 	case 8000:
    998 		clksrc = 18432000;		/* 18MHz */
    999 		reg = CLKSRC_18MHz;
   1000 		mclk_fs = 256;
   1001 		break;
   1002 
   1003 	case 44100:
   1004 		clksrc = 45158400;		/* 45MHz */
   1005 		reg = CLKSRC_45MHz;
   1006 		mclk_fs = 256;
   1007 		break;
   1008 
   1009 	case 48000:
   1010 		clksrc = 49152000;		/* 49MHz */
   1011 		reg = CLKSRC_49MHz;
   1012 		mclk_fs = 256;
   1013 		break;
   1014 
   1015 	default:
   1016 		return EINVAL;
   1017 	}
   1018 
   1019 	MCLK = rate * mclk_fs;
   1020 	mdiv = clksrc / MCLK;			// 4
   1021 	sdiv = mclk_fs / 64;			// 4
   1022 
   1023 	switch (mdiv) {
   1024 	case 1:
   1025 		reg |= MCLK_DIV1;
   1026 		break;
   1027 	case 3:
   1028 		reg |= MCLK_DIV3;
   1029 		break;
   1030 	case 5:
   1031 		reg |= MCLK_DIV5;
   1032 		break;
   1033 	default:
   1034 		reg |= ((mdiv / 2 - 1) << 24) & 0x1f000000;
   1035 		break;
   1036 	}
   1037 
   1038 	switch (sdiv) {
   1039 	case 1:
   1040 		reg |= SCLK_DIV1;
   1041 		break;
   1042 	case 3:
   1043 		reg |= SCLK_DIV3;
   1044 		break;
   1045 	default:
   1046 		reg |= ((sdiv / 2 - 1) << 20) & 0x00f00000;
   1047 		break;
   1048 	}
   1049 
   1050 	reg |= SCLK_MASTER;	/* XXX master mode */
   1051 
   1052 	reg |= SERIAL_64x;
   1053 
   1054 	/* stereo input and output */
   1055 	DPRINTF("I2SSetDataWordSizeReg 0x%08x -> 0x%08x\n",
   1056 	    in32rb(sc->sc_reg + I2S_WORDSIZE), 0x02000200);
   1057 	out32rb(sc->sc_reg + I2S_WORDSIZE, 0x02000200);
   1058 
   1059 	DPRINTF("I2SSetSerialFormatReg 0x%x -> 0x%x\n",
   1060 	    in32rb(sc->sc_reg + I2S_FORMAT), reg);
   1061 	out32rb(sc->sc_reg + I2S_FORMAT, reg);
   1062 
   1063 	return 0;
   1064 }
   1065 
   1066 #define DEQaddr 0x6a
   1067 
   1068 const struct tas3004_reg tas3004_initdata = {
   1069 	{ DEQ_MCR1_SC_64 | DEQ_MCR1_SM_I2S | DEQ_MCR1_W_20 },	/* MCR1 */
   1070 	{ 1, 0, 0, 0, 0, 0 },					/* DRC */
   1071 	{ 0, 0, 0, 0, 0, 0 },					/* VOLUME */
   1072 	{ 0x72 },						/* TREBLE */
   1073 	{ 0x72 },						/* BASS */
   1074 	{ 0x10, 0x00, 0x00, 0, 0, 0, 0, 0, 0 },			/* MIXER_L */
   1075 	{ 0x10, 0x00, 0x00, 0, 0, 0, 0, 0, 0 },			/* MIXER_R */
   1076 	{ 0x10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },	/* BIQUAD */
   1077 	{ 0x10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },	/* BIQUAD */
   1078 	{ 0x10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },	/* BIQUAD */
   1079 	{ 0x10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },	/* BIQUAD */
   1080 	{ 0x10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },	/* BIQUAD */
   1081 	{ 0x10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },	/* BIQUAD */
   1082 	{ 0x10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },	/* BIQUAD */
   1083 	{ 0x10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },	/* BIQUAD */
   1084 	{ 0x10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },	/* BIQUAD */
   1085 	{ 0x10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },	/* BIQUAD */
   1086 	{ 0x10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },	/* BIQUAD */
   1087 	{ 0x10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },	/* BIQUAD */
   1088 	{ 0x10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },	/* BIQUAD */
   1089 	{ 0x10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },	/* BIQUAD */
   1090 	{ 0x10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },	/* BIQUAD */
   1091 	{ 0x10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },	/* BIQUAD */
   1092 	{ 0, 0, 0 },						/* LLB_GAIN */
   1093 	{ 0, 0, 0 },						/* RLB_GAIN */
   1094 	{ 0 },							/* ACR */
   1095 	{ 0 }							/* MCR2 */
   1096 };
   1097 
   1098 const char tas3004_regsize[] = {
   1099 	0,					/* 0x00 */
   1100 	sizeof tas3004_initdata.MCR1,		/* 0x01 */
   1101 	sizeof tas3004_initdata.DRC,		/* 0x02 */
   1102 	0,					/* 0x03 */
   1103 	sizeof tas3004_initdata.VOLUME,		/* 0x04 */
   1104 	sizeof tas3004_initdata.TREBLE,		/* 0x05 */
   1105 	sizeof tas3004_initdata.BASS,		/* 0x06 */
   1106 	sizeof tas3004_initdata.MIXER_L,	/* 0x07 */
   1107 	sizeof tas3004_initdata.MIXER_R,	/* 0x08 */
   1108 	0,					/* 0x09 */
   1109 	sizeof tas3004_initdata.LB0,		/* 0x0a */
   1110 	sizeof tas3004_initdata.LB1,		/* 0x0b */
   1111 	sizeof tas3004_initdata.LB2,		/* 0x0c */
   1112 	sizeof tas3004_initdata.LB3,		/* 0x0d */
   1113 	sizeof tas3004_initdata.LB4,		/* 0x0e */
   1114 	sizeof tas3004_initdata.LB5,		/* 0x0f */
   1115 	sizeof tas3004_initdata.LB6,		/* 0x10 */
   1116 	0,					/* 0x11 */
   1117 	0,					/* 0x12 */
   1118 	sizeof tas3004_initdata.RB0,		/* 0x13 */
   1119 	sizeof tas3004_initdata.RB1,		/* 0x14 */
   1120 	sizeof tas3004_initdata.RB2,		/* 0x15 */
   1121 	sizeof tas3004_initdata.RB3,		/* 0x16 */
   1122 	sizeof tas3004_initdata.RB4,		/* 0x17 */
   1123 	sizeof tas3004_initdata.RB5,		/* 0x18 */
   1124 	sizeof tas3004_initdata.RB6,		/* 0x19 */
   1125 	0,0,0,0, 0,0,
   1126 	0,					/* 0x20 */
   1127 	sizeof tas3004_initdata.LLB,		/* 0x21 */
   1128 	sizeof tas3004_initdata.RLB,		/* 0x22 */
   1129 	sizeof tas3004_initdata.LLB_GAIN,	/* 0x23 */
   1130 	sizeof tas3004_initdata.RLB_GAIN,	/* 0x24 */
   1131 	0,0,0,0, 0,0,0,0, 0,0,0,
   1132 	0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0,
   1133 	sizeof tas3004_initdata.ACR,		/* 0x40 */
   1134 	0,					/* 0x41 */
   1135 	0,					/* 0x42 */
   1136 	sizeof tas3004_initdata.MCR2		/* 0x43 */
   1137 };
   1138 
   1139 int
   1140 tas3004_write(sc, reg, data)
   1141 	struct snapper_softc *sc;
   1142 	u_int reg;
   1143 	const void *data;
   1144 {
   1145 	int size;
   1146 
   1147 	KASSERT(reg < sizeof tas3004_regsize);
   1148 	size = tas3004_regsize[reg];
   1149 	KASSERT(size > 0);
   1150 
   1151 	if (ki2c_write(sc->sc_i2c, DEQaddr, reg, data, size))
   1152 		return -1;
   1153 
   1154 	return 0;
   1155 }
   1156 
   1157 int
   1158 gpio_read(addr)
   1159 	char *addr;
   1160 {
   1161 	if (*addr & GPIO_DATA)
   1162 		return 1;
   1163 	return 0;
   1164 }
   1165 
   1166 void
   1167 gpio_write(addr, val)
   1168 	char *addr;
   1169 	int val;
   1170 {
   1171 	u_int data = GPIO_DDR_OUTPUT;
   1172 
   1173 	if (val)
   1174 		data |= GPIO_DATA;
   1175 	*addr = data;
   1176 	asm volatile ("eieio");
   1177 }
   1178 
   1179 #define headphone_active 0	/* XXX OF */
   1180 #define amp_active 0		/* XXX OF */
   1181 
   1182 void
   1183 snapper_mute_speaker(sc, mute)
   1184 	struct snapper_softc *sc;
   1185 	int mute;
   1186 {
   1187 	u_int x;
   1188 
   1189 	DPRINTF("ampmute %d --> ", gpio_read(amp_mute));
   1190 
   1191 	if (mute)
   1192 		x = amp_active;		/* mute */
   1193 	else
   1194 		x = !amp_active;	/* unmute */
   1195 	if (x != gpio_read(amp_mute))
   1196 		gpio_write(amp_mute, x);
   1197 
   1198 	DPRINTF("%d\n", gpio_read(amp_mute));
   1199 }
   1200 
   1201 void
   1202 snapper_mute_headphone(sc, mute)
   1203 	struct snapper_softc *sc;
   1204 	int mute;
   1205 {
   1206 	u_int x;
   1207 
   1208 	DPRINTF("headphonemute %d --> ", gpio_read(headphone_mute));
   1209 
   1210 	if (mute)
   1211 		x = headphone_active;	/* mute */
   1212 	else
   1213 		x = !headphone_active;	/* unmute */
   1214 	if (x != gpio_read(headphone_mute))
   1215 		gpio_write(headphone_mute, x);
   1216 
   1217 	DPRINTF("%d\n", gpio_read(headphone_mute));
   1218 }
   1219 
   1220 int
   1221 snapper_cint(v)
   1222 	void *v;
   1223 {
   1224 	struct snapper_softc *sc = v;
   1225 	u_int sense;
   1226 
   1227 	sense = *headphone_detect;
   1228 	DPRINTF("headphone detect = 0x%x\n", sense);
   1229 
   1230 	if (((sense & 0x02) >> 1) == headphone_detect_active) {
   1231 		DPRINTF("headphone is inserted\n");
   1232 		snapper_mute_speaker(sc, 1);
   1233 		snapper_mute_headphone(sc, 0);
   1234 		sc->sc_output_mask = 1 << 1;
   1235 	} else {
   1236 		DPRINTF("headphone is NOT inserted\n");
   1237 		snapper_mute_speaker(sc, 0);
   1238 		snapper_mute_headphone(sc, 1);
   1239 		sc->sc_output_mask = 1 << 0;
   1240 	}
   1241 
   1242 	return 1;
   1243 }
   1244 
   1245 #define reset_active 0	/* XXX OF */
   1246 
   1247 #define DEQ_WRITE(sc, reg, addr) \
   1248 	if (tas3004_write(sc, reg, addr)) goto err
   1249 
   1250 int
   1251 tas3004_init(sc)
   1252 	struct snapper_softc *sc;
   1253 {
   1254 
   1255 	/* No reset port.  Nothing to do. */
   1256 	if (audio_hw_reset == NULL)
   1257 		goto noreset;
   1258 
   1259 	/* Reset TAS3004. */
   1260 	gpio_write(audio_hw_reset, !reset_active);	/* Negate RESET */
   1261 	delay(100000);				/* XXX Really needed? */
   1262 
   1263 	gpio_write(audio_hw_reset, reset_active);	/* Assert RESET */
   1264 	delay(1);
   1265 
   1266 	gpio_write(audio_hw_reset, !reset_active);	/* Negate RESET */
   1267 	delay(10000);
   1268 
   1269 noreset:
   1270 	DEQ_WRITE(sc, DEQ_LB0, tas3004_initdata.LB0);
   1271 	DEQ_WRITE(sc, DEQ_LB1, tas3004_initdata.LB1);
   1272 	DEQ_WRITE(sc, DEQ_LB2, tas3004_initdata.LB2);
   1273 	DEQ_WRITE(sc, DEQ_LB3, tas3004_initdata.LB3);
   1274 	DEQ_WRITE(sc, DEQ_LB4, tas3004_initdata.LB4);
   1275 	DEQ_WRITE(sc, DEQ_LB5, tas3004_initdata.LB5);
   1276 	DEQ_WRITE(sc, DEQ_LB6, tas3004_initdata.LB6);
   1277 	DEQ_WRITE(sc, DEQ_RB0, tas3004_initdata.RB0);
   1278 	DEQ_WRITE(sc, DEQ_RB1, tas3004_initdata.RB1);
   1279 	DEQ_WRITE(sc, DEQ_RB1, tas3004_initdata.RB1);
   1280 	DEQ_WRITE(sc, DEQ_RB2, tas3004_initdata.RB2);
   1281 	DEQ_WRITE(sc, DEQ_RB3, tas3004_initdata.RB3);
   1282 	DEQ_WRITE(sc, DEQ_RB4, tas3004_initdata.RB4);
   1283 	DEQ_WRITE(sc, DEQ_RB5, tas3004_initdata.RB5);
   1284 	DEQ_WRITE(sc, DEQ_MCR1, tas3004_initdata.MCR1);
   1285 	DEQ_WRITE(sc, DEQ_MCR2, tas3004_initdata.MCR2);
   1286 	DEQ_WRITE(sc, DEQ_DRC, tas3004_initdata.DRC);
   1287 	DEQ_WRITE(sc, DEQ_VOLUME, tas3004_initdata.VOLUME);
   1288 	DEQ_WRITE(sc, DEQ_TREBLE, tas3004_initdata.TREBLE);
   1289 	DEQ_WRITE(sc, DEQ_BASS, tas3004_initdata.BASS);
   1290 	DEQ_WRITE(sc, DEQ_MIXER_L, tas3004_initdata.MIXER_L);
   1291 	DEQ_WRITE(sc, DEQ_MIXER_R, tas3004_initdata.MIXER_R);
   1292 	DEQ_WRITE(sc, DEQ_LLB, tas3004_initdata.LLB);
   1293 	DEQ_WRITE(sc, DEQ_RLB, tas3004_initdata.RLB);
   1294 	DEQ_WRITE(sc, DEQ_LLB_GAIN, tas3004_initdata.LLB_GAIN);
   1295 	DEQ_WRITE(sc, DEQ_RLB_GAIN, tas3004_initdata.RLB_GAIN);
   1296 	DEQ_WRITE(sc, DEQ_ACR, tas3004_initdata.ACR);
   1297 
   1298 	return 0;
   1299 err:
   1300 	printf("tas3004_init: error\n");
   1301 	return -1;
   1302 }
   1303 
   1304 /* FCR(0x3c) bits */
   1305 #define I2S0CLKEN	0x1000
   1306 #define I2S0EN		0x2000
   1307 #define I2S1CLKEN	0x080000
   1308 #define I2S1EN		0x100000
   1309 
   1310 #define FCR3C_BITMASK "\020\25I2S1EN\24I2S1CLKEN\16I2S0EN\15I2S0CLKEN"
   1311 
   1312 void
   1313 snapper_init(sc, node)
   1314 	struct snapper_softc *sc;
   1315 	int node;
   1316 {
   1317 	int gpio;
   1318 	int headphone_detect_intr = -1, headphone_detect_intrtype;
   1319 
   1320 #ifdef SNAPPER_DEBUG
   1321 	char fcr[32];
   1322 
   1323 	bitmask_snprintf(in32rb(0x8000003c), FCR3C_BITMASK, fcr, sizeof fcr);
   1324 	printf("FCR(0x3c) 0x%s\n", fcr);
   1325 #endif
   1326 
   1327 	gpio = getnodebyname(OF_parent(node), "gpio");
   1328 	DPRINTF(" /gpio 0x%x\n", gpio);
   1329 	gpio = OF_child(gpio);
   1330 	while (gpio) {
   1331 		char name[64], audio_gpio[64];
   1332 		int intr[2];
   1333 		char *addr;
   1334 
   1335 		bzero(name, sizeof name);
   1336 		bzero(audio_gpio, sizeof audio_gpio);
   1337 		addr = 0;
   1338 		OF_getprop(gpio, "name", name, sizeof name);
   1339 		OF_getprop(gpio, "audio-gpio", audio_gpio, sizeof audio_gpio);
   1340 		OF_getprop(gpio, "AAPL,address", &addr, sizeof addr);
   1341 		/* printf("0x%x %s %s\n", gpio, name, audio_gpio); */
   1342 
   1343 		/* gpio5 */
   1344 		if (strcmp(audio_gpio, "headphone-mute") == 0)
   1345 			headphone_mute = addr;
   1346 		/* gpio6 */
   1347 		if (strcmp(audio_gpio, "amp-mute") == 0)
   1348 			amp_mute = addr;
   1349 		/* extint-gpio15 */
   1350 		if (strcmp(audio_gpio, "headphone-detect") == 0) {
   1351 			headphone_detect = addr;
   1352 			OF_getprop(gpio, "audio-gpio-active-state",
   1353 			    &headphone_detect_active, 4);
   1354 			OF_getprop(gpio, "interrupts", intr, 8);
   1355 			headphone_detect_intr = intr[0];
   1356 			headphone_detect_intrtype = intr[1];
   1357 		}
   1358 		/* gpio11 (keywest-11) */
   1359 		if (strcmp(audio_gpio, "audio-hw-reset") == 0)
   1360 			audio_hw_reset = addr;
   1361 		gpio = OF_peer(gpio);
   1362 	}
   1363 	DPRINTF(" headphone-mute %p\n", headphone_mute);
   1364 	DPRINTF(" amp-mute %p\n", amp_mute);
   1365 	DPRINTF(" headphone-detect %p\n", headphone_detect);
   1366 	DPRINTF(" headphone-detect active %x\n", headphone_detect_active);
   1367 	DPRINTF(" headphone-detect intr %x\n", headphone_detect_intr);
   1368 	DPRINTF(" audio-hw-reset %p\n", audio_hw_reset);
   1369 
   1370 	if (headphone_detect_intr != -1)
   1371 		intr_establish(headphone_detect_intr, IST_EDGE, IPL_AUDIO,
   1372 		    snapper_cint, sc);
   1373 
   1374 	/* "sample-rates" (44100, 48000) */
   1375 	snapper_set_rate(sc, 44100);
   1376 
   1377 	/* Enable headphone interrupt? */
   1378 	*headphone_detect |= 0x80;
   1379 	asm volatile ("eieio");
   1380 
   1381 	/* i2c_set_port(port); */
   1382 
   1383 #if 1
   1384 	/* Enable I2C interrupts. */
   1385 #define IER 4
   1386 #define I2C_INT_DATA 0x01
   1387 #define I2C_INT_ADDR 0x02
   1388 #define I2C_INT_STOP 0x04
   1389 	ki2c_writereg(sc->sc_i2c, IER,I2C_INT_DATA|I2C_INT_ADDR|I2C_INT_STOP);
   1390 #endif
   1391 
   1392 	if (tas3004_init(sc))
   1393 		return;
   1394 
   1395 	/* Update headphone status. */
   1396 	snapper_cint(sc);
   1397 
   1398 	snapper_set_volume(sc, 80, 80);
   1399 }
   1400