xref: /openbsd/sys/arch/macppc/dev/tumbler.c (revision cc5bdd41)
1 /*	$OpenBSD: tumbler.c,v 1.14 2022/10/26 20:19:07 kn Exp $	*/
2 
3 /*-
4  * Copyright (c) 2001,2003 Tsubai Masanari.  All rights reserved.
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  * 1. Redistributions of source code must retain the above copyright
10  *    notice, this list of conditions and the following disclaimer.
11  * 2. Redistributions in binary form must reproduce the above copyright
12  *    notice, this list of conditions and the following disclaimer in the
13  *    documentation and/or other materials provided with the distribution.
14  * 3. The name of the author may not be used to endorse or promote products
15  *    derived from this software without specific prior written permission.
16  *
17  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27  */
28 
29 /*
30  * Datasheet is available from
31  * http://focus.ti.com/docs/prod/folders/print/tas3001.html
32  */
33 
34 #include <sys/param.h>
35 #include <sys/audioio.h>
36 #include <sys/device.h>
37 #include <sys/systm.h>
38 
39 #include <dev/audio_if.h>
40 #include <dev/ofw/openfirm.h>
41 #include <macppc/dev/dbdma.h>
42 
43 #include <machine/autoconf.h>
44 
45 #include <macppc/dev/i2svar.h>
46 
47 #ifdef TUMBLER_DEBUG
48 # define DPRINTF printf
49 #else
50 # define DPRINTF while (0) printf
51 #endif
52 
53 /* XXX */
54 #define tumbler_softc i2s_softc
55 
56 /* XXX */
57 int kiic_write(struct device *, int, int, const void *, int);
58 int kiic_writereg(struct device *, int, u_int);
59 
60 void tumbler_init(struct tumbler_softc *);
61 int tumbler_match(struct device *, void *, void *);
62 void tumbler_attach(struct device *, struct device *, void *);
63 void tumbler_defer(struct device *);
64 void tumbler_set_volume(struct tumbler_softc *, int, int);
65 void tumbler_set_bass(struct tumbler_softc *, int);
66 void tumbler_set_treble(struct tumbler_softc *, int);
67 
68 int tas3001_write(struct tumbler_softc *, u_int, const void *);
69 int tas3001_init(struct tumbler_softc *);
70 
71 const struct cfattach tumbler_ca = {
72 	sizeof(struct tumbler_softc), tumbler_match, tumbler_attach
73 };
74 struct cfdriver tumbler_cd = {
75 	NULL, "tumbler", DV_DULL
76 };
77 
78 const struct audio_hw_if tumbler_hw_if = {
79 	.open = i2s_open,
80 	.close = i2s_close,
81 	.set_params = i2s_set_params,
82 	.round_blocksize = i2s_round_blocksize,
83 	.halt_output = i2s_halt_output,
84 	.halt_input = i2s_halt_input,
85 	.set_port = i2s_set_port,
86 	.get_port = i2s_get_port,
87 	.query_devinfo = i2s_query_devinfo,
88 	.allocm = i2s_allocm,
89 	.round_buffersize = i2s_round_buffersize,
90 	.trigger_output = i2s_trigger_output,
91 	.trigger_input = i2s_trigger_input,
92 };
93 
94 const uint8_t tumbler_trebletab[] = {
95 	0x96,	/* -18dB */
96 	0x94,	/* -17dB */
97 	0x92,	/* -16dB */
98 	0x90,	/* -15dB */
99 	0x8e,	/* -14dB */
100 	0x8c,	/* -13dB */
101 	0x8a,	/* -12dB */
102 	0x88,	/* -11dB */
103 	0x86,	/* -10dB */
104 	0x84,	/* -9dB */
105 	0x82,	/* -8dB */
106 	0x80,	/* -7dB */
107 	0x7e,	/* -6dB */
108 	0x7c,	/* -5dB */
109 	0x7a,	/* -4dB */
110 	0x78,	/* -3dB */
111 	0x76,	/* -2dB */
112 	0x74,	/* -1dB */
113 	0x72,	/* 0dB */
114 	0x70,	/* 1dB */
115 	0x6d,	/* 2dB */
116 	0x6b,	/* 3dB */
117 	0x68,	/* 4dB */
118 	0x65,	/* 5dB */
119 	0x62,	/* 6dB */
120 	0x5e,	/* 7dB */
121 	0x59,	/* 8dB */
122 	0x5a,	/* 9dB */
123 	0x4f,	/* 10dB */
124 	0x49,	/* 11dB */
125 	0x42,	/* 12dB */
126 	0x3a,	/* 13dB */
127 	0x32,	/* 14dB */
128 	0x28,	/* 15dB */
129 	0x1c,	/* 16dB */
130 	0x10,	/* 17dB */
131 	0x01,	/* 18dB */
132 };
133 
134 const uint8_t tumbler_basstab[] = {
135 	0x86,	/* -18dB */
136 	0x7f,	/* -17dB */
137 	0x7a,	/* -16dB */
138 	0x76,	/* -15dB */
139 	0x72,	/* -14dB */
140 	0x6e,	/* -13dB */
141 	0x6b,	/* -12dB */
142 	0x66,	/* -11dB */
143 	0x61,	/* -10dB */
144 	0x5d,	/* -9dB */
145 	0x5a,	/* -8dB */
146 	0x58,	/* -7dB */
147 	0x55,	/* -6dB */
148 	0x53,	/* -5dB */
149 	0x4f,	/* -4dB */
150 	0x4b,	/* -3dB */
151 	0x46,	/* -2dB */
152 	0x42,	/* -1dB */
153 	0x3e,	/* 0dB */
154 	0x3b,	/* 1dB */
155 	0x38,	/* 2dB */
156 	0x35,	/* 3dB */
157 	0x31,	/* 4dB */
158 	0x2e,	/* 5dB */
159 	0x2b,	/* 6dB */
160 	0x28,	/* 7dB */
161 	0x25,	/* 8dB */
162 	0x21,	/* 9dB */
163 	0x1c,	/* 10dB */
164 	0x18,	/* 11dB */
165 	0x16,	/* 12dB */
166 	0x13,	/* 13dB */
167 	0x10,	/* 14dB */
168 	0x0d,	/* 15dB */
169 	0x0a,	/* 16dB */
170 	0x06,	/* 17dB */
171 	0x01,	/* 18dB */
172 };
173 
174 /* TAS3001 registers */
175 #define DEQ_MCR		0x01	/* Main Control Register (1byte) */
176 #define DEQ_DRC		0x02	/* Dynamic Range Compression (2bytes) */
177 #define DEQ_VOLUME	0x04	/* Volume (6bytes) */
178 #define DEQ_TREBLE	0x05	/* Treble Control Register (1byte) */
179 #define DEQ_BASS	0x06	/* Bass Control Register (1byte) */
180 #define DEQ_MIXER1	0x07	/* Mixer 1 (3bytes) */
181 #define DEQ_MIXER2	0x08	/* Mixer 2 (3bytes) */
182 #define DEQ_LB0		0x0a	/* Left Biquad 0 (15bytes) */
183 #define DEQ_LB1		0x0b	/* Left Biquad 1 (15bytes) */
184 #define DEQ_LB2		0x0c	/* Left Biquad 2 (15bytes) */
185 #define DEQ_LB3		0x0d	/* Left Biquad 3 (15bytes) */
186 #define DEQ_LB4		0x0e	/* Left Biquad 4 (15bytes) */
187 #define DEQ_LB5		0x0f	/* Left Biquad 5 (15bytes) */
188 #define DEQ_RB0		0x13	/* Right Biquad 0 (15bytes) */
189 #define DEQ_RB1		0x14	/* Right Biquad 1 (15bytes) */
190 #define DEQ_RB2		0x15	/* Right Biquad 2 (15bytes) */
191 #define DEQ_RB3		0x16	/* Right Biquad 3 (15bytes) */
192 #define DEQ_RB4		0x17	/* Right Biquad 4 (15bytes) */
193 #define DEQ_RB5		0x18	/* Right Biquad 5 (15bytes) */
194 
195 #define DEQ_MCR_FL	0x80	/* Fast load */
196 #define DEQ_MCR_SC	0x40	/* SCLK frequency */
197 #define  DEQ_MCR_SC_32	0x00	/*  32fs */
198 #define  DEQ_MCR_SC_64	0x40	/*  64fs */
199 #define DEQ_MCR_OM	0x30	/* Output serial port mode */
200 #define  DEQ_MCR_OM_L	0x00	/*  Left justified */
201 #define  DEQ_MCR_OM_R	0x10	/*  Right justified */
202 #define  DEQ_MCR_OM_I2S	0x20	/*  I2S */
203 #define DEQ_MCR_IM	0x0c	/* Input serial port mode */
204 #define  DEQ_MCR_IM_L	0x00	/*  Left justified */
205 #define  DEQ_MCR_IM_R	0x04	/*  Right justified */
206 #define  DEQ_MCR_IM_I2S	0x08	/*  I2S */
207 #define DEQ_MCR_W	0x03	/* Serial port word length */
208 #define  DEQ_MCR_W_16	0x00	/*  16 bit */
209 #define  DEQ_MCR_W_18	0x01	/*  18 bit */
210 #define  DEQ_MCR_W_20	0x02	/*  20 bit */
211 
212 #define DEQ_DRC_CR	0xc0	/* Compression ratio */
213 #define  DEQ_DRC_CR_31	0xc0	/*  3:1 */
214 #define DEQ_DRC_EN	0x01	/* Enable DRC */
215 
216 #define DEQ_MCR_I2S	(DEQ_MCR_OM_I2S | DEQ_MCR_IM_I2S)
217 
218 struct tas3001_reg {
219 	u_char MCR[1];
220 	u_char DRC[2];
221 	u_char VOLUME[6];
222 	u_char TREBLE[1];
223 	u_char BASS[1];
224 	u_char MIXER1[3];
225 	u_char MIXER2[3];
226 	u_char LB0[15];
227 	u_char LB1[15];
228 	u_char LB2[15];
229 	u_char LB3[15];
230 	u_char LB4[15];
231 	u_char LB5[15];
232 	u_char RB0[15];
233 	u_char RB1[15];
234 	u_char RB2[15];
235 	u_char RB3[15];
236 	u_char RB4[15];
237 	u_char RB5[15];
238 };
239 
240 int
tumbler_match(struct device * parent,void * match,void * aux)241 tumbler_match(struct device *parent, void *match, void *aux)
242 {
243 	struct confargs *ca = aux;
244 	int soundbus, soundchip;
245 	char compat[32];
246 
247 	if (strcmp(ca->ca_name, "i2s") != 0)
248 		return (0);
249 
250 	if ((soundbus = OF_child(ca->ca_node)) == 0 ||
251 	    (soundchip = OF_child(soundbus)) == 0)
252 		return (0);
253 
254 	bzero(compat, sizeof compat);
255 	OF_getprop(soundchip, "compatible", compat, sizeof compat);
256 
257 	if (strcmp(compat, "tumbler") != 0)
258 		return (0);
259 
260 	return (1);
261 }
262 
263 void
tumbler_attach(struct device * parent,struct device * self,void * aux)264 tumbler_attach(struct device *parent, struct device *self, void *aux)
265 {
266 	struct tumbler_softc *sc = (struct tumbler_softc *)self;
267 
268 	sc->sc_setvolume = tumbler_set_volume;
269 	sc->sc_setbass = tumbler_set_bass;
270 	sc->sc_settreble = tumbler_set_treble;
271 
272 	i2s_attach(parent, sc, aux);
273 	config_defer(self, tumbler_defer);
274 }
275 
276 void
tumbler_defer(struct device * dev)277 tumbler_defer(struct device *dev)
278 {
279 	struct tumbler_softc *sc = (struct tumbler_softc *)dev;
280 	struct device *dv;
281 
282 	TAILQ_FOREACH(dv, &alldevs, dv_list)
283 		if (strcmp(dv->dv_cfdata->cf_driver->cd_name, "kiic") == 0 &&
284 		    strcmp(dv->dv_parent->dv_cfdata->cf_driver->cd_name, "macobio") == 0)
285 			sc->sc_i2c = dv;
286 	if (sc->sc_i2c == NULL) {
287 		printf("%s: unable to find i2c\n", sc->sc_dev.dv_xname);
288 		return;
289 	}
290 
291 	/* XXX If i2c has failed to attach, what should we do? */
292 
293 	audio_attach_mi(&tumbler_hw_if, sc, NULL, &sc->sc_dev);
294 
295 	tumbler_init(sc);
296 }
297 
298 void
tumbler_set_volume(struct tumbler_softc * sc,int left,int right)299 tumbler_set_volume(struct tumbler_softc *sc, int left, int right)
300 {
301 	u_char vol[6];
302 
303 	sc->sc_vol_l = left;
304 	sc->sc_vol_r = right;
305 
306 	left <<= 6;	/* XXX for now */
307 	right <<= 6;
308 
309 	vol[0] = left >> 16;
310 	vol[1] = left >> 8;
311 	vol[2] = left;
312 	vol[3] = right >> 16;
313 	vol[4] = right >> 8;
314 	vol[5] = right;
315 
316 	tas3001_write(sc, DEQ_VOLUME, vol);
317 }
318 
319 void
tumbler_set_treble(struct tumbler_softc * sc,int value)320 tumbler_set_treble(struct tumbler_softc *sc, int value)
321 {
322 	uint8_t reg;
323 
324 	if ((value >= 0) && (value <= 255) && (value != sc->sc_treble)) {
325 		reg = tumbler_trebletab[(value >> 3) + 2];
326 		if (tas3001_write(sc, DEQ_TREBLE, &reg) < 0)
327 			return;
328 		sc->sc_treble = value;
329 	}
330 }
331 
332 void
tumbler_set_bass(struct tumbler_softc * sc,int value)333 tumbler_set_bass(struct tumbler_softc *sc, int value)
334 {
335 	uint8_t reg;
336 
337 	if ((value >= 0) && (value <= 255) && (value != sc->sc_bass)) {
338 		reg = tumbler_basstab[(value >> 3) + 2];
339 		if (tas3001_write(sc, DEQ_BASS, &reg) < 0)
340 			return;
341 		sc->sc_bass = value;
342 	}
343 }
344 
345 const struct tas3001_reg tas3001_initdata = {
346 	{ DEQ_MCR_SC_64 | DEQ_MCR_I2S | DEQ_MCR_W_20 },		/* MCR */
347 	{ DEQ_DRC_CR_31, 0xa0 },				/* DRC */
348 	{ 0, 0, 0, 0, 0, 0 },					/* VOLUME */
349 	{ 0x72 },						/* TREBLE */
350 	{ 0x3e },						/* BASS */
351 	{ 0x10, 0x00, 0x00 },					/* MIXER1 */
352 	{ 0x00, 0x00, 0x00 },					/* MIXER2 */
353 	{ 0x10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },	/* BIQUAD */
354 	{ 0x10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },	/* BIQUAD */
355 	{ 0x10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },	/* BIQUAD */
356 	{ 0x10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },	/* BIQUAD */
357 	{ 0x10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },	/* BIQUAD */
358 	{ 0x10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },	/* BIQUAD */
359 	{ 0x10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },	/* BIQUAD */
360 	{ 0x10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },	/* BIQUAD */
361 	{ 0x10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },	/* BIQUAD */
362 	{ 0x10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },	/* BIQUAD */
363 	{ 0x10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },	/* BIQUAD */
364 	{ 0x10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },	/* BIQUAD */
365 };
366 
367 const char tas3001_regsize[] = {
368 	0,					/* 0x00 */
369 	sizeof tas3001_initdata.MCR,		/* 0x01 */
370 	sizeof tas3001_initdata.DRC,		/* 0x02 */
371 	0,					/* 0x03 */
372 	sizeof tas3001_initdata.VOLUME,		/* 0x04 */
373 	sizeof tas3001_initdata.TREBLE,		/* 0x05 */
374 	sizeof tas3001_initdata.BASS,		/* 0x06 */
375 	sizeof tas3001_initdata.MIXER1,		/* 0x07 */
376 	sizeof tas3001_initdata.MIXER2,		/* 0x08 */
377 	0,					/* 0x09 */
378 	sizeof tas3001_initdata.LB0,		/* 0x0a */
379 	sizeof tas3001_initdata.LB1,		/* 0x0b */
380 	sizeof tas3001_initdata.LB2,		/* 0x0c */
381 	sizeof tas3001_initdata.LB3,		/* 0x0d */
382 	sizeof tas3001_initdata.LB4,		/* 0x0e */
383 	sizeof tas3001_initdata.LB5,		/* 0x0f */
384 	0,					/* 0x10 */
385 	0,					/* 0x11 */
386 	0,					/* 0x12 */
387 	sizeof tas3001_initdata.RB0,		/* 0x13 */
388 	sizeof tas3001_initdata.RB1,		/* 0x14 */
389 	sizeof tas3001_initdata.RB2,		/* 0x15 */
390 	sizeof tas3001_initdata.RB3,		/* 0x16 */
391 	sizeof tas3001_initdata.RB4,		/* 0x17 */
392 	sizeof tas3001_initdata.RB5		/* 0x18 */
393 };
394 
395 #define DEQaddr 0x68
396 
397 int
tas3001_write(struct tumbler_softc * sc,u_int reg,const void * data)398 tas3001_write(struct tumbler_softc *sc, u_int reg, const void *data)
399 {
400 	int size;
401 
402 	KASSERT(reg < sizeof tas3001_regsize);
403 	size = tas3001_regsize[reg];
404 	KASSERT(size > 0);
405 
406 	if (kiic_write(sc->sc_i2c, DEQaddr, reg, data, size))
407 		return (-1);
408 
409 	return (0);
410 }
411 
412 #define DEQ_WRITE(sc, reg, addr) \
413 	if (tas3001_write(sc, reg, addr)) goto err
414 
415 int
tas3001_init(struct tumbler_softc * sc)416 tas3001_init(struct tumbler_softc *sc)
417 {
418 	deq_reset(sc);
419 
420 	/* Initialize TAS3001 registers. */
421 	DEQ_WRITE(sc, DEQ_LB0, tas3001_initdata.LB0);
422 	DEQ_WRITE(sc, DEQ_LB1, tas3001_initdata.LB1);
423 	DEQ_WRITE(sc, DEQ_LB2, tas3001_initdata.LB2);
424 	DEQ_WRITE(sc, DEQ_LB3, tas3001_initdata.LB3);
425 	DEQ_WRITE(sc, DEQ_LB4, tas3001_initdata.LB4);
426 	DEQ_WRITE(sc, DEQ_LB5, tas3001_initdata.LB5);
427 	DEQ_WRITE(sc, DEQ_RB0, tas3001_initdata.RB0);
428 	DEQ_WRITE(sc, DEQ_RB1, tas3001_initdata.RB1);
429 	DEQ_WRITE(sc, DEQ_RB1, tas3001_initdata.RB1);
430 	DEQ_WRITE(sc, DEQ_RB2, tas3001_initdata.RB2);
431 	DEQ_WRITE(sc, DEQ_RB3, tas3001_initdata.RB3);
432 	DEQ_WRITE(sc, DEQ_RB4, tas3001_initdata.RB4);
433 	DEQ_WRITE(sc, DEQ_MCR, tas3001_initdata.MCR);
434 	DEQ_WRITE(sc, DEQ_DRC, tas3001_initdata.DRC);
435 	DEQ_WRITE(sc, DEQ_VOLUME, tas3001_initdata.VOLUME);
436 	DEQ_WRITE(sc, DEQ_TREBLE, tas3001_initdata.TREBLE);
437 	DEQ_WRITE(sc, DEQ_BASS, tas3001_initdata.BASS);
438 	DEQ_WRITE(sc, DEQ_MIXER1, tas3001_initdata.MIXER1);
439 	DEQ_WRITE(sc, DEQ_MIXER2, tas3001_initdata.MIXER2);
440 
441 	return (0);
442 err:
443 	printf("%s: tas3001_init: error\n", sc->sc_dev.dv_xname);
444 	return (-1);
445 }
446 
447 void
tumbler_init(struct tumbler_softc * sc)448 tumbler_init(struct tumbler_softc *sc)
449 {
450 
451 	/* "sample-rates" (44100, 48000) */
452 	i2s_set_rate(sc, 44100);
453 
454 #if 1
455 	/* Enable I2C interrupts. */
456 #define IER 4
457 #define I2C_INT_DATA 0x01
458 #define I2C_INT_ADDR 0x02
459 #define I2C_INT_STOP 0x04
460 	kiic_writereg(sc->sc_i2c, IER,I2C_INT_DATA|I2C_INT_ADDR|I2C_INT_STOP);
461 #endif
462 
463 	if (tas3001_init(sc))
464 		return;
465 
466 	tumbler_set_volume(sc, 80, 80);
467 }
468