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, ®) < 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, ®) < 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