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