davbus.c revision 187692
1/*-
2 * Copyright 2008 by Marco Trillo. All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
6 * are met:
7 * 1. Redistributions of source code must retain the above copyright
8 *    notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 *    notice, this list of conditions and the following disclaimer in the
11 *    documentation and/or other materials provided with the distribution.
12 *
13 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
14 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
15 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
16 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
17 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
18 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
19 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
20 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
21 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
22 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
23 * SUCH DAMAGE.
24 *
25 * $FreeBSD: head/sys/dev/sound/macio/davbus.c 187692 2009-01-25 18:20:15Z nwhitehorn $
26 */
27
28/*
29 *	Apple DAVbus audio controller.
30 */
31
32#include <sys/param.h>
33#include <sys/systm.h>
34#include <sys/bus.h>
35#include <sys/kernel.h>
36#include <sys/lock.h>
37#include <sys/malloc.h>
38#include <sys/module.h>
39#include <sys/mutex.h>
40#include <sys/rman.h>
41
42#include <dev/ofw/ofw_bus.h>
43#include <dev/sound/pcm/sound.h>
44#include <dev/sound/macio/aoa.h>
45#include <dev/sound/macio/davbusreg.h>
46
47#include <machine/intr_machdep.h>
48#include <machine/resource.h>
49#include <machine/bus.h>
50
51#include "mixer_if.h"
52
53struct davbus_softc {
54	struct aoa_softc 	 aoa;
55	device_t 		 dev;
56	phandle_t 		 node;
57	phandle_t 		 soundnode;
58	struct resource 	*reg;
59	struct mtx 		 mutex;
60	int 			 device_id;
61	u_int 			 output_mask;
62	u_int 			(*read_status)(struct davbus_softc *, u_int);
63	void			(*set_outputs)(struct davbus_softc *, u_int);
64};
65
66static int 	davbus_probe(device_t);
67static int 	davbus_attach(device_t);
68static void	davbus_cint(void *);
69
70static device_method_t pcm_davbus_methods[] = {
71	/* Device interface. */
72	DEVMETHOD(device_probe,		davbus_probe),
73	DEVMETHOD(device_attach, 	davbus_attach),
74
75	{ 0, 0 }
76};
77
78static driver_t pcm_davbus_driver = {
79	"pcm",
80	pcm_davbus_methods,
81	sizeof(struct davbus_softc)
82};
83
84DRIVER_MODULE(pcm_davbus, macio, pcm_davbus_driver, pcm_devclass, 0, 0);
85MODULE_DEPEND(pcm_davbus, sound, SOUND_MINVER, SOUND_PREFVER, SOUND_MAXVER);
86
87/*****************************************************************************
88			Probe and attachment routines.
89 *****************************************************************************/
90static int
91davbus_probe(device_t self)
92{
93	const char 		*name;
94	struct davbus_softc 	*sc;
95
96	name = ofw_bus_get_name(self);
97	if (!name)
98		return (ENXIO);
99
100	if (strcmp(name, "davbus") != 0)
101		return (ENXIO);
102
103	sc = device_get_softc(self);
104	if (!sc)
105		return (ENOMEM);
106	bzero(sc, sizeof(*sc));
107
108	device_set_desc(self, "Apple DAVBus Audio Controller");
109
110	return (0);
111}
112
113/*
114 * Burgundy codec control
115 */
116
117static int	burgundy_init(struct snd_mixer *m);
118static int	burgundy_uninit(struct snd_mixer *m);
119static int	burgundy_reinit(struct snd_mixer *m);
120static void 	burgundy_write_locked(struct davbus_softc *, u_int, u_int);
121static void	burgundy_set_outputs(struct davbus_softc *d, u_int mask);
122static u_int	burgundy_read_status(struct davbus_softc *d, u_int status);
123static int	burgundy_set(struct snd_mixer *m, unsigned dev, unsigned left,
124		    unsigned right);
125static int	burgundy_setrecsrc(struct snd_mixer *m, u_int32_t src);
126
127static kobj_method_t burgundy_mixer_methods[] = {
128	KOBJMETHOD(mixer_init, 		burgundy_init),
129	KOBJMETHOD(mixer_uninit, 	burgundy_uninit),
130	KOBJMETHOD(mixer_reinit, 	burgundy_reinit),
131	KOBJMETHOD(mixer_set, 		burgundy_set),
132	KOBJMETHOD(mixer_setrecsrc,	burgundy_setrecsrc),
133	{ 0, 0 }
134};
135
136MIXER_DECLARE(burgundy_mixer);
137
138static int
139burgundy_init(struct snd_mixer *m)
140{
141	struct davbus_softc *d;
142
143	d = mix_getdevinfo(m);
144
145	d->read_status = burgundy_read_status;
146	d->set_outputs = burgundy_set_outputs;
147
148	/*
149	 * We configure the Burgundy codec as follows:
150	 *
151	 * 	o Input subframe 0 is connected to input digital
152	 *	  stream A (ISA).
153	 *	o Stream A (ISA) is mixed in mixer 2 (MIX2).
154	 *	o Output of mixer 2 (MIX2) is routed to output sources
155	 *	  OS0 and OS1 which can be converted to analog.
156	 *
157	 */
158	mtx_lock(&d->mutex);
159
160	burgundy_write_locked(d, 0x16700, 0x40);
161
162	burgundy_write_locked(d, BURGUNDY_MIX0_REG, 0);
163	burgundy_write_locked(d, BURGUNDY_MIX1_REG, 0);
164	burgundy_write_locked(d, BURGUNDY_MIX2_REG, BURGUNDY_MIX_ISA);
165	burgundy_write_locked(d, BURGUNDY_MIX3_REG, 0);
166
167	burgundy_write_locked(d, BURGUNDY_OS_REG, BURGUNDY_OS0_MIX2 |
168	    BURGUNDY_OS1_MIX2);
169
170	burgundy_write_locked(d, BURGUNDY_SDIN_REG, BURGUNDY_ISA_SF0);
171
172	/* Set several digital scalers to unity gain. */
173	burgundy_write_locked(d, BURGUNDY_MXS2L_REG, BURGUNDY_MXS_UNITY);
174	burgundy_write_locked(d, BURGUNDY_MXS2R_REG, BURGUNDY_MXS_UNITY);
175	burgundy_write_locked(d, BURGUNDY_OSS0L_REG, BURGUNDY_OSS_UNITY);
176	burgundy_write_locked(d, BURGUNDY_OSS0R_REG, BURGUNDY_OSS_UNITY);
177	burgundy_write_locked(d, BURGUNDY_OSS1L_REG, BURGUNDY_OSS_UNITY);
178	burgundy_write_locked(d, BURGUNDY_OSS1R_REG, BURGUNDY_OSS_UNITY);
179	burgundy_write_locked(d, BURGUNDY_ISSAL_REG, BURGUNDY_ISS_UNITY);
180	burgundy_write_locked(d, BURGUNDY_ISSAR_REG, BURGUNDY_ISS_UNITY);
181
182	burgundy_set_outputs(d, burgundy_read_status(d,
183	    bus_read_4(d->reg, DAVBUS_CODEC_STATUS)));
184
185	mtx_unlock(&d->mutex);
186
187	mix_setdevs(m, SOUND_MASK_VOLUME);
188
189	return (0);
190}
191
192static int
193burgundy_uninit(struct snd_mixer *m)
194{
195	return (0);
196}
197
198static int
199burgundy_reinit(struct snd_mixer *m)
200{
201	return (0);
202}
203
204static void
205burgundy_write_locked(struct davbus_softc *d, u_int reg, u_int val)
206{
207	u_int size, addr, offset, data, i;
208
209	size = (reg & 0x00FF0000) >> 16;
210	addr = (reg & 0x0000FF00) >> 8;
211	offset = reg & 0xFF;
212
213	for (i = offset; i < offset + size; ++i) {
214		data = BURGUNDY_CTRL_WRITE | (addr << 12) |
215		    ((size + offset - 1) << 10) | (i << 8) | (val & 0xFF);
216		if (i == offset)
217			data |= BURGUNDY_CTRL_RESET;
218
219		bus_write_4(d->reg, DAVBUS_CODEC_CTRL, data);
220
221		while (bus_read_4(d->reg, DAVBUS_CODEC_CTRL) &
222		    DAVBUS_CODEC_BUSY)
223			DELAY(1);
224
225		val >>= 8; /* next byte. */
226	}
227}
228
229/* Must be called with d->mutex held. */
230static void
231burgundy_set_outputs(struct davbus_softc *d, u_int mask)
232{
233	u_int	x = 0;
234
235	if (mask == d->output_mask)
236		return;
237
238	/*
239	 *	Bordeaux card wirings:
240	 *		Port 15:	RCA out
241	 *		Port 16:	Minijack out
242	 *		Port 17:	Internal speaker
243	 *
244	 *	B&W G3 wirings:
245	 *		Port 14:	Minijack out
246	 *		Port 17:	Internal speaker
247	 */
248
249	DPRINTF(("Enabled outputs:"));
250	if (mask & (1 << 0)) {
251		DPRINTF((" SPEAKER"));
252		x |= BURGUNDY_P17M_EN;
253	}
254	if (mask & (1 << 1)) {
255		DPRINTF((" HEADPHONES"));
256		x |= BURGUNDY_P14L_EN | BURGUNDY_P14R_EN;
257	}
258	DPRINTF(("\n"));
259
260	burgundy_write_locked(d, BURGUNDY_MUTE_REG, x);
261	d->output_mask = mask;
262}
263
264static u_int
265burgundy_read_status(struct davbus_softc *d, u_int status)
266{
267	if (status & 0x4)
268		return (1 << 1);
269	else
270		return (1 << 0);
271}
272
273static int
274burgundy_set(struct snd_mixer *m, unsigned dev, unsigned left, unsigned right)
275{
276	struct davbus_softc *d;
277	int lval, rval;
278
279	lval = ((100 - left) * 15 / 100) & 0xf;
280	rval = ((100 - right) * 15 / 100) & 0xf;
281	DPRINTF(("volume %d %d\n", lval, rval));
282
283	d = mix_getdevinfo(m);
284
285	switch (dev) {
286	case SOUND_MIXER_VOLUME:
287		mtx_lock(&d->mutex);
288
289		burgundy_write_locked(d, BURGUNDY_OL13_REG, lval);
290		burgundy_write_locked(d, BURGUNDY_OL14_REG, (rval << 4) | lval);
291		burgundy_write_locked(d, BURGUNDY_OL15_REG, (rval << 4) | lval);
292		burgundy_write_locked(d, BURGUNDY_OL16_REG, (rval << 4) | lval);
293		burgundy_write_locked(d, BURGUNDY_OL17_REG, lval);
294
295		mtx_unlock(&d->mutex);
296
297		return (left | (right << 8));
298	}
299
300	return (0);
301}
302
303static int
304burgundy_setrecsrc(struct snd_mixer *m, u_int32_t src)
305{
306	return (0);
307}
308
309/*
310 * Screamer Codec Control
311 */
312
313static int	screamer_init(struct snd_mixer *m);
314static int	screamer_uninit(struct snd_mixer *m);
315static int	screamer_reinit(struct snd_mixer *m);
316static void 	screamer_write_locked(struct davbus_softc *, u_int, u_int);
317static void	screamer_set_outputs(struct davbus_softc *d, u_int mask);
318static u_int	screamer_read_status(struct davbus_softc *d, u_int status);
319static int	screamer_set(struct snd_mixer *m, unsigned dev, unsigned left,
320		    unsigned right);
321static int	screamer_setrecsrc(struct snd_mixer *m, u_int32_t src);
322
323static kobj_method_t screamer_mixer_methods[] = {
324	KOBJMETHOD(mixer_init, 		screamer_init),
325	KOBJMETHOD(mixer_uninit, 	screamer_uninit),
326	KOBJMETHOD(mixer_reinit, 	screamer_reinit),
327	KOBJMETHOD(mixer_set, 		screamer_set),
328	KOBJMETHOD(mixer_setrecsrc,	screamer_setrecsrc),
329	{ 0, 0 }
330};
331
332MIXER_DECLARE(screamer_mixer);
333
334static int
335screamer_init(struct snd_mixer *m)
336{
337	struct davbus_softc *d;
338
339	d = mix_getdevinfo(m);
340
341	d->read_status = screamer_read_status;
342	d->set_outputs = screamer_set_outputs;
343
344	mtx_lock(&d->mutex);
345
346	screamer_write_locked(d, SCREAMER_CODEC_ADDR0, SCREAMER_INPUT_CD |
347	    SCREAMER_DEFAULT_CD_GAIN);
348
349	screamer_set_outputs(d, screamer_read_status(d,
350	    bus_read_4(d->reg, DAVBUS_CODEC_STATUS)));
351
352	screamer_write_locked(d, SCREAMER_CODEC_ADDR2, 0);
353	screamer_write_locked(d, SCREAMER_CODEC_ADDR4, 0);
354	screamer_write_locked(d, SCREAMER_CODEC_ADDR5, 0);
355	screamer_write_locked(d, SCREAMER_CODEC_ADDR6, 0);
356
357	mtx_unlock(&d->mutex);
358
359	mix_setdevs(m, SOUND_MASK_VOLUME);
360
361	return (0);
362}
363
364static int
365screamer_uninit(struct snd_mixer *m)
366{
367	return (0);
368}
369
370static int
371screamer_reinit(struct snd_mixer *m)
372{
373	return (0);
374}
375
376
377static void
378screamer_write_locked(struct davbus_softc *d, u_int reg, u_int val)
379{
380	u_int 		x;
381
382	KASSERT(val == (val & 0xfff), ("bad val"));
383
384	while (bus_read_4(d->reg, DAVBUS_CODEC_CTRL) & DAVBUS_CODEC_BUSY)
385		DELAY(100);
386
387	x = reg;
388	x |= SCREAMER_CODEC_EMSEL0;
389	x |= val;
390	bus_write_4(d->reg, DAVBUS_CODEC_CTRL, x);
391
392	while (bus_read_4(d->reg, DAVBUS_CODEC_CTRL) & DAVBUS_CODEC_BUSY)
393		DELAY(100);
394}
395
396/* Must be called with d->mutex held. */
397static void
398screamer_set_outputs(struct davbus_softc *d, u_int mask)
399{
400	u_int 	x;
401
402	if (mask == d->output_mask) {
403		return;
404	}
405
406	x = SCREAMER_MUTE_SPEAKER | SCREAMER_MUTE_HEADPHONES;
407
408	DPRINTF(("Enabled outputs: "));
409
410	if (mask & (1 << 0)) {
411		DPRINTF(("SPEAKER "));
412		x &= ~SCREAMER_MUTE_SPEAKER;
413	}
414	if (mask & (1 << 1)) {
415		DPRINTF(("HEADPHONES "));
416		x &= ~SCREAMER_MUTE_HEADPHONES;
417	}
418
419	DPRINTF(("\n"));
420
421	if (d->device_id == 5 || d->device_id == 11) {
422		DPRINTF(("Enabling programmable output.\n"));
423		x |= SCREAMER_PROG_OUTPUT0;
424	}
425	if (d->device_id == 8 || d->device_id == 11) {
426		x &= ~SCREAMER_MUTE_SPEAKER;
427
428		if (mask & (1 << 0))
429			x |= SCREAMER_PROG_OUTPUT1; /* enable speaker. */
430	}
431
432	screamer_write_locked(d, SCREAMER_CODEC_ADDR1, x);
433	d->output_mask = mask;
434}
435
436static u_int
437screamer_read_status(struct davbus_softc *d, u_int status)
438{
439	int 	headphones;
440
441	switch (d->device_id) {
442	case 5: /* Sawtooth */
443		headphones = (status & 0x4);
444		break;
445
446	case 8:
447	case 11: /* iMac DV */
448		/* The iMac DV has 2 headphone outputs. */
449		headphones = (status & 0x7);
450		break;
451
452	default:
453		headphones = (status & 0x8);
454	}
455
456	if (headphones)
457		return (1 << 1);
458	else
459		return (1 << 0);
460}
461
462static int
463screamer_set(struct snd_mixer *m, unsigned dev, unsigned left, unsigned right)
464{
465	struct davbus_softc *d;
466	int lval, rval;
467
468	lval = ((100 - left) * 15 / 100) & 0xf;
469	rval = ((100 - right) * 15 / 100) & 0xf;
470	DPRINTF(("volume %d %d\n", lval, rval));
471
472	d = mix_getdevinfo(m);
473
474	switch (dev) {
475	case SOUND_MIXER_VOLUME:
476		mtx_lock(&d->mutex);
477		screamer_write_locked(d, SCREAMER_CODEC_ADDR2, (lval << 6) |
478		    rval);
479		screamer_write_locked(d, SCREAMER_CODEC_ADDR4, (lval << 6) |
480		    rval);
481		mtx_unlock(&d->mutex);
482
483		return (left | (right << 8));
484	}
485
486	return (0);
487}
488
489static int
490screamer_setrecsrc(struct snd_mixer *m, u_int32_t src)
491{
492	return (0);
493}
494
495static int
496davbus_attach(device_t self)
497{
498	struct davbus_softc 	*sc = device_get_softc(self);
499	struct resource 	*dbdma_irq, *cintr;
500	void 			*cookie;
501	char			 compat[64];
502	int 			 rid, oirq, err;
503
504	sc->dev = self;
505	sc->node = ofw_bus_get_node(self);
506	sc->soundnode = OF_child(sc->node);
507
508	/* Map the controller register space. */
509	rid = 0;
510	sc->reg = bus_alloc_resource_any(self, SYS_RES_MEMORY, &rid, RF_ACTIVE);
511	if (sc->reg == NULL)
512		return (ENXIO);
513
514	/* Map the DBDMA channel register space. */
515	rid = 1;
516	sc->aoa.sc_odma = bus_alloc_resource_any(self, SYS_RES_MEMORY,
517	    &rid, RF_ACTIVE);
518	if (sc->aoa.sc_odma == NULL)
519		return (ENXIO);
520
521	/* Establish the DBDMA channel edge-triggered interrupt. */
522	rid = 1;
523	dbdma_irq = bus_alloc_resource_any(self, SYS_RES_IRQ,
524	    &rid, RF_SHAREABLE | RF_ACTIVE);
525	if (dbdma_irq == NULL)
526		return (ENXIO);
527
528	oirq = rman_get_start(dbdma_irq);
529
530	DPRINTF(("interrupting at irq %d\n", oirq));
531
532	err = powerpc_config_intr(oirq, INTR_TRIGGER_EDGE, INTR_POLARITY_LOW);
533	if (err != 0)
534		return (err);
535
536	bus_setup_intr(self, dbdma_irq, INTR_TYPE_AV | INTR_MPSAFE,
537	    NULL, aoa_interrupt, sc, &cookie);
538
539	/* Now initialize the controller. */
540
541	bzero(compat, sizeof(compat));
542	OF_getprop(sc->soundnode, "compatible", compat, sizeof(compat));
543	OF_getprop(sc->soundnode, "device-id", &sc->device_id, sizeof(u_int));
544
545	mtx_init(&sc->mutex, "DAVbus", NULL, MTX_DEF);
546
547	device_printf(self, "codec: <%s>\n", compat);
548
549	/* Setup the control interrupt. */
550	rid = 0;
551	cintr = bus_alloc_resource_any(self, SYS_RES_IRQ,
552	     &rid, RF_SHAREABLE | RF_ACTIVE);
553	if (cintr != NULL)
554		bus_setup_intr(self, cintr, INTR_TYPE_MISC | INTR_MPSAFE,
555		    NULL, davbus_cint, sc, &cookie);
556
557	/* Initialize controller registers. */
558        bus_write_4(sc->reg, DAVBUS_SOUND_CTRL, DAVBUS_INPUT_SUBFRAME0 |
559	    DAVBUS_OUTPUT_SUBFRAME0 | DAVBUS_RATE_44100 | DAVBUS_INTR_PORTCHG);
560
561	/* Attach DBDMA engine and PCM layer */
562	err = aoa_attach(self);
563	if (err)
564		return (err);
565
566	/* Install codec module */
567	if (strcmp(compat, "screamer") == 0)
568		mixer_init(self, &screamer_mixer_class, sc);
569	else if (strcmp(compat, "burgundy") == 0)
570		mixer_init(self, &burgundy_mixer_class, sc);
571
572	return (0);
573}
574
575static void
576davbus_cint(void *ptr)
577{
578	struct davbus_softc *d = ptr;
579	u_int	reg, status, mask;
580
581	mtx_lock(&d->mutex);
582
583	reg = bus_read_4(d->reg, DAVBUS_SOUND_CTRL);
584	if (reg & DAVBUS_PORTCHG) {
585
586		status = bus_read_4(d->reg, DAVBUS_CODEC_STATUS);
587
588		if (d->read_status && d->set_outputs) {
589
590			mask = (*d->read_status)(d, status);
591			(*d->set_outputs)(d, mask);
592		}
593
594		/* Clear the interrupt. */
595		bus_write_4(d->reg, DAVBUS_SOUND_CTRL, reg);
596	}
597
598	mtx_unlock(&d->mutex);
599}
600
601