xref: /openbsd/sys/arch/macppc/dev/tumbler.c (revision 17df1aa7)
1 /*	$OpenBSD: tumbler.c,v 1.7 2009/10/26 20:17:27 deraadt 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_getdev(void *, struct audio_device *);
62 int tumbler_match(struct device *, void *, void *);
63 void tumbler_attach(struct device *, struct device *, void *);
64 void tumbler_defer(struct device *);
65 void tumbler_set_volume(struct tumbler_softc *, int, int);
66 void tumbler_set_bass(struct tumbler_softc *, int);
67 void tumbler_set_treble(struct tumbler_softc *, int);
68 void tumbler_get_default_params(void *, int, struct audio_params *);
69 
70 int tas3001_write(struct tumbler_softc *, u_int, const void *);
71 int tas3001_init(struct tumbler_softc *);
72 
73 struct cfattach tumbler_ca = {
74 	sizeof(struct tumbler_softc), tumbler_match, tumbler_attach
75 };
76 struct cfdriver tumbler_cd = {
77 	NULL, "tumbler", DV_DULL
78 };
79 
80 struct audio_hw_if tumbler_hw_if = {
81 	i2s_open,
82 	i2s_close,
83 	NULL,
84 	i2s_query_encoding,
85 	i2s_set_params,
86 	i2s_round_blocksize,
87 	NULL,
88 	NULL,
89 	NULL,
90 	NULL,
91 	NULL,
92 	i2s_halt_output,
93 	i2s_halt_input,
94 	NULL,
95 	tumbler_getdev,
96 	NULL,
97 	i2s_set_port,
98 	i2s_get_port,
99 	i2s_query_devinfo,
100 	i2s_allocm,		/* allocm */
101 	NULL,
102 	i2s_round_buffersize,
103 	i2s_mappage,
104 	i2s_get_props,
105 	i2s_trigger_output,
106 	i2s_trigger_input,
107 	tumbler_get_default_params
108 };
109 
110 struct audio_device tumbler_device = {
111 	"TUMBLER",
112 	"",
113 	"tumbler"
114 };
115 
116 const uint8_t tumbler_trebletab[] = {
117 	0x96,	/* -18dB */
118 	0x94,	/* -17dB */
119 	0x92,	/* -16dB */
120 	0x90,	/* -15dB */
121 	0x8e,	/* -14dB */
122 	0x8c,	/* -13dB */
123 	0x8a,	/* -12dB */
124 	0x88,	/* -11dB */
125 	0x86,	/* -10dB */
126 	0x84,	/* -9dB */
127 	0x82,	/* -8dB */
128 	0x80,	/* -7dB */
129 	0x7e,	/* -6dB */
130 	0x7c,	/* -5dB */
131 	0x7a,	/* -4dB */
132 	0x78,	/* -3dB */
133 	0x76,	/* -2dB */
134 	0x74,	/* -1dB */
135 	0x72,	/* 0dB */
136 	0x70,	/* 1dB */
137 	0x6d,	/* 2dB */
138 	0x6b,	/* 3dB */
139 	0x68,	/* 4dB */
140 	0x65,	/* 5dB */
141 	0x62,	/* 6dB */
142 	0x5e,	/* 7dB */
143 	0x59,	/* 8dB */
144 	0x5a,	/* 9dB */
145 	0x4f,	/* 10dB */
146 	0x49,	/* 11dB */
147 	0x42,	/* 12dB */
148 	0x3a,	/* 13dB */
149 	0x32,	/* 14dB */
150 	0x28,	/* 15dB */
151 	0x1c,	/* 16dB */
152 	0x10,	/* 17dB */
153 	0x01,	/* 18dB */
154 };
155 
156 const uint8_t tumbler_basstab[] = {
157 	0x86,	/* -18dB */
158 	0x7f,	/* -17dB */
159 	0x7a,	/* -16dB */
160 	0x76,	/* -15dB */
161 	0x72,	/* -14dB */
162 	0x6e,	/* -13dB */
163 	0x6b,	/* -12dB */
164 	0x66,	/* -11dB */
165 	0x61,	/* -10dB */
166 	0x5d,	/* -9dB */
167 	0x5a,	/* -8dB */
168 	0x58,	/* -7dB */
169 	0x55,	/* -6dB */
170 	0x53,	/* -5dB */
171 	0x4f,	/* -4dB */
172 	0x4b,	/* -3dB */
173 	0x46,	/* -2dB */
174 	0x42,	/* -1dB */
175 	0x3e,	/* 0dB */
176 	0x3b,	/* 1dB */
177 	0x38,	/* 2dB */
178 	0x35,	/* 3dB */
179 	0x31,	/* 4dB */
180 	0x2e,	/* 5dB */
181 	0x2b,	/* 6dB */
182 	0x28,	/* 7dB */
183 	0x25,	/* 8dB */
184 	0x21,	/* 9dB */
185 	0x1c,	/* 10dB */
186 	0x18,	/* 11dB */
187 	0x16,	/* 12dB */
188 	0x13,	/* 13dB */
189 	0x10,	/* 14dB */
190 	0x0d,	/* 15dB */
191 	0x0a,	/* 16dB */
192 	0x06,	/* 17dB */
193 	0x01,	/* 18dB */
194 };
195 
196 /* TAS3001 registers */
197 #define DEQ_MCR		0x01	/* Main Control Register (1byte) */
198 #define DEQ_DRC		0x02	/* Dynamic Range Compression (2bytes) */
199 #define DEQ_VOLUME	0x04	/* Volume (6bytes) */
200 #define DEQ_TREBLE	0x05	/* Treble Control Register (1byte) */
201 #define DEQ_BASS	0x06	/* Bass Control Register (1byte) */
202 #define DEQ_MIXER1	0x07	/* Mixer 1 (3bytes) */
203 #define DEQ_MIXER2	0x08	/* Mixer 2 (3bytes) */
204 #define DEQ_LB0		0x0a	/* Left Biquad 0 (15bytes) */
205 #define DEQ_LB1		0x0b	/* Left Biquad 1 (15bytes) */
206 #define DEQ_LB2		0x0c	/* Left Biquad 2 (15bytes) */
207 #define DEQ_LB3		0x0d	/* Left Biquad 3 (15bytes) */
208 #define DEQ_LB4		0x0e	/* Left Biquad 4 (15bytes) */
209 #define DEQ_LB5		0x0f	/* Left Biquad 5 (15bytes) */
210 #define DEQ_RB0		0x13	/* Right Biquad 0 (15bytes) */
211 #define DEQ_RB1		0x14	/* Right Biquad 1 (15bytes) */
212 #define DEQ_RB2		0x15	/* Right Biquad 2 (15bytes) */
213 #define DEQ_RB3		0x16	/* Right Biquad 3 (15bytes) */
214 #define DEQ_RB4		0x17	/* Right Biquad 4 (15bytes) */
215 #define DEQ_RB5		0x18	/* Right Biquad 5 (15bytes) */
216 
217 #define DEQ_MCR_FL	0x80	/* Fast load */
218 #define DEQ_MCR_SC	0x40	/* SCLK frequency */
219 #define  DEQ_MCR_SC_32	0x00	/*  32fs */
220 #define  DEQ_MCR_SC_64	0x40	/*  64fs */
221 #define DEQ_MCR_OM	0x30	/* Output serial port mode */
222 #define  DEQ_MCR_OM_L	0x00	/*  Left justified */
223 #define  DEQ_MCR_OM_R	0x10	/*  Right justified */
224 #define  DEQ_MCR_OM_I2S	0x20	/*  I2S */
225 #define DEQ_MCR_IM	0x0c	/* Input serial port mode */
226 #define  DEQ_MCR_IM_L	0x00	/*  Left justified */
227 #define  DEQ_MCR_IM_R	0x04	/*  Right justified */
228 #define  DEQ_MCR_IM_I2S	0x08	/*  I2S */
229 #define DEQ_MCR_W	0x03	/* Serial port word length */
230 #define  DEQ_MCR_W_16	0x00	/*  16 bit */
231 #define  DEQ_MCR_W_18	0x01	/*  18 bit */
232 #define  DEQ_MCR_W_20	0x02	/*  20 bit */
233 
234 #define DEQ_DRC_CR	0xc0	/* Compression ratio */
235 #define  DEQ_DRC_CR_31	0xc0	/*  3:1 */
236 #define DEQ_DRC_EN	0x01	/* Enable DRC */
237 
238 #define DEQ_MCR_I2S	(DEQ_MCR_OM_I2S | DEQ_MCR_IM_I2S)
239 
240 struct tas3001_reg {
241 	u_char MCR[1];
242 	u_char DRC[2];
243 	u_char VOLUME[6];
244 	u_char TREBLE[1];
245 	u_char BASS[1];
246 	u_char MIXER1[3];
247 	u_char MIXER2[3];
248 	u_char LB0[15];
249 	u_char LB1[15];
250 	u_char LB2[15];
251 	u_char LB3[15];
252 	u_char LB4[15];
253 	u_char LB5[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 };
261 
262 int
263 tumbler_match(struct device *parent, void *match, void *aux)
264 {
265 	struct confargs *ca = aux;
266 	int soundbus, soundchip;
267 	char compat[32];
268 
269 	if (strcmp(ca->ca_name, "i2s") != 0)
270 		return (0);
271 
272 	if ((soundbus = OF_child(ca->ca_node)) == 0 ||
273 	    (soundchip = OF_child(soundbus)) == 0)
274 		return (0);
275 
276 	bzero(compat, sizeof compat);
277 	OF_getprop(soundchip, "compatible", compat, sizeof compat);
278 
279 	if (strcmp(compat, "tumbler") != 0)
280 		return (0);
281 
282 	return (1);
283 }
284 
285 void
286 tumbler_attach(struct device *parent, struct device *self, void *aux)
287 {
288 	struct tumbler_softc *sc = (struct tumbler_softc *)self;
289 
290 	sc->sc_setvolume = tumbler_set_volume;
291 	sc->sc_setbass = tumbler_set_bass;
292 	sc->sc_settreble = tumbler_set_treble;
293 
294 	i2s_attach(parent, sc, aux);
295 	config_defer(self, tumbler_defer);
296 }
297 
298 void
299 tumbler_defer(struct device *dev)
300 {
301 	struct tumbler_softc *sc = (struct tumbler_softc *)dev;
302 	struct device *dv;
303 
304 	TAILQ_FOREACH(dv, &alldevs, dv_list)
305 		if (strcmp(dv->dv_cfdata->cf_driver->cd_name, "kiic") == 0 &&
306 		    strcmp(dv->dv_parent->dv_cfdata->cf_driver->cd_name, "macobio") == 0)
307 			sc->sc_i2c = dv;
308 	if (sc->sc_i2c == NULL) {
309 		printf("%s: unable to find i2c\n", sc->sc_dev.dv_xname);
310 		return;
311 	}
312 
313 	/* XXX If i2c has failed to attach, what should we do? */
314 
315 	audio_attach_mi(&tumbler_hw_if, sc, &sc->sc_dev);
316 
317 	tumbler_init(sc);
318 }
319 
320 void
321 tumbler_set_volume(struct tumbler_softc *sc, int left, int right)
322 {
323 	u_char vol[6];
324 
325 	sc->sc_vol_l = left;
326 	sc->sc_vol_r = right;
327 
328 	left <<= 6;	/* XXX for now */
329 	right <<= 6;
330 
331 	vol[0] = left >> 16;
332 	vol[1] = left >> 8;
333 	vol[2] = left;
334 	vol[3] = right >> 16;
335 	vol[4] = right >> 8;
336 	vol[5] = right;
337 
338 	tas3001_write(sc, DEQ_VOLUME, vol);
339 }
340 
341 void
342 tumbler_set_treble(struct tumbler_softc *sc, int value)
343 {
344 	uint8_t reg;
345 
346 	if ((value >= 0) && (value <= 255) && (value != sc->sc_treble)) {
347 		reg = tumbler_trebletab[(value >> 3) + 2];
348 		if (tas3001_write(sc, DEQ_TREBLE, &reg) < 0)
349 			return;
350 		sc->sc_treble = value;
351 	}
352 }
353 
354 void
355 tumbler_set_bass(struct tumbler_softc *sc, int value)
356 {
357 	uint8_t reg;
358 
359 	if ((value >= 0) && (value <= 255) && (value != sc->sc_bass)) {
360 		reg = tumbler_basstab[(value >> 3) + 2];
361 		if (tas3001_write(sc, DEQ_BASS, &reg) < 0)
362 			return;
363 		sc->sc_bass = value;
364 	}
365 }
366 
367 const struct tas3001_reg tas3001_initdata = {
368 	{ DEQ_MCR_SC_64 | DEQ_MCR_I2S | DEQ_MCR_W_20 },		/* MCR */
369 	{ DEQ_DRC_CR_31, 0xa0 },				/* DRC */
370 	{ 0, 0, 0, 0, 0, 0 },					/* VOLUME */
371 	{ 0x72 },						/* TREBLE */
372 	{ 0x3e },						/* BASS */
373 	{ 0x10, 0x00, 0x00 },					/* MIXER1 */
374 	{ 0x00, 0x00, 0x00 },					/* MIXER2 */
375 	{ 0x10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },	/* BIQUAD */
376 	{ 0x10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },	/* BIQUAD */
377 	{ 0x10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },	/* BIQUAD */
378 	{ 0x10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },	/* BIQUAD */
379 	{ 0x10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },	/* BIQUAD */
380 	{ 0x10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },	/* BIQUAD */
381 	{ 0x10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },	/* BIQUAD */
382 	{ 0x10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },	/* BIQUAD */
383 	{ 0x10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },	/* BIQUAD */
384 	{ 0x10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },	/* BIQUAD */
385 	{ 0x10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },	/* BIQUAD */
386 	{ 0x10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },	/* BIQUAD */
387 };
388 
389 const char tas3001_regsize[] = {
390 	0,					/* 0x00 */
391 	sizeof tas3001_initdata.MCR,		/* 0x01 */
392 	sizeof tas3001_initdata.DRC,		/* 0x02 */
393 	0,					/* 0x03 */
394 	sizeof tas3001_initdata.VOLUME,		/* 0x04 */
395 	sizeof tas3001_initdata.TREBLE,		/* 0x05 */
396 	sizeof tas3001_initdata.BASS,		/* 0x06 */
397 	sizeof tas3001_initdata.MIXER1,		/* 0x07 */
398 	sizeof tas3001_initdata.MIXER2,		/* 0x08 */
399 	0,					/* 0x09 */
400 	sizeof tas3001_initdata.LB0,		/* 0x0a */
401 	sizeof tas3001_initdata.LB1,		/* 0x0b */
402 	sizeof tas3001_initdata.LB2,		/* 0x0c */
403 	sizeof tas3001_initdata.LB3,		/* 0x0d */
404 	sizeof tas3001_initdata.LB4,		/* 0x0e */
405 	sizeof tas3001_initdata.LB5,		/* 0x0f */
406 	0,					/* 0x10 */
407 	0,					/* 0x11 */
408 	0,					/* 0x12 */
409 	sizeof tas3001_initdata.RB0,		/* 0x13 */
410 	sizeof tas3001_initdata.RB1,		/* 0x14 */
411 	sizeof tas3001_initdata.RB2,		/* 0x15 */
412 	sizeof tas3001_initdata.RB3,		/* 0x16 */
413 	sizeof tas3001_initdata.RB4,		/* 0x17 */
414 	sizeof tas3001_initdata.RB5		/* 0x18 */
415 };
416 
417 #define DEQaddr 0x68
418 
419 int
420 tas3001_write(struct tumbler_softc *sc, u_int reg, const void *data)
421 {
422 	int size;
423 
424 	KASSERT(reg < sizeof tas3001_regsize);
425 	size = tas3001_regsize[reg];
426 	KASSERT(size > 0);
427 
428 	if (kiic_write(sc->sc_i2c, DEQaddr, reg, data, size))
429 		return (-1);
430 
431 	return (0);
432 }
433 
434 #define DEQ_WRITE(sc, reg, addr) \
435 	if (tas3001_write(sc, reg, addr)) goto err
436 
437 int
438 tas3001_init(struct tumbler_softc *sc)
439 {
440 	deq_reset(sc);
441 
442 	/* Initialize TAS3001 registers. */
443 	DEQ_WRITE(sc, DEQ_LB0, tas3001_initdata.LB0);
444 	DEQ_WRITE(sc, DEQ_LB1, tas3001_initdata.LB1);
445 	DEQ_WRITE(sc, DEQ_LB2, tas3001_initdata.LB2);
446 	DEQ_WRITE(sc, DEQ_LB3, tas3001_initdata.LB3);
447 	DEQ_WRITE(sc, DEQ_LB4, tas3001_initdata.LB4);
448 	DEQ_WRITE(sc, DEQ_LB5, tas3001_initdata.LB5);
449 	DEQ_WRITE(sc, DEQ_RB0, tas3001_initdata.RB0);
450 	DEQ_WRITE(sc, DEQ_RB1, tas3001_initdata.RB1);
451 	DEQ_WRITE(sc, DEQ_RB1, tas3001_initdata.RB1);
452 	DEQ_WRITE(sc, DEQ_RB2, tas3001_initdata.RB2);
453 	DEQ_WRITE(sc, DEQ_RB3, tas3001_initdata.RB3);
454 	DEQ_WRITE(sc, DEQ_RB4, tas3001_initdata.RB4);
455 	DEQ_WRITE(sc, DEQ_MCR, tas3001_initdata.MCR);
456 	DEQ_WRITE(sc, DEQ_DRC, tas3001_initdata.DRC);
457 	DEQ_WRITE(sc, DEQ_VOLUME, tas3001_initdata.VOLUME);
458 	DEQ_WRITE(sc, DEQ_TREBLE, tas3001_initdata.TREBLE);
459 	DEQ_WRITE(sc, DEQ_BASS, tas3001_initdata.BASS);
460 	DEQ_WRITE(sc, DEQ_MIXER1, tas3001_initdata.MIXER1);
461 	DEQ_WRITE(sc, DEQ_MIXER2, tas3001_initdata.MIXER2);
462 
463 	return (0);
464 err:
465 	printf("%s: tas3001_init: error\n", sc->sc_dev.dv_xname);
466 	return (-1);
467 }
468 
469 void
470 tumbler_init(struct tumbler_softc *sc)
471 {
472 
473 	/* "sample-rates" (44100, 48000) */
474 	i2s_set_rate(sc, 44100);
475 
476 #if 1
477 	/* Enable I2C interrupts. */
478 #define IER 4
479 #define I2C_INT_DATA 0x01
480 #define I2C_INT_ADDR 0x02
481 #define I2C_INT_STOP 0x04
482 	kiic_writereg(sc->sc_i2c, IER,I2C_INT_DATA|I2C_INT_ADDR|I2C_INT_STOP);
483 #endif
484 
485 	if (tas3001_init(sc))
486 		return;
487 
488 	tumbler_set_volume(sc, 80, 80);
489 }
490 
491 int
492 tumbler_getdev(void *h, struct audio_device *retp)
493 {
494 	*retp = tumbler_device;
495 	return (0);
496 }
497 
498 void
499 tumbler_get_default_params(void *addr, int mode, struct audio_params *params)
500 {
501 	i2s_get_default_params(params);
502 }
503