xref: /openbsd-src/sys/arch/macppc/dev/tumbler.c (revision cc5bdd413dc6810be27950ffc92a3e2dad4ebdcb)
1*cc5bdd41Skn /*	$OpenBSD: tumbler.c,v 1.14 2022/10/26 20:19:07 kn Exp $	*/
238b74790Sbrad 
338b74790Sbrad /*-
438b74790Sbrad  * Copyright (c) 2001,2003 Tsubai Masanari.  All rights reserved.
538b74790Sbrad  *
638b74790Sbrad  * Redistribution and use in source and binary forms, with or without
738b74790Sbrad  * modification, are permitted provided that the following conditions
838b74790Sbrad  * are met:
938b74790Sbrad  * 1. Redistributions of source code must retain the above copyright
1038b74790Sbrad  *    notice, this list of conditions and the following disclaimer.
1138b74790Sbrad  * 2. Redistributions in binary form must reproduce the above copyright
1238b74790Sbrad  *    notice, this list of conditions and the following disclaimer in the
1338b74790Sbrad  *    documentation and/or other materials provided with the distribution.
1438b74790Sbrad  * 3. The name of the author may not be used to endorse or promote products
1538b74790Sbrad  *    derived from this software without specific prior written permission.
1638b74790Sbrad  *
1738b74790Sbrad  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
1838b74790Sbrad  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
1938b74790Sbrad  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
2038b74790Sbrad  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
2138b74790Sbrad  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
2238b74790Sbrad  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
2338b74790Sbrad  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
2438b74790Sbrad  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
2538b74790Sbrad  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
2638b74790Sbrad  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
2738b74790Sbrad  */
2838b74790Sbrad 
2938b74790Sbrad /*
3038b74790Sbrad  * Datasheet is available from
3173c0f596Sbrad  * http://focus.ti.com/docs/prod/folders/print/tas3001.html
3238b74790Sbrad  */
3338b74790Sbrad 
3438b74790Sbrad #include <sys/param.h>
3538b74790Sbrad #include <sys/audioio.h>
3638b74790Sbrad #include <sys/device.h>
3738b74790Sbrad #include <sys/systm.h>
3838b74790Sbrad 
3938b74790Sbrad #include <dev/audio_if.h>
4038b74790Sbrad #include <dev/ofw/openfirm.h>
4138b74790Sbrad #include <macppc/dev/dbdma.h>
4238b74790Sbrad 
4338b74790Sbrad #include <machine/autoconf.h>
4438b74790Sbrad 
4538b74790Sbrad #include <macppc/dev/i2svar.h>
4638b74790Sbrad 
4738b74790Sbrad #ifdef TUMBLER_DEBUG
4838b74790Sbrad # define DPRINTF printf
4938b74790Sbrad #else
5038b74790Sbrad # define DPRINTF while (0) printf
5138b74790Sbrad #endif
5238b74790Sbrad 
5338b74790Sbrad /* XXX */
5438b74790Sbrad #define tumbler_softc i2s_softc
5538b74790Sbrad 
5638b74790Sbrad /* XXX */
57715b6a7bSderaadt int kiic_write(struct device *, int, int, const void *, int);
58715b6a7bSderaadt int kiic_writereg(struct device *, int, u_int);
5938b74790Sbrad 
6038b74790Sbrad void tumbler_init(struct tumbler_softc *);
6138b74790Sbrad int tumbler_match(struct device *, void *, void *);
6238b74790Sbrad void tumbler_attach(struct device *, struct device *, void *);
6338b74790Sbrad void tumbler_defer(struct device *);
6438b74790Sbrad void tumbler_set_volume(struct tumbler_softc *, int, int);
6573c0f596Sbrad void tumbler_set_bass(struct tumbler_softc *, int);
6673c0f596Sbrad void tumbler_set_treble(struct tumbler_softc *, int);
6738b74790Sbrad 
6838b74790Sbrad int tas3001_write(struct tumbler_softc *, u_int, const void *);
6938b74790Sbrad int tas3001_init(struct tumbler_softc *);
7038b74790Sbrad 
7189ed722cSmpi const struct cfattach tumbler_ca = {
7238b74790Sbrad 	sizeof(struct tumbler_softc), tumbler_match, tumbler_attach
7338b74790Sbrad };
7438b74790Sbrad struct cfdriver tumbler_cd = {
7538b74790Sbrad 	NULL, "tumbler", DV_DULL
7638b74790Sbrad };
7738b74790Sbrad 
780d6a2fdeSmiod const struct audio_hw_if tumbler_hw_if = {
795a8d990aSkn 	.open = i2s_open,
805a8d990aSkn 	.close = i2s_close,
815a8d990aSkn 	.set_params = i2s_set_params,
825a8d990aSkn 	.round_blocksize = i2s_round_blocksize,
835a8d990aSkn 	.halt_output = i2s_halt_output,
845a8d990aSkn 	.halt_input = i2s_halt_input,
855a8d990aSkn 	.set_port = i2s_set_port,
865a8d990aSkn 	.get_port = i2s_get_port,
875a8d990aSkn 	.query_devinfo = i2s_query_devinfo,
885a8d990aSkn 	.allocm = i2s_allocm,
895a8d990aSkn 	.round_buffersize = i2s_round_buffersize,
905a8d990aSkn 	.trigger_output = i2s_trigger_output,
915a8d990aSkn 	.trigger_input = i2s_trigger_input,
9238b74790Sbrad };
9338b74790Sbrad 
9473c0f596Sbrad const uint8_t tumbler_trebletab[] = {
9573c0f596Sbrad 	0x96,	/* -18dB */
9673c0f596Sbrad 	0x94,	/* -17dB */
9773c0f596Sbrad 	0x92,	/* -16dB */
9873c0f596Sbrad 	0x90,	/* -15dB */
9973c0f596Sbrad 	0x8e,	/* -14dB */
10073c0f596Sbrad 	0x8c,	/* -13dB */
10173c0f596Sbrad 	0x8a,	/* -12dB */
10273c0f596Sbrad 	0x88,	/* -11dB */
10373c0f596Sbrad 	0x86,	/* -10dB */
10473c0f596Sbrad 	0x84,	/* -9dB */
10573c0f596Sbrad 	0x82,	/* -8dB */
10673c0f596Sbrad 	0x80,	/* -7dB */
10773c0f596Sbrad 	0x7e,	/* -6dB */
10873c0f596Sbrad 	0x7c,	/* -5dB */
10973c0f596Sbrad 	0x7a,	/* -4dB */
11073c0f596Sbrad 	0x78,	/* -3dB */
11173c0f596Sbrad 	0x76,	/* -2dB */
11273c0f596Sbrad 	0x74,	/* -1dB */
11373c0f596Sbrad 	0x72,	/* 0dB */
11473c0f596Sbrad 	0x70,	/* 1dB */
11573c0f596Sbrad 	0x6d,	/* 2dB */
11673c0f596Sbrad 	0x6b,	/* 3dB */
11773c0f596Sbrad 	0x68,	/* 4dB */
11873c0f596Sbrad 	0x65,	/* 5dB */
11973c0f596Sbrad 	0x62,	/* 6dB */
12073c0f596Sbrad 	0x5e,	/* 7dB */
12173c0f596Sbrad 	0x59,	/* 8dB */
12273c0f596Sbrad 	0x5a,	/* 9dB */
12373c0f596Sbrad 	0x4f,	/* 10dB */
12473c0f596Sbrad 	0x49,	/* 11dB */
12573c0f596Sbrad 	0x42,	/* 12dB */
12673c0f596Sbrad 	0x3a,	/* 13dB */
12773c0f596Sbrad 	0x32,	/* 14dB */
12873c0f596Sbrad 	0x28,	/* 15dB */
12973c0f596Sbrad 	0x1c,	/* 16dB */
13073c0f596Sbrad 	0x10,	/* 17dB */
13173c0f596Sbrad 	0x01,	/* 18dB */
13273c0f596Sbrad };
13373c0f596Sbrad 
13473c0f596Sbrad const uint8_t tumbler_basstab[] = {
13573c0f596Sbrad 	0x86,	/* -18dB */
13673c0f596Sbrad 	0x7f,	/* -17dB */
13773c0f596Sbrad 	0x7a,	/* -16dB */
13873c0f596Sbrad 	0x76,	/* -15dB */
13973c0f596Sbrad 	0x72,	/* -14dB */
14073c0f596Sbrad 	0x6e,	/* -13dB */
14173c0f596Sbrad 	0x6b,	/* -12dB */
14273c0f596Sbrad 	0x66,	/* -11dB */
14373c0f596Sbrad 	0x61,	/* -10dB */
14473c0f596Sbrad 	0x5d,	/* -9dB */
14573c0f596Sbrad 	0x5a,	/* -8dB */
14673c0f596Sbrad 	0x58,	/* -7dB */
14773c0f596Sbrad 	0x55,	/* -6dB */
14873c0f596Sbrad 	0x53,	/* -5dB */
14973c0f596Sbrad 	0x4f,	/* -4dB */
15073c0f596Sbrad 	0x4b,	/* -3dB */
15173c0f596Sbrad 	0x46,	/* -2dB */
15273c0f596Sbrad 	0x42,	/* -1dB */
15373c0f596Sbrad 	0x3e,	/* 0dB */
15473c0f596Sbrad 	0x3b,	/* 1dB */
15573c0f596Sbrad 	0x38,	/* 2dB */
15673c0f596Sbrad 	0x35,	/* 3dB */
15773c0f596Sbrad 	0x31,	/* 4dB */
15873c0f596Sbrad 	0x2e,	/* 5dB */
15973c0f596Sbrad 	0x2b,	/* 6dB */
16073c0f596Sbrad 	0x28,	/* 7dB */
16173c0f596Sbrad 	0x25,	/* 8dB */
16273c0f596Sbrad 	0x21,	/* 9dB */
16373c0f596Sbrad 	0x1c,	/* 10dB */
16473c0f596Sbrad 	0x18,	/* 11dB */
16573c0f596Sbrad 	0x16,	/* 12dB */
16673c0f596Sbrad 	0x13,	/* 13dB */
16773c0f596Sbrad 	0x10,	/* 14dB */
16873c0f596Sbrad 	0x0d,	/* 15dB */
16973c0f596Sbrad 	0x0a,	/* 16dB */
17073c0f596Sbrad 	0x06,	/* 17dB */
17173c0f596Sbrad 	0x01,	/* 18dB */
17273c0f596Sbrad };
17373c0f596Sbrad 
17438b74790Sbrad /* TAS3001 registers */
17538b74790Sbrad #define DEQ_MCR		0x01	/* Main Control Register (1byte) */
17638b74790Sbrad #define DEQ_DRC		0x02	/* Dynamic Range Compression (2bytes) */
17738b74790Sbrad #define DEQ_VOLUME	0x04	/* Volume (6bytes) */
17838b74790Sbrad #define DEQ_TREBLE	0x05	/* Treble Control Register (1byte) */
17938b74790Sbrad #define DEQ_BASS	0x06	/* Bass Control Register (1byte) */
18038b74790Sbrad #define DEQ_MIXER1	0x07	/* Mixer 1 (3bytes) */
18138b74790Sbrad #define DEQ_MIXER2	0x08	/* Mixer 2 (3bytes) */
18238b74790Sbrad #define DEQ_LB0		0x0a	/* Left Biquad 0 (15bytes) */
18338b74790Sbrad #define DEQ_LB1		0x0b	/* Left Biquad 1 (15bytes) */
18438b74790Sbrad #define DEQ_LB2		0x0c	/* Left Biquad 2 (15bytes) */
18538b74790Sbrad #define DEQ_LB3		0x0d	/* Left Biquad 3 (15bytes) */
18638b74790Sbrad #define DEQ_LB4		0x0e	/* Left Biquad 4 (15bytes) */
18738b74790Sbrad #define DEQ_LB5		0x0f	/* Left Biquad 5 (15bytes) */
18838b74790Sbrad #define DEQ_RB0		0x13	/* Right Biquad 0 (15bytes) */
18938b74790Sbrad #define DEQ_RB1		0x14	/* Right Biquad 1 (15bytes) */
19038b74790Sbrad #define DEQ_RB2		0x15	/* Right Biquad 2 (15bytes) */
19138b74790Sbrad #define DEQ_RB3		0x16	/* Right Biquad 3 (15bytes) */
19238b74790Sbrad #define DEQ_RB4		0x17	/* Right Biquad 4 (15bytes) */
19338b74790Sbrad #define DEQ_RB5		0x18	/* Right Biquad 5 (15bytes) */
19438b74790Sbrad 
19538b74790Sbrad #define DEQ_MCR_FL	0x80	/* Fast load */
19638b74790Sbrad #define DEQ_MCR_SC	0x40	/* SCLK frequency */
19738b74790Sbrad #define  DEQ_MCR_SC_32	0x00	/*  32fs */
19838b74790Sbrad #define  DEQ_MCR_SC_64	0x40	/*  64fs */
19938b74790Sbrad #define DEQ_MCR_OM	0x30	/* Output serial port mode */
20038b74790Sbrad #define  DEQ_MCR_OM_L	0x00	/*  Left justified */
20138b74790Sbrad #define  DEQ_MCR_OM_R	0x10	/*  Right justified */
20238b74790Sbrad #define  DEQ_MCR_OM_I2S	0x20	/*  I2S */
20338b74790Sbrad #define DEQ_MCR_IM	0x0c	/* Input serial port mode */
20438b74790Sbrad #define  DEQ_MCR_IM_L	0x00	/*  Left justified */
20538b74790Sbrad #define  DEQ_MCR_IM_R	0x04	/*  Right justified */
20638b74790Sbrad #define  DEQ_MCR_IM_I2S	0x08	/*  I2S */
20738b74790Sbrad #define DEQ_MCR_W	0x03	/* Serial port word length */
20838b74790Sbrad #define  DEQ_MCR_W_16	0x00	/*  16 bit */
20938b74790Sbrad #define  DEQ_MCR_W_18	0x01	/*  18 bit */
21038b74790Sbrad #define  DEQ_MCR_W_20	0x02	/*  20 bit */
21138b74790Sbrad 
21238b74790Sbrad #define DEQ_DRC_CR	0xc0	/* Compression ratio */
21338b74790Sbrad #define  DEQ_DRC_CR_31	0xc0	/*  3:1 */
21438b74790Sbrad #define DEQ_DRC_EN	0x01	/* Enable DRC */
21538b74790Sbrad 
21638b74790Sbrad #define DEQ_MCR_I2S	(DEQ_MCR_OM_I2S | DEQ_MCR_IM_I2S)
21738b74790Sbrad 
21838b74790Sbrad struct tas3001_reg {
21938b74790Sbrad 	u_char MCR[1];
22038b74790Sbrad 	u_char DRC[2];
22138b74790Sbrad 	u_char VOLUME[6];
22238b74790Sbrad 	u_char TREBLE[1];
22338b74790Sbrad 	u_char BASS[1];
22438b74790Sbrad 	u_char MIXER1[3];
22538b74790Sbrad 	u_char MIXER2[3];
22638b74790Sbrad 	u_char LB0[15];
22738b74790Sbrad 	u_char LB1[15];
22838b74790Sbrad 	u_char LB2[15];
22938b74790Sbrad 	u_char LB3[15];
23038b74790Sbrad 	u_char LB4[15];
23138b74790Sbrad 	u_char LB5[15];
23238b74790Sbrad 	u_char RB0[15];
23338b74790Sbrad 	u_char RB1[15];
23438b74790Sbrad 	u_char RB2[15];
23538b74790Sbrad 	u_char RB3[15];
23638b74790Sbrad 	u_char RB4[15];
23738b74790Sbrad 	u_char RB5[15];
23838b74790Sbrad };
23938b74790Sbrad 
24038b74790Sbrad int
tumbler_match(struct device * parent,void * match,void * aux)24138b74790Sbrad tumbler_match(struct device *parent, void *match, void *aux)
24238b74790Sbrad {
24338b74790Sbrad 	struct confargs *ca = aux;
24438b74790Sbrad 	int soundbus, soundchip;
24538b74790Sbrad 	char compat[32];
24638b74790Sbrad 
24738b74790Sbrad 	if (strcmp(ca->ca_name, "i2s") != 0)
248ea884047Sbrad 		return (0);
24938b74790Sbrad 
25038b74790Sbrad 	if ((soundbus = OF_child(ca->ca_node)) == 0 ||
25138b74790Sbrad 	    (soundchip = OF_child(soundbus)) == 0)
252ea884047Sbrad 		return (0);
25338b74790Sbrad 
25438b74790Sbrad 	bzero(compat, sizeof compat);
25538b74790Sbrad 	OF_getprop(soundchip, "compatible", compat, sizeof compat);
25638b74790Sbrad 
25738b74790Sbrad 	if (strcmp(compat, "tumbler") != 0)
258ea884047Sbrad 		return (0);
25938b74790Sbrad 
260ea884047Sbrad 	return (1);
26138b74790Sbrad }
26238b74790Sbrad 
26338b74790Sbrad void
tumbler_attach(struct device * parent,struct device * self,void * aux)26438b74790Sbrad tumbler_attach(struct device *parent, struct device *self, void *aux)
26538b74790Sbrad {
26638b74790Sbrad 	struct tumbler_softc *sc = (struct tumbler_softc *)self;
26738b74790Sbrad 
26838b74790Sbrad 	sc->sc_setvolume = tumbler_set_volume;
26973c0f596Sbrad 	sc->sc_setbass = tumbler_set_bass;
27073c0f596Sbrad 	sc->sc_settreble = tumbler_set_treble;
27138b74790Sbrad 
27238b74790Sbrad 	i2s_attach(parent, sc, aux);
27338b74790Sbrad 	config_defer(self, tumbler_defer);
27438b74790Sbrad }
27538b74790Sbrad 
27638b74790Sbrad void
tumbler_defer(struct device * dev)27738b74790Sbrad tumbler_defer(struct device *dev)
27838b74790Sbrad {
27938b74790Sbrad 	struct tumbler_softc *sc = (struct tumbler_softc *)dev;
28038b74790Sbrad 	struct device *dv;
28138b74790Sbrad 
28238b74790Sbrad 	TAILQ_FOREACH(dv, &alldevs, dv_list)
2839f4ceda2Sderaadt 		if (strcmp(dv->dv_cfdata->cf_driver->cd_name, "kiic") == 0 &&
2849f4ceda2Sderaadt 		    strcmp(dv->dv_parent->dv_cfdata->cf_driver->cd_name, "macobio") == 0)
28538b74790Sbrad 			sc->sc_i2c = dv;
28638b74790Sbrad 	if (sc->sc_i2c == NULL) {
28738b74790Sbrad 		printf("%s: unable to find i2c\n", sc->sc_dev.dv_xname);
28838b74790Sbrad 		return;
28938b74790Sbrad 	}
29038b74790Sbrad 
29138b74790Sbrad 	/* XXX If i2c has failed to attach, what should we do? */
29238b74790Sbrad 
2932baa08e2Santon 	audio_attach_mi(&tumbler_hw_if, sc, NULL, &sc->sc_dev);
29438b74790Sbrad 
29538b74790Sbrad 	tumbler_init(sc);
29638b74790Sbrad }
29738b74790Sbrad 
29838b74790Sbrad void
tumbler_set_volume(struct tumbler_softc * sc,int left,int right)29938b74790Sbrad tumbler_set_volume(struct tumbler_softc *sc, int left, int right)
30038b74790Sbrad {
30138b74790Sbrad 	u_char vol[6];
30238b74790Sbrad 
30338b74790Sbrad 	sc->sc_vol_l = left;
30438b74790Sbrad 	sc->sc_vol_r = right;
30538b74790Sbrad 
30638b74790Sbrad 	left <<= 6;	/* XXX for now */
30738b74790Sbrad 	right <<= 6;
30838b74790Sbrad 
30938b74790Sbrad 	vol[0] = left >> 16;
31038b74790Sbrad 	vol[1] = left >> 8;
31138b74790Sbrad 	vol[2] = left;
31238b74790Sbrad 	vol[3] = right >> 16;
31338b74790Sbrad 	vol[4] = right >> 8;
31438b74790Sbrad 	vol[5] = right;
31538b74790Sbrad 
31638b74790Sbrad 	tas3001_write(sc, DEQ_VOLUME, vol);
31738b74790Sbrad }
31838b74790Sbrad 
31973c0f596Sbrad void
tumbler_set_treble(struct tumbler_softc * sc,int value)32073c0f596Sbrad tumbler_set_treble(struct tumbler_softc *sc, int value)
32173c0f596Sbrad {
32273c0f596Sbrad 	uint8_t reg;
32373c0f596Sbrad 
32473c0f596Sbrad 	if ((value >= 0) && (value <= 255) && (value != sc->sc_treble)) {
32573c0f596Sbrad 		reg = tumbler_trebletab[(value >> 3) + 2];
32673c0f596Sbrad 		if (tas3001_write(sc, DEQ_TREBLE, &reg) < 0)
32773c0f596Sbrad 			return;
32873c0f596Sbrad 		sc->sc_treble = value;
32973c0f596Sbrad 	}
33073c0f596Sbrad }
33173c0f596Sbrad 
33273c0f596Sbrad void
tumbler_set_bass(struct tumbler_softc * sc,int value)33373c0f596Sbrad tumbler_set_bass(struct tumbler_softc *sc, int value)
33473c0f596Sbrad {
33573c0f596Sbrad 	uint8_t reg;
33673c0f596Sbrad 
33773c0f596Sbrad 	if ((value >= 0) && (value <= 255) && (value != sc->sc_bass)) {
33873c0f596Sbrad 		reg = tumbler_basstab[(value >> 3) + 2];
33973c0f596Sbrad 		if (tas3001_write(sc, DEQ_BASS, &reg) < 0)
34073c0f596Sbrad 			return;
34173c0f596Sbrad 		sc->sc_bass = value;
34273c0f596Sbrad 	}
34373c0f596Sbrad }
34473c0f596Sbrad 
34538b74790Sbrad const struct tas3001_reg tas3001_initdata = {
34638b74790Sbrad 	{ DEQ_MCR_SC_64 | DEQ_MCR_I2S | DEQ_MCR_W_20 },		/* MCR */
34738b74790Sbrad 	{ DEQ_DRC_CR_31, 0xa0 },				/* DRC */
34838b74790Sbrad 	{ 0, 0, 0, 0, 0, 0 },					/* VOLUME */
34938b74790Sbrad 	{ 0x72 },						/* TREBLE */
35038b74790Sbrad 	{ 0x3e },						/* BASS */
35138b74790Sbrad 	{ 0x10, 0x00, 0x00 },					/* MIXER1 */
35238b74790Sbrad 	{ 0x00, 0x00, 0x00 },					/* MIXER2 */
35338b74790Sbrad 	{ 0x10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },	/* BIQUAD */
35438b74790Sbrad 	{ 0x10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },	/* BIQUAD */
35538b74790Sbrad 	{ 0x10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },	/* BIQUAD */
35638b74790Sbrad 	{ 0x10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },	/* BIQUAD */
35738b74790Sbrad 	{ 0x10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },	/* BIQUAD */
35838b74790Sbrad 	{ 0x10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },	/* BIQUAD */
35938b74790Sbrad 	{ 0x10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },	/* BIQUAD */
36038b74790Sbrad 	{ 0x10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },	/* BIQUAD */
36138b74790Sbrad 	{ 0x10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },	/* BIQUAD */
36238b74790Sbrad 	{ 0x10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },	/* BIQUAD */
36338b74790Sbrad 	{ 0x10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },	/* BIQUAD */
36438b74790Sbrad 	{ 0x10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },	/* BIQUAD */
36538b74790Sbrad };
36638b74790Sbrad 
36738b74790Sbrad const char tas3001_regsize[] = {
36838b74790Sbrad 	0,					/* 0x00 */
36938b74790Sbrad 	sizeof tas3001_initdata.MCR,		/* 0x01 */
37038b74790Sbrad 	sizeof tas3001_initdata.DRC,		/* 0x02 */
37138b74790Sbrad 	0,					/* 0x03 */
37238b74790Sbrad 	sizeof tas3001_initdata.VOLUME,		/* 0x04 */
37338b74790Sbrad 	sizeof tas3001_initdata.TREBLE,		/* 0x05 */
37438b74790Sbrad 	sizeof tas3001_initdata.BASS,		/* 0x06 */
37538b74790Sbrad 	sizeof tas3001_initdata.MIXER1,		/* 0x07 */
37638b74790Sbrad 	sizeof tas3001_initdata.MIXER2,		/* 0x08 */
37738b74790Sbrad 	0,					/* 0x09 */
37838b74790Sbrad 	sizeof tas3001_initdata.LB0,		/* 0x0a */
37938b74790Sbrad 	sizeof tas3001_initdata.LB1,		/* 0x0b */
38038b74790Sbrad 	sizeof tas3001_initdata.LB2,		/* 0x0c */
38138b74790Sbrad 	sizeof tas3001_initdata.LB3,		/* 0x0d */
38238b74790Sbrad 	sizeof tas3001_initdata.LB4,		/* 0x0e */
38338b74790Sbrad 	sizeof tas3001_initdata.LB5,		/* 0x0f */
38438b74790Sbrad 	0,					/* 0x10 */
38538b74790Sbrad 	0,					/* 0x11 */
38638b74790Sbrad 	0,					/* 0x12 */
38738b74790Sbrad 	sizeof tas3001_initdata.RB0,		/* 0x13 */
38838b74790Sbrad 	sizeof tas3001_initdata.RB1,		/* 0x14 */
38938b74790Sbrad 	sizeof tas3001_initdata.RB2,		/* 0x15 */
39038b74790Sbrad 	sizeof tas3001_initdata.RB3,		/* 0x16 */
39138b74790Sbrad 	sizeof tas3001_initdata.RB4,		/* 0x17 */
39238b74790Sbrad 	sizeof tas3001_initdata.RB5		/* 0x18 */
39338b74790Sbrad };
39438b74790Sbrad 
39538b74790Sbrad #define DEQaddr 0x68
39638b74790Sbrad 
39738b74790Sbrad int
tas3001_write(struct tumbler_softc * sc,u_int reg,const void * data)39838b74790Sbrad tas3001_write(struct tumbler_softc *sc, u_int reg, const void *data)
39938b74790Sbrad {
40038b74790Sbrad 	int size;
40138b74790Sbrad 
40238b74790Sbrad 	KASSERT(reg < sizeof tas3001_regsize);
40338b74790Sbrad 	size = tas3001_regsize[reg];
40438b74790Sbrad 	KASSERT(size > 0);
40538b74790Sbrad 
406715b6a7bSderaadt 	if (kiic_write(sc->sc_i2c, DEQaddr, reg, data, size))
407ea884047Sbrad 		return (-1);
40838b74790Sbrad 
409ea884047Sbrad 	return (0);
41038b74790Sbrad }
41138b74790Sbrad 
41238b74790Sbrad #define DEQ_WRITE(sc, reg, addr) \
41338b74790Sbrad 	if (tas3001_write(sc, reg, addr)) goto err
41438b74790Sbrad 
41538b74790Sbrad int
tas3001_init(struct tumbler_softc * sc)41638b74790Sbrad tas3001_init(struct tumbler_softc *sc)
41738b74790Sbrad {
41838b74790Sbrad 	deq_reset(sc);
41938b74790Sbrad 
42038b74790Sbrad 	/* Initialize TAS3001 registers. */
42138b74790Sbrad 	DEQ_WRITE(sc, DEQ_LB0, tas3001_initdata.LB0);
42238b74790Sbrad 	DEQ_WRITE(sc, DEQ_LB1, tas3001_initdata.LB1);
42338b74790Sbrad 	DEQ_WRITE(sc, DEQ_LB2, tas3001_initdata.LB2);
42438b74790Sbrad 	DEQ_WRITE(sc, DEQ_LB3, tas3001_initdata.LB3);
42538b74790Sbrad 	DEQ_WRITE(sc, DEQ_LB4, tas3001_initdata.LB4);
42638b74790Sbrad 	DEQ_WRITE(sc, DEQ_LB5, tas3001_initdata.LB5);
42738b74790Sbrad 	DEQ_WRITE(sc, DEQ_RB0, tas3001_initdata.RB0);
42838b74790Sbrad 	DEQ_WRITE(sc, DEQ_RB1, tas3001_initdata.RB1);
42938b74790Sbrad 	DEQ_WRITE(sc, DEQ_RB1, tas3001_initdata.RB1);
43038b74790Sbrad 	DEQ_WRITE(sc, DEQ_RB2, tas3001_initdata.RB2);
43138b74790Sbrad 	DEQ_WRITE(sc, DEQ_RB3, tas3001_initdata.RB3);
43238b74790Sbrad 	DEQ_WRITE(sc, DEQ_RB4, tas3001_initdata.RB4);
43338b74790Sbrad 	DEQ_WRITE(sc, DEQ_MCR, tas3001_initdata.MCR);
43438b74790Sbrad 	DEQ_WRITE(sc, DEQ_DRC, tas3001_initdata.DRC);
43538b74790Sbrad 	DEQ_WRITE(sc, DEQ_VOLUME, tas3001_initdata.VOLUME);
43638b74790Sbrad 	DEQ_WRITE(sc, DEQ_TREBLE, tas3001_initdata.TREBLE);
43738b74790Sbrad 	DEQ_WRITE(sc, DEQ_BASS, tas3001_initdata.BASS);
43838b74790Sbrad 	DEQ_WRITE(sc, DEQ_MIXER1, tas3001_initdata.MIXER1);
43938b74790Sbrad 	DEQ_WRITE(sc, DEQ_MIXER2, tas3001_initdata.MIXER2);
44038b74790Sbrad 
441ea884047Sbrad 	return (0);
44238b74790Sbrad err:
44338b74790Sbrad 	printf("%s: tas3001_init: error\n", sc->sc_dev.dv_xname);
444ea884047Sbrad 	return (-1);
44538b74790Sbrad }
44638b74790Sbrad 
44738b74790Sbrad void
tumbler_init(struct tumbler_softc * sc)44838b74790Sbrad tumbler_init(struct tumbler_softc *sc)
44938b74790Sbrad {
45038b74790Sbrad 
45138b74790Sbrad 	/* "sample-rates" (44100, 48000) */
45238b74790Sbrad 	i2s_set_rate(sc, 44100);
45338b74790Sbrad 
45438b74790Sbrad #if 1
45538b74790Sbrad 	/* Enable I2C interrupts. */
45638b74790Sbrad #define IER 4
45738b74790Sbrad #define I2C_INT_DATA 0x01
45838b74790Sbrad #define I2C_INT_ADDR 0x02
45938b74790Sbrad #define I2C_INT_STOP 0x04
460715b6a7bSderaadt 	kiic_writereg(sc->sc_i2c, IER,I2C_INT_DATA|I2C_INT_ADDR|I2C_INT_STOP);
46138b74790Sbrad #endif
46238b74790Sbrad 
46338b74790Sbrad 	if (tas3001_init(sc))
46438b74790Sbrad 		return;
46538b74790Sbrad 
46638b74790Sbrad 	tumbler_set_volume(sc, 80, 80);
46738b74790Sbrad }
468