svn commit: r187692 - in head: share/man/man4/man4.powerpc sys/conf sys/dev/sound/macio sys/modules/sound/driver sys/modules/sound/driver/ai2s sys/modules/sound/driver/davbus sys/powerpc/conf

Nathan Whitehorn nwhitehorn at FreeBSD.org
Sun Jan 25 10:20:16 PST 2009


Author: nwhitehorn
Date: Sun Jan 25 18:20:15 2009
New Revision: 187692
URL: http://svn.freebsd.org/changeset/base/187692

Log:
  Add support for the I2S and davbus audio controllers found in Apple PowerPC
  hardware.
  
  Submitted by:	Marco Trillo

Added:
  head/share/man/man4/man4.powerpc/snd_ai2s.4   (contents, props changed)
  head/share/man/man4/man4.powerpc/snd_davbus.4   (contents, props changed)
  head/sys/dev/sound/macio/
  head/sys/dev/sound/macio/aoa.c   (contents, props changed)
  head/sys/dev/sound/macio/aoa.h   (contents, props changed)
  head/sys/dev/sound/macio/davbus.c   (contents, props changed)
  head/sys/dev/sound/macio/davbusreg.h   (contents, props changed)
  head/sys/dev/sound/macio/i2s.c   (contents, props changed)
  head/sys/dev/sound/macio/snapper.c   (contents, props changed)
  head/sys/dev/sound/macio/tumbler.c   (contents, props changed)
  head/sys/modules/sound/driver/ai2s/
  head/sys/modules/sound/driver/ai2s/Makefile   (contents, props changed)
  head/sys/modules/sound/driver/davbus/
  head/sys/modules/sound/driver/davbus/Makefile   (contents, props changed)
Modified:
  head/share/man/man4/man4.powerpc/Makefile
  head/sys/conf/files.powerpc
  head/sys/modules/sound/driver/Makefile
  head/sys/powerpc/conf/GENERIC
  head/sys/powerpc/conf/NOTES

Modified: head/share/man/man4/man4.powerpc/Makefile
==============================================================================
--- head/share/man/man4/man4.powerpc/Makefile	Sun Jan 25 17:50:53 2009	(r187691)
+++ head/share/man/man4/man4.powerpc/Makefile	Sun Jan 25 18:20:15 2009	(r187692)
@@ -2,7 +2,9 @@
 
 MAN=	bm.4 \
 	pmu.4 \
-	powermac_nvram.4
+	powermac_nvram.4 \
+	snd_ai2s.4 \
+	snd_davbus
 
 MANSUBDIR=/powerpc
 

Added: head/share/man/man4/man4.powerpc/snd_ai2s.4
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ head/share/man/man4/man4.powerpc/snd_ai2s.4	Sun Jan 25 18:20:15 2009	(r187692)
@@ -0,0 +1,90 @@
+.\"-
+.\" Copyright (c) 2009 Nathan Whitehorn <nwhitehorn at FreeBSD.org>
+.\" All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\"    notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\"    notice, this list of conditions and the following disclaimer in the
+.\"    documentation and/or other materials provided with the distribution.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+.\" IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+.\" WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+.\" DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
+.\" INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+.\" (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+.\" SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+.\" STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+.\" ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+.\" POSSIBILITY OF SUCH DAMAGE.
+.\"
+.\" $FreeBSD$
+.\"
+.Dd January 20, 2009
+.Dt SND_AI2S 4
+.Os
+.Sh NAME
+.Nm snd_ai2s
+.Nd "Apple I2S audio device driver"
+.Sh SYNOPSIS
+To compile this driver into the kernel,
+place the following lines in your
+kernel configuration file:
+.Bd -ragged -offset indent
+.Cd "device sound"
+.Cd "device snd_ai2s"
+.Ed
+.Pp
+Alternatively, to load the driver as a
+module at boot time, place the following line in
+.Xr loader.conf 5 :
+.Bd -literal -offset indent
+snd_ai2s_load="YES"
+.Ed
+.Sh DESCRIPTION
+The
+.Nm
+driver provides support for the Apple I2S audio controllers found 
+predominantly in G4 and G5 machines, along with the snapper and tumbler
+codecs. Some machines (e.g. the Mac Mini) do not have configurable
+codecs and so lack hardware volume control.
+.Sh HARDWARE
+.Pp
+Chips supported by the
+.Nm
+driver include:
+.Pp
+.Bl -bullet -compact
+.It
+Apple Tumbler Audio
+.It
+Apple Snapper Audio
+.El
+.Pp
+.Sh BUGS
+Recording and operation with non-44.1 Khz audio are not currently supported.
+.Sh SEE ALSO
+.Xr sound 4 ,
+.Xr snd_davbus 4
+.Sh HISTORY
+The
+.Nm
+device driver appeared in
+.Nx 2.0
+and then in
+.Fx 8.0 .
+.Sh AUTHORS
+.An -nosplit
+The
+.Nm
+driver was written by
+.An Tsubai Masanari
+.Aq tsubai at netbsd.org ,
+and ported to FreeBSD by
+.An Marco Trillo
+.Aq marcotrillo at gmail.com .

Added: head/share/man/man4/man4.powerpc/snd_davbus.4
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ head/share/man/man4/man4.powerpc/snd_davbus.4	Sun Jan 25 18:20:15 2009	(r187692)
@@ -0,0 +1,83 @@
+.\"-
+.\" Copyright (c) 2009 Nathan Whitehorn <nwhitehorn at FreeBSD.org>
+.\" All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\"    notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\"    notice, this list of conditions and the following disclaimer in the
+.\"    documentation and/or other materials provided with the distribution.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+.\" IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+.\" WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+.\" DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
+.\" INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+.\" (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+.\" SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+.\" STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+.\" ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+.\" POSSIBILITY OF SUCH DAMAGE.
+.\"
+.\" $FreeBSD$
+.\"
+.Dd January 20, 2009
+.Dt SND_DAVBUS 4
+.Os
+.Sh NAME
+.Nm snd_davbus
+.Nd "Apple Davbus audio device driver"
+.Sh SYNOPSIS
+To compile this driver into the kernel,
+place the following lines in your
+kernel configuration file:
+.Bd -ragged -offset indent
+.Cd "device sound"
+.Cd "device snd_davbus"
+.Ed
+.Pp
+Alternatively, to load the driver as a
+module at boot time, place the following line in
+.Xr loader.conf 5 :
+.Bd -literal -offset indent
+snd_davbus_load="YES"
+.Ed
+.Sh DESCRIPTION
+The
+.Nm
+driver provides support for the Apple Davbus audio controllers found in
+many G3-era Apple machines.
+.Sh HARDWARE
+.Pp
+Chips supported by the
+.Nm
+driver include:
+.Pp
+.Bl -bullet -compact
+.It
+Apple Burgundy Audio
+.It
+Apple Screamer Audio
+.El
+.Pp
+.Sh BUGS
+Recording is not currently supported.
+.Sh SEE ALSO
+.Xr sound 4 ,
+.Xr snd_ai2s 4
+.Sh HISTORY
+The
+.Nm
+device driver appeared in
+.Fx 8.0 .
+.Sh AUTHORS
+.An -nosplit
+The
+.Nm
+driver was written by
+.An Marco Trillo
+.Aq marcotrillo at gmail.com .

Modified: head/sys/conf/files.powerpc
==============================================================================
--- head/sys/conf/files.powerpc	Sun Jan 25 17:50:53 2009	(r187691)
+++ head/sys/conf/files.powerpc	Sun Jan 25 18:20:15 2009	(r187692)
@@ -39,6 +39,11 @@ dev/ofw/ofw_standard.c		optional	aim
 dev/powermac_nvram/powermac_nvram.c optional	powermac_nvram powermac
 dev/quicc/quicc_bfe_ocp.c	optional	quicc mpc85xx
 dev/scc/scc_bfe_macio.c		optional	scc powermac
+dev/sound/macio/aoa.c		optional	snd_davbus | snd_ai2s powermac
+dev/sound/macio/davbus.c	optional	snd_davbus powermac
+dev/sound/macio/i2s.c		optional	snd_ai2s powermac
+dev/sound/macio/snapper.c	optional	snd_ai2s iicbus powermac
+dev/sound/macio/tumbler.c	optional	snd_ai2s iicbus powermac
 dev/syscons/scgfbrndr.c		optional	sc
 dev/syscons/scterm-teken.c	optional	sc
 dev/syscons/scvtb.c		optional	sc

Added: head/sys/dev/sound/macio/aoa.c
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ head/sys/dev/sound/macio/aoa.c	Sun Jan 25 18:20:15 2009	(r187692)
@@ -0,0 +1,379 @@
+/*-
+ * Copyright 2008 by Marco Trillo. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+/*
+ *	Apple Onboard Audio (AOA).
+ */
+
+#include <sys/cdefs.h>
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/kernel.h>
+#include <sys/bus.h>
+#include <sys/malloc.h>
+#include <sys/lock.h>
+#include <sys/mutex.h>
+#include <machine/dbdma.h>
+#include <machine/resource.h>
+#include <machine/bus.h>
+#include <sys/rman.h>
+#include <dev/ofw/ofw_bus.h>
+#include <dev/sound/pcm/sound.h>
+#include <dev/sound/macio/aoa.h>
+#include "mixer_if.h"
+
+struct aoa_dma {
+	struct mtx 		 mutex;
+	struct resource 	*reg; 		/* DBDMA registers */
+	dbdma_channel_t 	*channel; 	/* DBDMA channel */
+	bus_dma_tag_t 		 tag; 		/* bus_dma tag */
+	struct pcm_channel 	*pcm;		/* PCM channel */
+	struct snd_dbuf		*buf; 		/* PCM buffer */
+	u_int 			 slots; 	/* # of slots */
+	u_int 			 slot;		/* current slot */
+	u_int 			 bufsz; 	/* buffer size */
+	u_int 			 blksz; 	/* block size */
+	int 			 running;
+};
+
+static void
+aoa_dma_set_program(struct aoa_dma *dma)
+{
+	u_int32_t 		 addr;
+	int 			 i;
+
+	addr = (u_int32_t) sndbuf_getbufaddr(dma->buf);
+	KASSERT(dma->bufsz == sndbuf_getsize(dma->buf), ("bad size"));
+
+	dma->slots = dma->bufsz / dma->blksz;
+
+	for (i = 0; i < dma->slots; ++i) {
+		dbdma_insert_command(dma->channel, 
+		    i, /* slot */
+		    DBDMA_OUTPUT_MORE, /* command */
+		    0, /* stream */
+		    addr, /* data */
+		    dma->blksz, /* count */
+		    DBDMA_ALWAYS, /* interrupt */
+		    DBDMA_COND_TRUE, /* branch */
+		    DBDMA_NEVER, /* wait */
+		    dma->slots + 1 /* branch_slot */
+		);
+
+		addr += dma->blksz;
+	}
+
+	/* Branch back to beginning. */
+	dbdma_insert_branch(dma->channel, dma->slots, 0);
+
+	/* STOP command to branch when S0 is asserted. */
+	dbdma_insert_stop(dma->channel, dma->slots + 1);
+
+	/* Set S0 as the condition to branch to STOP. */
+	dbdma_set_branch_selector(dma->channel, 1 << 0, 1 << 0);
+	dbdma_set_device_status(dma->channel, 1 << 0, 0);
+
+	dbdma_sync_commands(dma->channel, BUS_DMASYNC_PREWRITE);
+}
+
+#define AOA_BUFFER_SIZE		65536
+
+static struct aoa_dma * 
+aoa_dma_create(device_t self)
+{
+	struct aoa_softc *sc = device_get_softc(self);
+	struct aoa_dma *dma;
+	bus_dma_tag_t 	tag;
+	int 		err;
+
+	err = bus_dma_tag_create(bus_get_dma_tag(self), 
+	    4, 0, BUS_SPACE_MAXADDR_32BIT, BUS_SPACE_MAXADDR, NULL, NULL, 
+	    AOA_BUFFER_SIZE, 1, AOA_BUFFER_SIZE, 0, NULL, NULL, &tag);
+	if (err != 0) 
+		return (NULL);
+
+	dma = malloc(sizeof(*dma), M_DEVBUF, M_WAITOK | M_ZERO);
+	dma->tag = tag;
+	dma->bufsz = AOA_BUFFER_SIZE;
+	dma->blksz = PAGE_SIZE; /* initial blocksize */
+	
+	mtx_init(&dma->mutex, "AOA", NULL, MTX_DEF);
+
+	sc->sc_intrp = dma;
+
+	return (dma);
+}
+
+static void
+aoa_dma_delete(struct aoa_dma *dma)
+{
+	bus_dma_tag_destroy(dma->tag);
+	mtx_destroy(&dma->mutex);
+	free(dma, M_DEVBUF);
+}
+
+static int
+aoa_chan_setblocksize(kobj_t obj, void *data, u_int32_t blocksz)
+{
+	struct aoa_dma 		*dma = data;
+	int 			 err, lz;
+
+	DPRINTF(("aoa_chan_setblocksize: blocksz = %u, dma->blksz = %u\n", 
+		blocksz, dma->blksz));
+	KASSERT(!dma->running, ("dma is running"));
+	KASSERT(blocksz > 0, ("bad blocksz"));
+
+	/* Round blocksz down to a power of two... */
+	__asm volatile ("cntlzw %0,%1" : "=r"(lz) : "r"(blocksz));
+	blocksz = 1 << (31 - lz);
+	DPRINTF(("blocksz = %u\n", blocksz));
+
+	/* ...but no more than the buffer. */
+	if (blocksz > dma->bufsz)
+		blocksz = dma->bufsz;
+
+	err = sndbuf_resize(dma->buf, dma->bufsz / blocksz, blocksz);
+	if (err != 0) {
+		DPRINTF(("sndbuf_resize returned %d\n", err));
+		return (0);
+	}
+
+	if (blocksz == dma->blksz)
+		return (dma->blksz);
+
+	/* One slot per block plus branch to 0 plus STOP. */
+	err = dbdma_resize_channel(dma->channel, 2 + dma->bufsz / blocksz);
+	if (err != 0) {
+		DPRINTF(("dbdma_resize_channel returned %d\n", err));
+		return (0);
+	}
+
+	/* Set the new blocksize. */
+	dma->blksz = blocksz;
+	aoa_dma_set_program(dma);
+
+	return (dma->blksz);
+}
+
+static int
+aoa_chan_setformat(kobj_t obj, void *data, u_int32_t format)
+{
+	DPRINTF(("aoa_chan_setformat: format = %u\n", format));
+
+	if (format != (AFMT_STEREO | AFMT_S16_BE))
+		return (EINVAL);
+
+	return (0);
+}
+
+static int
+aoa_chan_setspeed(kobj_t obj, void *data, u_int32_t speed)
+{
+	DPRINTF(("aoa_chan_setspeed: speed = %u\n", speed));
+
+	return (44100);
+}
+
+static int
+aoa_chan_getptr(kobj_t obj, void *data)
+{
+	struct aoa_dma 	 *dma = data;
+
+	if (!dma->running)
+		return (0);
+	
+	return (dma->slot * dma->blksz);
+}
+
+static void *
+aoa_chan_init(kobj_t obj, void *devinfo, struct snd_dbuf *b, 
+	struct pcm_channel *c, int dir)
+{
+	device_t 		 self = devinfo;
+	struct aoa_softc 	*sc = device_get_softc(self);
+	struct aoa_dma		*dma;
+	int 	 		 max_slots, err;
+
+	KASSERT(dir == PCMDIR_PLAY, ("bad dir"));
+
+	dma = aoa_dma_create(self);
+	if (!dma)
+		return (NULL);
+	dma->pcm = c;
+	dma->buf = b;
+	dma->reg = sc->sc_odma;
+
+	/* One slot per block, plus branch to 0 plus STOP. */
+	max_slots = 2 + dma->bufsz / dma->blksz;
+	err = dbdma_allocate_channel(dma->reg, 0, bus_get_dma_tag(self),
+	    max_slots, &dma->channel );
+	if (err != 0) {
+		aoa_dma_delete(dma);
+		return (NULL);
+	}
+
+	if (sndbuf_alloc(dma->buf, dma->tag, 0, dma->bufsz) != 0) {
+		dbdma_free_channel(dma->channel);
+		aoa_dma_delete(dma);
+		return (NULL);
+	}
+
+	aoa_dma_set_program(dma);
+
+	return (dma);
+}
+
+static int
+aoa_chan_trigger(kobj_t obj, void *data, int go)
+{
+	struct aoa_dma 	*dma = data;
+	int 		 i;
+
+	switch (go) {
+	case PCMTRIG_START:
+
+		/* Start the DMA. */
+		dma->running = 1;
+		
+		dma->slot = 0;
+		dbdma_set_current_cmd(dma->channel, dma->slot);
+
+		dbdma_run(dma->channel);
+
+		return (0);
+
+	case PCMTRIG_STOP:
+	case PCMTRIG_ABORT:
+		
+		mtx_lock(&dma->mutex);
+
+		dma->running = 0;
+
+		/* Make it branch to the STOP command. */
+		dbdma_set_device_status(dma->channel, 1 << 0, 1 << 0);
+
+		/* XXX should wait for DBDMA_ACTIVE to clear. */
+		DELAY(40000);
+
+		/* Reset the DMA. */
+		dbdma_stop(dma->channel);
+		dbdma_set_device_status(dma->channel, 1 << 0, 0);
+
+		for (i = 0; i < dma->slots; ++i)
+			dbdma_clear_cmd_status(dma->channel, i);
+
+		mtx_unlock(&dma->mutex);
+
+		return (0);
+	}
+
+	return (0);
+}
+
+static int
+aoa_chan_free(kobj_t obj, void *data)
+{
+	struct aoa_dma 	*dma = data;
+
+	sndbuf_free(dma->buf);
+	dbdma_free_channel(dma->channel);
+	aoa_dma_delete(dma);
+
+	return (0);
+}
+
+void 
+aoa_interrupt(void *arg)
+{
+	struct aoa_softc	*sc = arg;
+	struct aoa_dma		*dma;
+
+	if (!(dma = sc->sc_intrp) || !dma->running)
+		return;
+
+	mtx_lock(&dma->mutex);
+
+	while (dbdma_get_cmd_status(dma->channel, dma->slot)) {
+
+		dbdma_clear_cmd_status(dma->channel, dma->slot);
+		dma->slot = (dma->slot + 1) % dma->slots;
+
+		mtx_unlock(&dma->mutex);
+		chn_intr(dma->pcm);
+		mtx_lock(&dma->mutex);
+	}
+
+	mtx_unlock(&dma->mutex);
+}
+
+static u_int32_t sc_fmt[] = {
+	AFMT_S16_BE | AFMT_STEREO,
+	0
+};
+static struct pcmchan_caps aoa_caps = {44100, 44100, sc_fmt, 0};
+
+static struct pcmchan_caps *
+aoa_chan_getcaps(kobj_t obj, void *data)
+{
+	return (&aoa_caps);
+}
+
+static kobj_method_t aoa_chan_methods[] = {
+	KOBJMETHOD(channel_init, 	aoa_chan_init),
+	KOBJMETHOD(channel_free, 	aoa_chan_free),
+	KOBJMETHOD(channel_setformat, 	aoa_chan_setformat),
+	KOBJMETHOD(channel_setspeed, 	aoa_chan_setspeed),
+	KOBJMETHOD(channel_setblocksize,aoa_chan_setblocksize),
+	KOBJMETHOD(channel_trigger,	aoa_chan_trigger),
+	KOBJMETHOD(channel_getptr,	aoa_chan_getptr),
+	KOBJMETHOD(channel_getcaps,	aoa_chan_getcaps),
+	{ 0, 0 }
+};
+CHANNEL_DECLARE(aoa_chan);
+
+int
+aoa_attach(device_t self)
+{
+	char status[SND_STATUSLEN];
+	int err;
+
+	if (pcm_register(self, self, 1, 0))
+		return (ENXIO);
+
+	err = pcm_getbuffersize(self, AOA_BUFFER_SIZE, AOA_BUFFER_SIZE,
+	    AOA_BUFFER_SIZE);
+	DPRINTF(("pcm_getbuffersize returned %d\n", err));
+
+	pcm_addchan(self, PCMDIR_PLAY, &aoa_chan_class, self);
+
+	snprintf(status, sizeof(status), "at %s", ofw_bus_get_name(self)); 
+	pcm_setstatus(self, status);
+
+	return (0);
+}
+

Added: head/sys/dev/sound/macio/aoa.h
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ head/sys/dev/sound/macio/aoa.h	Sun Jan 25 18:20:15 2009	(r187692)
@@ -0,0 +1,44 @@
+/*-
+ * Copyright 2008 by Marco Trillo. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#ifndef SOUND_AOA_H
+#define SOUND_AOA_H
+
+#define DPRINTF(x)	/* nothing */
+/* #define DPRINTF(x)	printf x */
+
+struct aoa_softc {
+	u_int8_t	  sc_super[PCM_SOFTC_SIZE];
+	void		 *sc_intrp;
+	struct resource	 *sc_odma;
+};
+
+void	aoa_interrupt(void *);
+int	aoa_attach(device_t);
+
+#endif /* SOUND_AOA_H */
+

Added: head/sys/dev/sound/macio/davbus.c
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ head/sys/dev/sound/macio/davbus.c	Sun Jan 25 18:20:15 2009	(r187692)
@@ -0,0 +1,600 @@
+/*-
+ * Copyright 2008 by Marco Trillo. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+/*
+ *	Apple DAVbus audio controller.
+ */
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/bus.h>
+#include <sys/kernel.h>
+#include <sys/lock.h>
+#include <sys/malloc.h>
+#include <sys/module.h>
+#include <sys/mutex.h>
+#include <sys/rman.h>
+
+#include <dev/ofw/ofw_bus.h>
+#include <dev/sound/pcm/sound.h>
+#include <dev/sound/macio/aoa.h>
+#include <dev/sound/macio/davbusreg.h>
+
+#include <machine/intr_machdep.h>
+#include <machine/resource.h>
+#include <machine/bus.h>
+
+#include "mixer_if.h"
+
+struct davbus_softc {
+	struct aoa_softc 	 aoa;
+	device_t 		 dev;
+	phandle_t 		 node;
+	phandle_t 		 soundnode;
+	struct resource 	*reg;
+	struct mtx 		 mutex;
+	int 			 device_id;
+	u_int 			 output_mask;
+	u_int 			(*read_status)(struct davbus_softc *, u_int);
+	void			(*set_outputs)(struct davbus_softc *, u_int);
+};
+
+static int 	davbus_probe(device_t);
+static int 	davbus_attach(device_t);
+static void	davbus_cint(void *);
+
+static device_method_t pcm_davbus_methods[] = {
+	/* Device interface. */
+	DEVMETHOD(device_probe,		davbus_probe),
+	DEVMETHOD(device_attach, 	davbus_attach),
+
+	{ 0, 0 }
+};
+
+static driver_t pcm_davbus_driver = {
+	"pcm",
+	pcm_davbus_methods,
+	sizeof(struct davbus_softc)
+};
+
+DRIVER_MODULE(pcm_davbus, macio, pcm_davbus_driver, pcm_devclass, 0, 0);
+MODULE_DEPEND(pcm_davbus, sound, SOUND_MINVER, SOUND_PREFVER, SOUND_MAXVER);
+
+/*****************************************************************************
+			Probe and attachment routines.
+ *****************************************************************************/
+static int
+davbus_probe(device_t self)
+{
+	const char 		*name;
+	struct davbus_softc 	*sc;
+
+	name = ofw_bus_get_name(self);
+	if (!name)
+		return (ENXIO);
+
+	if (strcmp(name, "davbus") != 0)
+		return (ENXIO);
+	
+	sc = device_get_softc(self);
+	if (!sc)
+		return (ENOMEM);
+	bzero(sc, sizeof(*sc));
+
+	device_set_desc(self, "Apple DAVBus Audio Controller");
+
+	return (0);
+}
+
+/*
+ * Burgundy codec control
+ */
+
+static int	burgundy_init(struct snd_mixer *m);
+static int	burgundy_uninit(struct snd_mixer *m);
+static int	burgundy_reinit(struct snd_mixer *m);
+static void 	burgundy_write_locked(struct davbus_softc *, u_int, u_int);
+static void	burgundy_set_outputs(struct davbus_softc *d, u_int mask);
+static u_int	burgundy_read_status(struct davbus_softc *d, u_int status);
+static int	burgundy_set(struct snd_mixer *m, unsigned dev, unsigned left,
+		    unsigned right);
+static int	burgundy_setrecsrc(struct snd_mixer *m, u_int32_t src);
+
+static kobj_method_t burgundy_mixer_methods[] = {
+	KOBJMETHOD(mixer_init, 		burgundy_init),
+	KOBJMETHOD(mixer_uninit, 	burgundy_uninit),
+	KOBJMETHOD(mixer_reinit, 	burgundy_reinit),
+	KOBJMETHOD(mixer_set, 		burgundy_set),
+	KOBJMETHOD(mixer_setrecsrc,	burgundy_setrecsrc),
+	{ 0, 0 }
+};
+
+MIXER_DECLARE(burgundy_mixer);
+
+static int
+burgundy_init(struct snd_mixer *m)
+{
+	struct davbus_softc *d;
+
+	d = mix_getdevinfo(m);
+
+	d->read_status = burgundy_read_status;
+	d->set_outputs = burgundy_set_outputs;
+
+	/*
+	 * We configure the Burgundy codec as follows:
+	 *
+	 * 	o Input subframe 0 is connected to input digital
+	 *	  stream A (ISA).
+	 *	o Stream A (ISA) is mixed in mixer 2 (MIX2).
+	 *	o Output of mixer 2 (MIX2) is routed to output sources
+	 *	  OS0 and OS1 which can be converted to analog.
+	 *
+	 */
+	mtx_lock(&d->mutex);
+
+	burgundy_write_locked(d, 0x16700, 0x40);
+	
+	burgundy_write_locked(d, BURGUNDY_MIX0_REG, 0); 
+	burgundy_write_locked(d, BURGUNDY_MIX1_REG, 0);
+	burgundy_write_locked(d, BURGUNDY_MIX2_REG, BURGUNDY_MIX_ISA);
+	burgundy_write_locked(d, BURGUNDY_MIX3_REG, 0);
+
+	burgundy_write_locked(d, BURGUNDY_OS_REG, BURGUNDY_OS0_MIX2 | 
+	    BURGUNDY_OS1_MIX2);
+
+	burgundy_write_locked(d, BURGUNDY_SDIN_REG, BURGUNDY_ISA_SF0);
+
+	/* Set several digital scalers to unity gain. */
+	burgundy_write_locked(d, BURGUNDY_MXS2L_REG, BURGUNDY_MXS_UNITY);
+	burgundy_write_locked(d, BURGUNDY_MXS2R_REG, BURGUNDY_MXS_UNITY);
+	burgundy_write_locked(d, BURGUNDY_OSS0L_REG, BURGUNDY_OSS_UNITY);
+	burgundy_write_locked(d, BURGUNDY_OSS0R_REG, BURGUNDY_OSS_UNITY);
+	burgundy_write_locked(d, BURGUNDY_OSS1L_REG, BURGUNDY_OSS_UNITY);
+	burgundy_write_locked(d, BURGUNDY_OSS1R_REG, BURGUNDY_OSS_UNITY);
+	burgundy_write_locked(d, BURGUNDY_ISSAL_REG, BURGUNDY_ISS_UNITY);
+	burgundy_write_locked(d, BURGUNDY_ISSAR_REG, BURGUNDY_ISS_UNITY);
+
+	burgundy_set_outputs(d, burgundy_read_status(d, 
+	    bus_read_4(d->reg, DAVBUS_CODEC_STATUS)));
+
+	mtx_unlock(&d->mutex);
+
+	mix_setdevs(m, SOUND_MASK_VOLUME);
+
+	return (0);
+}
+
+static int
+burgundy_uninit(struct snd_mixer *m)
+{
+	return (0);
+}
+
+static int
+burgundy_reinit(struct snd_mixer *m)
+{
+	return (0);
+}
+
+static void
+burgundy_write_locked(struct davbus_softc *d, u_int reg, u_int val)
+{
+	u_int size, addr, offset, data, i;
+
+	size = (reg & 0x00FF0000) >> 16;
+	addr = (reg & 0x0000FF00) >> 8;
+	offset = reg & 0xFF;
+
+	for (i = offset; i < offset + size; ++i) {
+		data = BURGUNDY_CTRL_WRITE | (addr << 12) | 
+		    ((size + offset - 1) << 10) | (i << 8) | (val & 0xFF);
+		if (i == offset)
+			data |= BURGUNDY_CTRL_RESET;
+
+		bus_write_4(d->reg, DAVBUS_CODEC_CTRL, data);
+
+		while (bus_read_4(d->reg, DAVBUS_CODEC_CTRL) &
+		    DAVBUS_CODEC_BUSY)
+			DELAY(1);
+		
+		val >>= 8; /* next byte. */
+	}	
+}
+
+/* Must be called with d->mutex held. */
+static void
+burgundy_set_outputs(struct davbus_softc *d, u_int mask)
+{
+	u_int	x = 0;
+
+	if (mask == d->output_mask)
+		return;
+
+	/*
+	 *	Bordeaux card wirings:
+	 *		Port 15:	RCA out
+	 *		Port 16:	Minijack out
+	 *		Port 17:	Internal speaker
+	 *
+	 *	B&W G3 wirings:
+	 *		Port 14:	Minijack out
+	 *		Port 17:	Internal speaker
+	 */
+
+	DPRINTF(("Enabled outputs:"));
+	if (mask & (1 << 0)) {
+		DPRINTF((" SPEAKER"));
+		x |= BURGUNDY_P17M_EN;
+	}
+	if (mask & (1 << 1)) {
+		DPRINTF((" HEADPHONES"));
+		x |= BURGUNDY_P14L_EN | BURGUNDY_P14R_EN;	
+	}
+	DPRINTF(("\n"));
+
+	burgundy_write_locked(d, BURGUNDY_MUTE_REG, x);
+	d->output_mask = mask;
+}
+
+static u_int
+burgundy_read_status(struct davbus_softc *d, u_int status)
+{
+	if (status & 0x4)
+		return (1 << 1);
+	else
+		return (1 << 0);
+}
+
+static int
+burgundy_set(struct snd_mixer *m, unsigned dev, unsigned left, unsigned right)
+{
+	struct davbus_softc *d;
+	int lval, rval;
+
+	lval = ((100 - left) * 15 / 100) & 0xf;
+	rval = ((100 - right) * 15 / 100) & 0xf;
+	DPRINTF(("volume %d %d\n", lval, rval));
+
+	d = mix_getdevinfo(m);
+
+	switch (dev) {
+	case SOUND_MIXER_VOLUME:
+		mtx_lock(&d->mutex);
+
+		burgundy_write_locked(d, BURGUNDY_OL13_REG, lval);
+		burgundy_write_locked(d, BURGUNDY_OL14_REG, (rval << 4) | lval);
+		burgundy_write_locked(d, BURGUNDY_OL15_REG, (rval << 4) | lval);
+		burgundy_write_locked(d, BURGUNDY_OL16_REG, (rval << 4) | lval);
+		burgundy_write_locked(d, BURGUNDY_OL17_REG, lval);
+
+		mtx_unlock(&d->mutex);
+
+		return (left | (right << 8));
+	}
+
+	return (0);
+}
+
+static int
+burgundy_setrecsrc(struct snd_mixer *m, u_int32_t src)
+{
+	return (0);
+}
+
+/*
+ * Screamer Codec Control
+ */
+
+static int	screamer_init(struct snd_mixer *m);
+static int	screamer_uninit(struct snd_mixer *m);
+static int	screamer_reinit(struct snd_mixer *m);
+static void 	screamer_write_locked(struct davbus_softc *, u_int, u_int);
+static void	screamer_set_outputs(struct davbus_softc *d, u_int mask);
+static u_int	screamer_read_status(struct davbus_softc *d, u_int status);
+static int	screamer_set(struct snd_mixer *m, unsigned dev, unsigned left,
+		    unsigned right);
+static int	screamer_setrecsrc(struct snd_mixer *m, u_int32_t src);
+
+static kobj_method_t screamer_mixer_methods[] = {
+	KOBJMETHOD(mixer_init, 		screamer_init),
+	KOBJMETHOD(mixer_uninit, 	screamer_uninit),
+	KOBJMETHOD(mixer_reinit, 	screamer_reinit),
+	KOBJMETHOD(mixer_set, 		screamer_set),
+	KOBJMETHOD(mixer_setrecsrc,	screamer_setrecsrc),
+	{ 0, 0 }
+};
+
+MIXER_DECLARE(screamer_mixer);
+
+static int
+screamer_init(struct snd_mixer *m)
+{
+	struct davbus_softc *d;
+
+	d = mix_getdevinfo(m);
+
+	d->read_status = screamer_read_status;
+	d->set_outputs = screamer_set_outputs;
+
+	mtx_lock(&d->mutex);
+
+	screamer_write_locked(d, SCREAMER_CODEC_ADDR0, SCREAMER_INPUT_CD | 
+	    SCREAMER_DEFAULT_CD_GAIN);
+
+	screamer_set_outputs(d, screamer_read_status(d, 
+	    bus_read_4(d->reg, DAVBUS_CODEC_STATUS)));
+
+	screamer_write_locked(d, SCREAMER_CODEC_ADDR2, 0);
+	screamer_write_locked(d, SCREAMER_CODEC_ADDR4, 0);
+	screamer_write_locked(d, SCREAMER_CODEC_ADDR5, 0);
+	screamer_write_locked(d, SCREAMER_CODEC_ADDR6, 0);
+
+	mtx_unlock(&d->mutex);
+
+	mix_setdevs(m, SOUND_MASK_VOLUME);
+
+	return (0);
+}

*** DIFF OUTPUT TRUNCATED AT 1000 LINES ***


More information about the svn-src-all mailing list