summaryrefslogtreecommitdiffstats
path: root/sys/dev/sound/pcm
diff options
context:
space:
mode:
authorcg <cg@FreeBSD.org>2000-12-18 01:36:41 +0000
committercg <cg@FreeBSD.org>2000-12-18 01:36:41 +0000
commit2fae4aec24ea4529882b3ec4cda45661ccd48ea8 (patch)
treee7e32573ed48df98bed54daa386c3520e959e951 /sys/dev/sound/pcm
parent1fd2c926a884cc824e7da7ee1a51dad72b1dec5b (diff)
downloadFreeBSD-src-2fae4aec24ea4529882b3ec4cda45661ccd48ea8.zip
FreeBSD-src-2fae4aec24ea4529882b3ec4cda45661ccd48ea8.tar.gz
kobjify.
this gives us several benefits, including: * easier extensibility- new optional methods can be added to ac97/mixer/channel classes without having to fixup every driver. * forward compatibility for drivers, provided no new mandatory methods are added.
Diffstat (limited to 'sys/dev/sound/pcm')
-rw-r--r--sys/dev/sound/pcm/ac97.c103
-rw-r--r--sys/dev/sound/pcm/ac97.h34
-rw-r--r--sys/dev/sound/pcm/ac97_if.m60
-rw-r--r--sys/dev/sound/pcm/channel.c87
-rw-r--r--sys/dev/sound/pcm/channel.h6
-rw-r--r--sys/dev/sound/pcm/channel_if.m123
-rw-r--r--sys/dev/sound/pcm/datatypes.h71
-rw-r--r--sys/dev/sound/pcm/dsp.c5
-rw-r--r--sys/dev/sound/pcm/fake.c67
-rw-r--r--sys/dev/sound/pcm/feeder.c160
-rw-r--r--sys/dev/sound/pcm/feeder.h24
-rw-r--r--sys/dev/sound/pcm/feeder_fmt.c218
-rw-r--r--sys/dev/sound/pcm/feeder_if.m71
-rw-r--r--sys/dev/sound/pcm/mixer.c249
-rw-r--r--sys/dev/sound/pcm/mixer.h8
-rw-r--r--sys/dev/sound/pcm/mixer_if.m68
-rw-r--r--sys/dev/sound/pcm/sound.c27
-rw-r--r--sys/dev/sound/pcm/sound.h4
18 files changed, 849 insertions, 536 deletions
diff --git a/sys/dev/sound/pcm/ac97.c b/sys/dev/sound/pcm/ac97.c
index 3a8bf36..a4020e8 100644
--- a/sys/dev/sound/pcm/ac97.c
+++ b/sys/dev/sound/pcm/ac97.c
@@ -29,28 +29,9 @@
#include <dev/sound/pcm/sound.h>
#include <dev/sound/pcm/ac97.h>
-struct ac97mixtable_entry {
- int reg:8;
- unsigned bits:4;
- unsigned ofs:4;
- unsigned stereo:1;
- unsigned mute:1;
- unsigned recidx:4;
- unsigned mask:1;
- unsigned enable:1;
-};
+#include "mixer_if.h"
-struct ac97_info {
- device_t dev;
- ac97_init *init;
- ac97_read *read;
- ac97_write *write;
- void *devinfo;
- char *name;
- char rev;
- unsigned count, caps, se, extcaps, extid, extstat, noext:1;
- struct ac97mixtable_entry mix[32];
-};
+MALLOC_DEFINE(M_AC97, "ac97", "ac97 codec");
struct ac97_codecid {
u_int32_t id, noext:1;
@@ -154,13 +135,13 @@ static char *ac97extfeature[] = {
static u_int16_t
rdcd(struct ac97_info *codec, int reg)
{
- return codec->read(codec->devinfo, reg);
+ return AC97_READ(codec->methods, codec->devinfo, reg);
}
static void
wrcd(struct ac97_info *codec, int reg, u_int16_t val)
{
- codec->write(codec->devinfo, reg, val);
+ AC97_WRITE(codec->methods, codec->devinfo, reg, val);
}
int
@@ -309,14 +290,11 @@ ac97_initmixer(struct ac97_info *codec)
for (i = 0; i < 32; i++)
codec->mix[i] = ac97mixtable_default[i];
- if (codec->init) {
- codec->count = codec->init(codec->devinfo);
- if (codec->count == 0) {
- device_printf(codec->dev, "ac97 codec init failed\n");
- return ENODEV;
- }
- } else
- codec->count = 1;
+ codec->count = AC97_INIT(codec->methods, codec->devinfo);
+ if (codec->count == 0) {
+ device_printf(codec->dev, "ac97 codec init failed\n");
+ return ENODEV;
+ }
wrcd(codec, AC97_REG_POWER, 0);
wrcd(codec, AC97_REG_RESET, 0);
@@ -401,14 +379,11 @@ ac97_reinitmixer(struct ac97_info *codec)
{
unsigned i;
- if (codec->init) {
- codec->count = codec->init(codec->devinfo);
- if (codec->count == 0) {
- device_printf(codec->dev, "ac97 codec init failed\n");
- return ENODEV;
- }
- } else
- codec->count = 1;
+ codec->count = AC97_INIT(codec->methods, codec->devinfo);
+ if (codec->count == 0) {
+ device_printf(codec->dev, "ac97 codec init failed\n");
+ return ENODEV;
+ }
wrcd(codec, AC97_REG_POWER, 0);
wrcd(codec, AC97_REG_RESET, 0);
@@ -428,27 +403,35 @@ ac97_reinitmixer(struct ac97_info *codec)
}
struct ac97_info *
-ac97_create(device_t dev, void *devinfo, ac97_init *init, ac97_read *rd, ac97_write *wr)
+ac97_create(device_t dev, void *devinfo, kobj_class_t cls)
{
struct ac97_info *codec;
- codec = (struct ac97_info *)malloc(sizeof *codec, M_DEVBUF, M_NOWAIT);
- if (codec != NULL) {
- codec->dev = dev;
- codec->init = init;
- codec->read = rd;
- codec->write = wr;
- codec->devinfo = devinfo;
+ codec = (struct ac97_info *)malloc(sizeof *codec, M_AC97, M_NOWAIT);
+ if (codec == NULL)
+ return NULL;
+
+ codec->methods = kobj_create(cls, M_AC97, M_WAITOK);
+ if (codec->methods == NULL) {
+ free(codec, M_AC97);
+ return NULL;
}
+
+ codec->dev = dev;
+ codec->devinfo = devinfo;
return codec;
}
void
ac97_destroy(struct ac97_info *codec)
{
- free(codec, M_DEVBUF);
+ if (codec->methods != NULL)
+ kobj_delete(codec->methods, M_AC97);
+ free(codec, M_AC97);
}
+/* -------------------------------------------------------------------- */
+
static int
ac97mix_init(snd_mixer *m)
{
@@ -522,12 +505,22 @@ ac97mix_setrecsrc(snd_mixer *m, u_int32_t src)
return (ac97_setrecsrc(codec, i) == 0)? 1 << i : -1;
}
-snd_mixer ac97_mixer = {
- "AC97 mixer",
- ac97mix_init,
- ac97mix_uninit,
- ac97mix_reinit,
- ac97mix_set,
- ac97mix_setrecsrc,
+static kobj_method_t ac97mixer_methods[] = {
+ KOBJMETHOD(mixer_init, ac97mix_init),
+ KOBJMETHOD(mixer_uninit, ac97mix_uninit),
+ KOBJMETHOD(mixer_reinit, ac97mix_reinit),
+ KOBJMETHOD(mixer_set, ac97mix_set),
+ KOBJMETHOD(mixer_setrecsrc, ac97mix_setrecsrc),
+ { 0, 0 }
};
+MIXER_DECLARE(ac97mixer);
+
+/* -------------------------------------------------------------------- */
+
+kobj_class_t
+ac97_getmixerclass(void)
+{
+ return &ac97mixer_class;
+}
+
diff --git a/sys/dev/sound/pcm/ac97.h b/sys/dev/sound/pcm/ac97.h
index 1305424..6f36761 100644
--- a/sys/dev/sound/pcm/ac97.h
+++ b/sys/dev/sound/pcm/ac97.h
@@ -63,15 +63,35 @@
#define AC97_REG_ID1 0x7c
#define AC97_REG_ID2 0x7e
-typedef u_int32_t (ac97_init)(void *devinfo);
-typedef u_int32_t (ac97_read)(void *devinfo, int regno);
-typedef void (ac97_write)(void *devinfo, int regno, u_int32_t data);
+struct ac97mixtable_entry {
+ int reg:8;
+ unsigned bits:4;
+ unsigned ofs:4;
+ unsigned stereo:1;
+ unsigned mute:1;
+ unsigned recidx:4;
+ unsigned mask:1;
+ unsigned enable:1;
+};
-extern snd_mixer ac97_mixer;
-struct ac97_info;
+#define AC97_DECLARE(name) static DEFINE_CLASS(name, name ## _methods, sizeof(struct kobj))
+#define AC97_CREATE(dev, devinfo, cls) ac97_create(dev, devinfo, &cls ## _class)
-struct ac97_info *ac97_create(device_t dev, void *devinfo, ac97_init *init,
- ac97_read *rd, ac97_write *wr);
+struct ac97_info {
+ kobj_t methods;
+ device_t dev;
+ void *devinfo;
+ char *name;
+ char rev;
+ unsigned count, caps, se, extcaps, extid, extstat, noext:1;
+ struct ac97mixtable_entry mix[32];
+};
+
+#include "ac97_if.h"
+
+extern kobj_class_t ac97_getmixerclass(void);
+
+struct ac97_info *ac97_create(device_t dev, void *devinfo, kobj_class_t cls);
void ac97_destroy(struct ac97_info *codec);
int ac97_setrate(struct ac97_info *codec, int which, int rate);
int ac97_setextmode(struct ac97_info *codec, u_int16_t mode);
diff --git a/sys/dev/sound/pcm/ac97_if.m b/sys/dev/sound/pcm/ac97_if.m
new file mode 100644
index 0000000..d71f3d1
--- /dev/null
+++ b/sys/dev/sound/pcm/ac97_if.m
@@ -0,0 +1,60 @@
+#
+# Copyright (c) 2000 Cameron Grant <cg@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 AND CONTRIBUTORS ``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 OR CONTRIBUTORS 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$
+#
+
+#include <dev/sound/pcm/sound.h>
+
+INTERFACE ac97;
+
+CODE {
+
+ static u_int32_t
+ ac97_noinit(kobj_t obj, void *devinfo)
+ {
+ return 1;
+ }
+
+};
+
+METHOD u_int32_t init {
+ kobj_t obj;
+ void *devinfo;
+} DEFAULT ac97_noinit;
+
+METHOD int read {
+ kobj_t obj;
+ void *devinfo;
+ int regno;
+};
+
+METHOD int write {
+ kobj_t obj;
+ void *devinfo;
+ int regno;
+ u_int32_t data;
+};
+
diff --git a/sys/dev/sound/pcm/channel.c b/sys/dev/sound/pcm/channel.c
index 4e37da4..4030028 100644
--- a/sys/dev/sound/pcm/channel.c
+++ b/sys/dev/sound/pcm/channel.c
@@ -29,6 +29,9 @@
#include <dev/sound/pcm/sound.h>
+#include "feeder_if.h"
+
+MALLOC_DEFINE(M_CHANNEL, "channel", "pcm channel");
#define MIN_CHUNK_SIZE 256 /* for uiomove etc. */
#define DMA_ALIGN_THRESHOLD 4
#define DMA_ALIGN_MASK (~(DMA_ALIGN_THRESHOLD - 1))
@@ -326,13 +329,13 @@ chn_wrfeed2nd(pcm_channel *c, struct uio *buf)
l = min(bs->fl, bs->bufsize - bs->fp);
/* Move the samples, update the markers and pointers. */
if (l < 64) {
- w = c->feeder->feed(c->feeder, c, hackbuf, 64, buf);
+ w = FEEDER_FEED(c->feeder, c, hackbuf, 64, buf);
l = min(w, bs->bufsize - bs->fp);
bcopy(hackbuf, bs->buf + bs->fp, l);
if (w > l)
bcopy(hackbuf + l, bs->buf, w - l);
} else
- w = c->feeder->feed(c->feeder, c, bs->buf + bs->fp, l, buf);
+ w = FEEDER_FEED(c->feeder, c, bs->buf + bs->fp, l, buf);
if (w == 0)
panic("no feed");
bs->rl += w;
@@ -639,7 +642,7 @@ chn_rdfeed2nd(pcm_channel *c, struct uio *buf)
*/
l = min(bs->rl, bs->bufsize - bs->rp);
/* Move the samples, update the markers and pointers. */
- w = c->feeder->feed(c->feeder, c, bs->buf + bs->rp, l, buf);
+ w = FEEDER_FEED(c->feeder, c, bs->buf + bs->rp, l, buf);
if (w == 0)
panic("no feed");
bs->fl += w;
@@ -1128,8 +1131,7 @@ chn_reset(pcm_channel *c, u_int32_t fmt)
chn_abort(c);
c->flags &= CHN_F_RESET;
- if (c->reset)
- c->reset(c->devinfo);
+ CHANNEL_RESET(c->methods, c->devinfo);
r = chn_setblocksize(c, CHN_2NDBUFBLKNUM, CHN_2NDBUFBLKSIZE);
if (r)
return r;
@@ -1145,8 +1147,7 @@ chn_reset(pcm_channel *c, u_int32_t fmt)
r = chn_setvolume(c, 100, 100);
}
chn_resetbuf(c);
- if (c->resetdone)
- c->resetdone(c->devinfo);
+ CHANNEL_RESETDONE(c->methods, c->devinfo);
/* c->flags |= CHN_F_INIT; */
return 0;
}
@@ -1167,26 +1168,25 @@ chn_reinit(pcm_channel *c)
int
chn_init(pcm_channel *c, void *devinfo, int dir)
{
- snd_dbuf *bs = &c->buffer2nd;
+ struct feeder_class *fc;
+ snd_dbuf *bs = &c->buffer2nd;
/* Initialize the hardware and DMA buffer first. */
- c->feeder = malloc(sizeof(*(c->feeder)), M_DEVBUF, M_NOWAIT);
- *(c->feeder) = *feeder_getroot();
- c->feederdesc = malloc(sizeof(*(c->feeder)), M_DEVBUF, M_NOWAIT);
- c->feederdesc->type = FEEDER_ROOT;
- c->feederdesc->in = 0;
- c->feederdesc->out = 0;
- c->feederdesc->flags = 0;
- c->feederdesc->idx = 0;
- c->feeder->desc = c->feederdesc;
- c->feeder->source = NULL;
+ c->feeder = NULL;
+ fc = feeder_getclass(NULL);
+ if (fc == NULL)
+ return EINVAL;
+ if (chn_addfeeder(c, fc, NULL))
+ return EINVAL;
c->flags = 0;
c->feederflags = 0;
c->buffer.chan = -1;
- c->devinfo = c->init(devinfo, &c->buffer, c, dir);
- if (c->devinfo == NULL || c->buffer.bufsize == 0)
- return 1;
+ c->devinfo = CHANNEL_INIT(c->methods, devinfo, &c->buffer, c, dir);
+ if (c->devinfo == NULL)
+ return ENODEV;
+ if (c->buffer.bufsize == 0)
+ return ENOMEM;
chn_setdir(c, dir);
/* And the secondary buffer. */
@@ -1201,11 +1201,7 @@ chn_kill(pcm_channel *c)
if (c->flags & CHN_F_TRIGGERED)
chn_trigger(c, PCMTRIG_ABORT);
while (chn_removefeeder(c) == 0);
- free(c->feeder->desc, M_DEVBUF);
- free(c->feeder, M_DEVBUF);
- if (c->free)
- c->free(c->devinfo);
- else
+ if (CHANNEL_FREE(c->methods, c->devinfo))
chn_freebuf(&c->buffer);
c->flags |= CHN_F_DEAD;
return 0;
@@ -1217,7 +1213,7 @@ chn_setdir(pcm_channel *c, int dir)
int r;
c->direction = dir;
- r = c->setdir? c->setdir(c->devinfo, c->direction) : 0;
+ r = CHANNEL_SETDIR(c->methods, c->devinfo, c->direction);
if (!r && ISA_DMA(&c->buffer))
c->buffer.dir = (dir == PCMDIR_PLAY)? ISADMA_WRITE : ISADMA_READ;
return r;
@@ -1250,7 +1246,7 @@ chn_setspeed(pcm_channel *c, int speed)
hwspd = speed;
RANGE(hwspd, chn_getcaps(c)->minspeed, chn_getcaps(c)->maxspeed);
DEB(printf("try speed %d, ", hwspd));
- hwspd = c->setspeed(c->devinfo, hwspd);
+ hwspd = CHANNEL_SETSPEED(c->methods, c->devinfo, hwspd);
DEB(printf("got speed %d, ", hwspd));
delta = hwspd - speed;
if (delta < 0)
@@ -1270,11 +1266,11 @@ chn_setspeed(pcm_channel *c, int speed)
DEB(printf("feedrate = %p\n", f));
if (f == NULL)
return EINVAL;
- r = feeder_set(f, FEEDRATE_SRC, speed);
+ r = FEEDER_SET(f, FEEDRATE_SRC, speed);
DEB(printf("feeder_set(FEEDRATE_SRC, %d) = %d\n", speed, r));
if (r)
return r;
- r = feeder_set(f, FEEDRATE_DST, hwspd);
+ r = FEEDER_SET(f, FEEDRATE_DST, hwspd);
DEB(printf("feeder_set(FEEDRATE_DST, %d) = %d\n", hwspd, r));
if (r)
return r;
@@ -1296,7 +1292,6 @@ chn_setformat(pcm_channel *c, u_int32_t fmt)
if (CANCHANGE(c)) {
DEB(printf("want format %d\n", fmt));
c->format = fmt;
- c->feederdesc->out = c->format;
hwfmt = c->format;
c->feederflags &= ~(1 << FEEDER_FMT);
if (!fmtvalid(hwfmt, chn_getcaps(c)->fmtlist))
@@ -1308,7 +1303,7 @@ chn_setformat(pcm_channel *c, u_int32_t fmt)
b->fmt = hwfmt;
bs->fmt = hwfmt;
chn_resetbuf(c);
- c->setformat(c->devinfo, hwfmt);
+ CHANNEL_SETFORMAT(c->methods, c->devinfo, hwfmt);
return chn_setspeed(c, c->speed);
}
c->format = fmt;
@@ -1368,7 +1363,7 @@ chn_setblocksize(pcm_channel *c, int blkcnt, int blksz)
bs->blkcnt = blkcnt;
bs->blksz = blksz;
RANGE(blksz, 16, b->bufsize / 2);
- b->blksz = c->setblocksize(c->devinfo, blksz);
+ b->blksz = CHANNEL_SETBLOCKSIZE(c->methods, c->devinfo, blksz);
splx(s);
return 0;
@@ -1377,7 +1372,7 @@ chn_setblocksize(pcm_channel *c, int blkcnt, int blksz)
int
chn_trigger(pcm_channel *c, int go)
{
- return c->trigger(c->devinfo, go);
+ return CHANNEL_TRIGGER(c->methods, c->devinfo, go);
}
int
@@ -1387,7 +1382,7 @@ chn_getptr(pcm_channel *c)
int a = (1 << c->align) - 1;
snd_dbuf *b = &c->buffer;
- hwptr = b->dl? c->getptr(c->devinfo) : 0;
+ hwptr = b->dl? CHANNEL_GETPTR(c->methods, c->devinfo) : 0;
/* don't allow unaligned values in the hwa ptr */
hwptr &= ~a ; /* Apply channel align mask */
hwptr &= DMA_ALIGN_MASK; /* Apply DMA align mask */
@@ -1397,7 +1392,7 @@ chn_getptr(pcm_channel *c)
pcmchan_caps *
chn_getcaps(pcm_channel *c)
{
- return c->getcaps(c->devinfo);
+ return CHANNEL_GETCAPS(c->methods, c->devinfo);
}
u_int32_t
@@ -1417,12 +1412,20 @@ chn_getformats(pcm_channel *c)
static int
chn_buildfeeder(pcm_channel *c)
{
- pcm_feeder *f;
+ struct feeder_class *fc;
struct pcm_feederdesc desc;
u_int32_t tmp[2], src, dst, type, flags;
while (chn_removefeeder(c) == 0);
+ KASSERT((c->feeder == NULL), ("feeder chain not empty"));
c->align = 0;
+ fc = feeder_getclass(NULL);
+ if (fc == NULL)
+ return EINVAL;
+ if (chn_addfeeder(c, fc, NULL))
+ return EINVAL;
+ c->feeder->desc->out = c->format;
+
flags = c->feederflags;
src = c->feeder->desc->out;
if ((c->flags & CHN_F_MAPPED) && (flags != 0))
@@ -1435,11 +1438,11 @@ chn_buildfeeder(pcm_channel *c)
desc.out = 0;
desc.flags = 0;
DEB(printf("find feeder type %d, ", type));
- f = feeder_get(&desc);
+ fc = feeder_getclass(&desc);
DEB(printf("got %p\n", f));
- if (f == NULL)
+ if (fc == NULL)
return EINVAL;
- dst = f->desc->in;
+ dst = fc->desc->in;
if (src != dst) {
DEB(printf("build fmtchain from %x to %x: ", src, dst));
tmp[0] = dst;
@@ -1448,9 +1451,9 @@ chn_buildfeeder(pcm_channel *c)
return EINVAL;
DEB(printf("ok\n"));
}
- if (chn_addfeeder(c, f))
+ if (chn_addfeeder(c, fc, fc->desc))
return EINVAL;
- src = f->desc->out;
+ src = fc->desc->out;
DEB(printf("added feeder %p, output %x\n", f, src));
dst = 0;
flags &= ~(1 << type);
diff --git a/sys/dev/sound/pcm/channel.h b/sys/dev/sound/pcm/channel.h
index fa1173b..243c207 100644
--- a/sys/dev/sound/pcm/channel.h
+++ b/sys/dev/sound/pcm/channel.h
@@ -26,6 +26,8 @@
* $FreeBSD$
*/
+#include "channel_if.h"
+
int chn_reinit(pcm_channel *c);
int chn_write(pcm_channel *c, struct uio *buf);
int chn_read(pcm_channel *c, struct uio *buf);
@@ -85,7 +87,7 @@ int buf_isadmaptr(snd_dbuf *b);
#define CHN_F_INIT 0x00008000 /* changed parameters. need init */
#define CHN_F_MAPPED 0x00010000 /* has been mmap()ed */
#define CHN_F_DEAD 0x00020000
-
+#define CHN_F_BADSETTING 0x00040000
#define CHN_F_RESET (CHN_F_BUSY | CHN_F_DEAD)
@@ -99,3 +101,5 @@ int buf_isadmaptr(snd_dbuf *b);
#define CHN_2NDBUFBLKNUM (32)
/* The size of a whole secondary buffer. */
#define CHN_2NDBUFMAXSIZE (131072)
+
+#define CHANNEL_DECLARE(name) static DEFINE_CLASS(name, name ## _methods, sizeof(struct kobj))
diff --git a/sys/dev/sound/pcm/channel_if.m b/sys/dev/sound/pcm/channel_if.m
new file mode 100644
index 0000000..96a60f1
--- /dev/null
+++ b/sys/dev/sound/pcm/channel_if.m
@@ -0,0 +1,123 @@
+#
+# Copyright (c) 2000 Cameron Grant <cg@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 AND CONTRIBUTORS ``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 OR CONTRIBUTORS 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$
+#
+
+#include <dev/sound/pcm/sound.h>
+
+INTERFACE channel;
+
+CODE {
+
+ static int
+ channel_nosetdir(kobj_t obj, void *data, int dir)
+ {
+ return 0;
+ }
+
+ static int
+ channel_noreset(kobj_t obj, void *data)
+ {
+ return 0;
+ }
+
+ static int
+ channel_noresetdone(kobj_t obj, void *data)
+ {
+ return 0;
+ }
+
+ static int
+ channel_nofree(kobj_t obj, void *data)
+ {
+ return 1;
+ }
+
+};
+
+METHOD void* init {
+ kobj_t obj;
+ void *devinfo;
+ snd_dbuf *b;
+ pcm_channel *c;
+ int dir;
+};
+
+METHOD int free {
+ kobj_t obj;
+ void *data;
+} DEFAULT channel_nofree;
+
+METHOD int reset {
+ kobj_t obj;
+ void *data;
+} DEFAULT channel_noreset;
+
+METHOD int resetdone {
+ kobj_t obj;
+ void *data;
+} DEFAULT channel_noresetdone;
+
+METHOD int setdir {
+ kobj_t obj;
+ void *data;
+ int dir;
+} DEFAULT channel_nosetdir;
+
+METHOD u_int32_t setformat {
+ kobj_t obj;
+ void *data;
+ u_int32_t format;
+};
+
+METHOD u_int32_t setspeed {
+ kobj_t obj;
+ void *data;
+ u_int32_t speed;
+};
+
+METHOD u_int32_t setblocksize {
+ kobj_t obj;
+ void *data;
+ u_int32_t blocksize;
+};
+
+METHOD int trigger {
+ kobj_t obj;
+ void *data;
+ int go;
+};
+
+METHOD u_int32_t getptr {
+ kobj_t obj;
+ void *data;
+};
+
+METHOD pcmchan_caps* getcaps {
+ kobj_t obj;
+ void *data;
+};
+
diff --git a/sys/dev/sound/pcm/datatypes.h b/sys/dev/sound/pcm/datatypes.h
index 6b4c01b..aaa17a3 100644
--- a/sys/dev/sound/pcm/datatypes.h
+++ b/sys/dev/sound/pcm/datatypes.h
@@ -33,20 +33,11 @@ typedef struct _pcmchan_caps pcmchan_caps;
typedef struct _pcm_feeder pcm_feeder;
typedef struct _pcm_channel pcm_channel;
-typedef int (mix_set_t)(snd_mixer *m, unsigned dev, unsigned left, unsigned right);
-typedef int (mix_recsrc_t)(snd_mixer *m, u_int32_t src);
-typedef int (mix_init_t)(snd_mixer *m);
-typedef int (mix_uninit_t)(snd_mixer *m);
-typedef int (mix_reinit_t)(snd_mixer *m);
+/*****************************************************************************/
struct _snd_mixer {
- char name[64];
- mix_init_t *init;
- mix_uninit_t *uninit;
- mix_uninit_t *reinit;
- mix_set_t *set;
- mix_recsrc_t *setrecsrc;
-
+ KOBJ_FIELDS;
+ const char *name;
void *devinfo;
int busy;
u_int32_t devs;
@@ -55,6 +46,8 @@ struct _snd_mixer {
u_int16_t level[32];
};
+/*****************************************************************************/
+
/*
* descriptor of a dma buffer. See dmabuf.c for documentation.
* (rp,rl) and (fp,fl) identify the READY and FREE regions of the
@@ -79,11 +72,7 @@ struct _snd_dbuf {
struct selinfo sel;
};
-typedef int (pcmfeed_init_t)(pcm_feeder *feeder);
-typedef int (pcmfeed_free_t)(pcm_feeder *feeder);
-typedef int (pcmfeed_feed_t)(pcm_feeder *feeder, pcm_channel *c, u_int8_t *buffer,
- u_int32_t count, struct uio *stream);
-typedef int (pcmfeed_set_t)(pcm_feeder *feeder, int what, int value);
+/*****************************************************************************/
struct pcm_feederdesc {
u_int32_t type;
@@ -93,55 +82,25 @@ struct pcm_feederdesc {
};
struct _pcm_feeder {
- char name[16];
+ KOBJ_FIELDS;
int align;
struct pcm_feederdesc *desc;
- pcmfeed_init_t *init;
- pcmfeed_free_t *free;
- pcmfeed_set_t *set;
- pcmfeed_feed_t *feed;
void *data;
pcm_feeder *source;
};
+/*****************************************************************************/
+
struct _pcmchan_caps {
u_int32_t minspeed, maxspeed;
u_int32_t *fmtlist;
u_int32_t caps;
};
-typedef void *(pcmchan_init_t)(void *devinfo, snd_dbuf *b, pcm_channel *c, int dir);
-typedef int (pcmchan_setdir_t)(void *data, int dir);
-typedef int (pcmchan_setformat_t)(void *data, u_int32_t format);
-typedef int (pcmchan_setspeed_t)(void *data, u_int32_t speed);
-typedef int (pcmchan_setblocksize_t)(void *data, u_int32_t blocksize);
-typedef int (pcmchan_trigger_t)(void *data, int go);
-typedef int (pcmchan_getptr_t)(void *data);
-typedef int (pcmchan_free_t)(void *data);
-typedef pcmchan_caps *(pcmchan_getcaps_t)(void *data);
-typedef int (pcmchan_reset_t)(void *data);
-typedef int (pcmchan_resetdone_t)(void *data);
-
struct _pcm_channel {
- pcmchan_init_t *init;
- pcmchan_setdir_t *setdir;
- pcmchan_setformat_t *setformat;
- pcmchan_setspeed_t *setspeed;
- pcmchan_setblocksize_t *setblocksize;
- pcmchan_trigger_t *trigger;
- pcmchan_getptr_t *getptr;
- pcmchan_getcaps_t *getcaps;
- pcmchan_free_t *free;
- pcmchan_reset_t *reset;
- pcmchan_resetdone_t *resetdone;
- void *nop3;
- void *nop4;
- void *nop5;
- void *nop6;
- void *nop7;
+ kobj_t methods;
pcm_feeder *feeder;
- struct pcm_feederdesc *feederdesc;
u_int32_t align;
int volume;
@@ -157,24 +116,26 @@ struct _pcm_channel {
void *devinfo;
};
-typedef void (pcm_swap_t)(void *data, int dir);
+/*****************************************************************************/
+
#define SND_STATUSLEN 64
/* descriptor of audio device */
struct _snddev_info {
pcm_channel *play, *rec, **aplay, **arec, fakechan;
int *ref;
unsigned playcount, reccount, chancount, maxchans;
- snd_mixer mixer;
+ snd_mixer *mixer;
u_long magic;
unsigned flags;
void *devinfo;
- pcm_swap_t *swap;
device_t dev;
char status[SND_STATUSLEN];
};
+/*****************************************************************************/
+
/* mixer description structure and macros - these should go away,
- * only sb.[ch] and mss.[ch] use them
+ * only mss.[ch] use them
*/
struct mixer_def {
u_int regno:7;
diff --git a/sys/dev/sound/pcm/dsp.c b/sys/dev/sound/pcm/dsp.c
index b3f5c29..59c14e9 100644
--- a/sys/dev/sound/pcm/dsp.c
+++ b/sys/dev/sound/pcm/dsp.c
@@ -72,7 +72,6 @@ setchns(snddev_info *d, int chan)
KASSERT((d->flags & SD_F_PRIO_SET) != SD_F_PRIO_SET, \
("getchns: read and write both prioritised"));
d->flags |= SD_F_DIR_SET;
- if (d->swap) d->swap(d->devinfo, (d->flags & SD_F_PRIO_WR)? PCMDIR_PLAY : PCMDIR_REC);
}
int
@@ -288,7 +287,7 @@ dsp_ioctl(snddev_info *d, int chan, u_long cmd, caddr_t arg)
if (rdch && wrch)
p->formats |= (d->flags & SD_F_SIMPLEX)? 0 : AFMT_FULLDUPLEX;
p->mixers = 1; /* default: one mixer */
- p->inputs = d->mixer.devs;
+ p->inputs = d->mixer->devs;
p->left = p->right = 100;
}
break;
@@ -417,7 +416,7 @@ dsp_ioctl(snddev_info *d, int chan, u_long cmd, caddr_t arg)
if (rdch && ret == 0)
ret = chn_setformat(rdch, (*arg_i) | (rdch->format & AFMT_STEREO));
}
- *arg_i = (wrch? wrch->format: rdch->format) & ~AFMT_STEREO;
+ *arg_i = (wrch? wrch->format : rdch->format) & ~AFMT_STEREO;
break;
case SNDCTL_DSP_SUBDIVIDE:
diff --git a/sys/dev/sound/pcm/fake.c b/sys/dev/sound/pcm/fake.c
index 9cdb1f6..28ae84a 100644
--- a/sys/dev/sound/pcm/fake.c
+++ b/sys/dev/sound/pcm/fake.c
@@ -28,16 +28,6 @@
#include <dev/sound/pcm/sound.h>
-/* channel interface */
-static void *fkchan_init(void *devinfo, snd_dbuf *b, pcm_channel *c, int dir);
-static int fkchan_setdir(void *data, int dir);
-static int fkchan_setformat(void *data, u_int32_t format);
-static int fkchan_setspeed(void *data, u_int32_t speed);
-static int fkchan_setblocksize(void *data, u_int32_t blocksize);
-static int fkchan_trigger(void *data, int go);
-static int fkchan_getptr(void *data);
-static pcmchan_caps *fkchan_getcaps(void *data);
-
static u_int32_t fk_fmt[] = {
AFMT_U8,
AFMT_STEREO | AFMT_U8,
@@ -53,22 +43,11 @@ static u_int32_t fk_fmt[] = {
AFMT_STEREO | AFMT_U16_BE,
0
};
-static pcmchan_caps fk_caps = {4000, 48000, fk_fmt, 0};
-
-static pcm_channel fk_chantemplate = {
- fkchan_init,
- fkchan_setdir,
- fkchan_setformat,
- fkchan_setspeed,
- fkchan_setblocksize,
- fkchan_trigger,
- fkchan_getptr,
- fkchan_getcaps,
-};
+static pcmchan_caps fk_caps = {0, 1000000, fk_fmt, 0};
/* channel interface */
static void *
-fkchan_init(void *devinfo, snd_dbuf *b, pcm_channel *c, int dir)
+fkchan_init(kobj_t obj, void *devinfo, snd_dbuf *b, pcm_channel *c, int dir)
{
b->bufsize = 16384;
b->buf = malloc(b->bufsize, M_DEVBUF, M_NOWAIT);
@@ -76,50 +55,66 @@ fkchan_init(void *devinfo, snd_dbuf *b, pcm_channel *c, int dir)
}
static int
-fkchan_setdir(void *data, int dir)
-{
- return 0;
-}
-
-static int
-fkchan_setformat(void *data, u_int32_t format)
+fkchan_setformat(kobj_t obj, void *data, u_int32_t format)
{
return 0;
}
static int
-fkchan_setspeed(void *data, u_int32_t speed)
+fkchan_setspeed(kobj_t obj, void *data, u_int32_t speed)
{
return speed;
}
static int
-fkchan_setblocksize(void *data, u_int32_t blocksize)
+fkchan_setblocksize(kobj_t obj, void *data, u_int32_t blocksize)
{
return blocksize;
}
static int
-fkchan_trigger(void *data, int go)
+fkchan_trigger(kobj_t obj, void *data, int go)
{
return 0;
}
static int
-fkchan_getptr(void *data)
+fkchan_getptr(kobj_t obj, void *data)
{
return 0;
}
static pcmchan_caps *
-fkchan_getcaps(void *data)
+fkchan_getcaps(kobj_t obj, void *data)
{
return &fk_caps;
}
+static kobj_method_t fkchan_methods[] = {
+ KOBJMETHOD(channel_init, fkchan_init),
+ KOBJMETHOD(channel_setformat, fkchan_setformat),
+ KOBJMETHOD(channel_setspeed, fkchan_setspeed),
+ KOBJMETHOD(channel_setblocksize, fkchan_setblocksize),
+ KOBJMETHOD(channel_trigger, fkchan_trigger),
+ KOBJMETHOD(channel_getptr, fkchan_getptr),
+ KOBJMETHOD(channel_getcaps, fkchan_getcaps),
+ { 0, 0 }
+};
+CHANNEL_DECLARE(fkchan);
+
int
fkchan_setup(pcm_channel *c)
{
- *c = fk_chantemplate;
+ c->methods = kobj_create(&fkchan_class, M_DEVBUF, M_WAITOK);
return 0;
}
+
+int
+fkchan_kill(pcm_channel *c)
+{
+ kobj_delete(c->methods, M_DEVBUF);
+ c->methods = NULL;
+ return 0;
+}
+
+
diff --git a/sys/dev/sound/pcm/feeder.c b/sys/dev/sound/pcm/feeder.c
index c10d62e..5853770 100644
--- a/sys/dev/sound/pcm/feeder.c
+++ b/sys/dev/sound/pcm/feeder.c
@@ -28,12 +28,16 @@
#include <dev/sound/pcm/sound.h>
+#include "feeder_if.h"
+
+MALLOC_DEFINE(M_FEEDER, "feeder", "pcm feeder");
+
#define MAXFEEDERS 256
#undef FEEDER_DEBUG
struct feedertab_entry {
SLIST_ENTRY(feedertab_entry) link;
- pcm_feeder *feeder;
+ struct feeder_class *feederclass;
struct pcm_feederdesc *desc;
int idx;
@@ -45,17 +49,17 @@ static SLIST_HEAD(, feedertab_entry) feedertab;
void
feeder_register(void *p)
{
- pcm_feeder *f = p;
+ struct feeder_class *fc = p;
struct feedertab_entry *fte;
static int feedercnt = 0;
int i;
if (feedercnt == 0) {
- if (f->desc)
- panic("FIRST FEEDER NOT ROOT: %s\n", f->name);
+ if (fc->desc)
+ panic("FIRST FEEDER NOT ROOT: %s\n", fc->name);
SLIST_INIT(&feedertab);
- fte = malloc(sizeof(*fte), M_DEVBUF, M_NOWAIT);
- fte->feeder = f;
+ fte = malloc(sizeof(*fte), M_FEEDER, M_WAITOK | M_ZERO);
+ fte->feederclass = fc;
fte->desc = NULL;
fte->idx = feedercnt;
SLIST_INSERT_HEAD(&feedertab, fte, link);
@@ -65,10 +69,10 @@ feeder_register(void *p)
/* printf("installing feeder: %s\n", f->name); */
i = 0;
- while ((feedercnt < MAXFEEDERS) && (f->desc[i].type > 0)) {
- fte = malloc(sizeof(*fte), M_DEVBUF, M_NOWAIT);
- fte->feeder = f;
- fte->desc = &f->desc[i];
+ while ((feedercnt < MAXFEEDERS) && (fc->desc[i].type > 0)) {
+ fte = malloc(sizeof(*fte), M_FEEDER, M_WAITOK | M_ZERO);
+ fte->feederclass = fc;
+ fte->desc = &fc->desc[i];
fte->idx = feedercnt;
fte->desc->idx = feedercnt;
SLIST_INSERT_HEAD(&feedertab, fte, link);
@@ -88,53 +92,67 @@ cmpdesc(struct pcm_feederdesc *n, struct pcm_feederdesc *m)
(n->flags == m->flags));
}
-pcm_feeder *
-feeder_get(struct pcm_feederdesc *desc)
+static void
+feeder_destroy(pcm_feeder *f)
{
- struct feedertab_entry *fte;
+ FEEDER_FREE(f);
+ free(f->desc, M_FEEDER);
+ kobj_delete((kobj_t)f, M_FEEDER);
+}
- SLIST_FOREACH(fte, &feedertab, link) {
- if ((fte->desc != NULL) && cmpdesc(desc, fte->desc))
- return fte->feeder;
+static pcm_feeder *
+feeder_create(struct feeder_class *fc, struct pcm_feederdesc *desc)
+{
+ pcm_feeder *f;
+ int err;
+
+ f = (pcm_feeder *)kobj_create((kobj_class_t)fc, M_FEEDER, M_WAITOK | M_ZERO);
+ f->align = fc->align;
+ f->desc = malloc(sizeof(*(f->desc)), M_FEEDER, M_WAITOK | M_ZERO);
+ if (desc)
+ *(f->desc) = *desc;
+ else {
+ f->desc->type = FEEDER_ROOT;
+ f->desc->in = 0;
+ f->desc->out = 0;
+ f->desc->flags = 0;
+ f->desc->idx = 0;
}
- return NULL;
+ f->data = fc->data;
+ f->source = NULL;
+ err = FEEDER_INIT(f);
+ if (err) {
+ feeder_destroy(f);
+ return NULL;
+ } else
+ return f;
}
-pcm_feeder *
-feeder_getroot()
+struct feeder_class *
+feeder_getclass(struct pcm_feederdesc *desc)
{
struct feedertab_entry *fte;
SLIST_FOREACH(fte, &feedertab, link) {
- if (fte->desc == NULL)
- return fte->feeder;
+ if ((desc == NULL) && (fte->desc == NULL))
+ return fte->feederclass;
+ if ((fte->desc != NULL) && (desc != NULL) && cmpdesc(desc, fte->desc))
+ return fte->feederclass;
}
return NULL;
}
int
-feeder_set(pcm_feeder *feeder, int what, int value)
-{
- if (feeder->set)
- return feeder->set(feeder, what, value);
- else
- return -1;
-}
-
-int
-chn_addfeeder(pcm_channel *c, pcm_feeder *f)
+chn_addfeeder(pcm_channel *c, struct feeder_class *fc, struct pcm_feederdesc *desc)
{
pcm_feeder *nf;
- struct pcm_feederdesc *nfdesc;
- nf = malloc(sizeof(*nf), M_DEVBUF, M_NOWAIT);
- nfdesc = malloc(sizeof(*nfdesc), M_DEVBUF, M_NOWAIT);
- *nfdesc = *(f->desc);
- *nf = *f;
- nf->desc = nfdesc;
+ nf = feeder_create(fc, desc);
+ if (nf == NULL)
+ return -1;
+
nf->source = c->feeder;
- if (nf->init)
- nf->init(nf);
+
if (nf->align > 0)
c->align += nf->align;
else if (nf->align < 0 && c->align < -nf->align)
@@ -150,14 +168,11 @@ chn_removefeeder(pcm_channel *c)
{
pcm_feeder *f;
- if (c->feeder->source == NULL)
+ if (c->feeder == NULL)
return -1;
- f = c->feeder->source;
- if (c->feeder->free)
- c->feeder->free(c->feeder);
- free(c->feeder->desc, M_DEVBUF);
- free(c->feeder, M_DEVBUF);
- c->feeder = f;
+ f = c->feeder;
+ c->feeder = c->feeder->source;
+ feeder_destroy(f);
return 0;
}
@@ -203,7 +218,7 @@ feeder_fmtchain(u_int32_t *to, pcm_feeder *source, pcm_feeder *stop, int maxdept
{
struct feedertab_entry *fte;
pcm_feeder *try, *ret;
- struct pcm_feederdesc *trydesc;
+ struct pcm_feederdesc trydesc;
/* printf("trying %s...\n", source->name); */
if (fmtvalid(source->desc->out, to)) {
@@ -214,28 +229,26 @@ feeder_fmtchain(u_int32_t *to, pcm_feeder *source, pcm_feeder *stop, int maxdept
if (maxdepth < 0)
return NULL;
- try = malloc(sizeof(*try), M_DEVBUF, M_NOWAIT);
- trydesc = malloc(sizeof(*trydesc), M_DEVBUF, M_NOWAIT);
- trydesc->type = FEEDER_FMT;
- trydesc->in = source->desc->out;
- trydesc->out = 0;
- trydesc->flags = 0;
- trydesc->idx = -1;
+ trydesc.type = FEEDER_FMT;
+ trydesc.in = source->desc->out;
+ trydesc.out = 0;
+ trydesc.flags = 0;
+ trydesc.idx = -1;
SLIST_FOREACH(fte, &feedertab, link) {
if ((fte->desc) && (fte->desc->in == source->desc->out)) {
- *try = *(fte->feeder);
+ trydesc.out = fte->desc->out;
+ trydesc.idx = fte->idx;
+ try = feeder_create(fte->feederclass, &trydesc);
+ if (try == NULL)
+ return NULL;
try->source = source;
- try->desc = trydesc;
- trydesc->out = fte->desc->out;
- trydesc->idx = fte->idx;
ret = chainok(try, stop)? feeder_fmtchain(to, try, stop, maxdepth - 1) : NULL;
if (ret != NULL)
return ret;
+ feeder_destroy(try);
}
}
- free(try, M_DEVBUF);
- free(trydesc, M_DEVBUF);
/* printf("giving up %s...\n", source->name); */
return NULL;
}
@@ -266,8 +279,6 @@ chn_fmtchain(pcm_channel *c, u_int32_t *to)
if (try->source)
printf(" -> ");
#endif
- if (try->init)
- try->init(try);
if (try->align > 0)
c->align += try->align;
else if (try->align < 0 && c->align < -try->align)
@@ -295,22 +306,27 @@ feed_root(pcm_feeder *feeder, pcm_channel *ch, u_int8_t *buffer, u_int32_t count
count = min(count, stream->uio_resid);
if (count) {
ret = uiomove(buffer, count, stream);
- KASSERT(ret == 0, ("feed_root: uiomove failed"));
+ KASSERT(ret == 0, ("feed_root: uiomove failed (%d)", ret));
}
splx(s);
return count;
}
-static pcm_feeder feeder_root = {
- "root",
- 0,
- NULL,
- NULL,
- NULL,
- NULL,
- feed_root,
+
+static kobj_method_t feeder_root_methods[] = {
+ KOBJMETHOD(feeder_feed, feed_root),
+ { 0, 0 }
+};
+static struct feeder_class feeder_root_class = {
+ name: "feeder_root",
+ methods: feeder_root_methods,
+ size: sizeof(pcm_feeder),
+ align: 0,
+ desc: NULL,
+ data: NULL,
};
-SYSINIT(feeder_root, SI_SUB_DRIVERS, SI_ORDER_FIRST, feeder_register, &feeder_root);
+SYSINIT(feeder_root, SI_SUB_DRIVERS, SI_ORDER_FIRST, feeder_register, &feeder_root_class);
+
diff --git a/sys/dev/sound/pcm/feeder.h b/sys/dev/sound/pcm/feeder.h
index 40f866c..bde1218 100644
--- a/sys/dev/sound/pcm/feeder.h
+++ b/sys/dev/sound/pcm/feeder.h
@@ -26,17 +26,31 @@
* $FreeBSD$
*/
+struct feeder_class {
+ KOBJ_CLASS_FIELDS;
+ int align;
+ struct pcm_feederdesc *desc;
+ void *data;
+};
+
void feeder_register(void *p);
-pcm_feeder *feeder_get(struct pcm_feederdesc *desc);
-pcm_feeder *feeder_getroot(void);
-int feeder_set(pcm_feeder *feeder, int what, int value);
+struct feeder_class *feeder_getclass(struct pcm_feederdesc *desc);
u_int32_t chn_fmtchain(pcm_channel *c, u_int32_t *to);
-int chn_addfeeder(pcm_channel *c, pcm_feeder *f);
+int chn_addfeeder(pcm_channel *c, struct feeder_class *fc, struct pcm_feederdesc *desc);
int chn_removefeeder(pcm_channel *c);
pcm_feeder *chn_findfeeder(pcm_channel *c, u_int32_t type);
-#define FEEDER_DECLARE(feeder) SYSINIT(feeder, SI_SUB_DRIVERS, SI_ORDER_MIDDLE, feeder_register, &feeder)
+#define FEEDER_DECLARE(feeder, palign, pdata) \
+static struct feeder_class feeder ## _class = { \
+ name: #feeder, \
+ methods: feeder ## _methods, \
+ size: sizeof(pcm_feeder), \
+ align: palign, \
+ desc: feeder ## _desc, \
+ data: pdata, \
+}; \
+SYSINIT(feeder, SI_SUB_DRIVERS, SI_ORDER_MIDDLE, feeder_register, &feeder ## _class);
#define FEEDER_ROOT 1
#define FEEDER_FMT 2
diff --git a/sys/dev/sound/pcm/feeder_fmt.c b/sys/dev/sound/pcm/feeder_fmt.c
index e056da6..739c7a5 100644
--- a/sys/dev/sound/pcm/feeder_fmt.c
+++ b/sys/dev/sound/pcm/feeder_fmt.c
@@ -28,6 +28,10 @@
#include <dev/sound/pcm/sound.h>
+#include "feeder_if.h"
+
+MALLOC_DEFINE(M_FMTFEEDER, "fmtfeed", "pcm format feeder");
+
#define FEEDBUFSZ 8192
static unsigned char ulaw_to_u8[] = {
@@ -107,7 +111,7 @@ feed_8to16le(pcm_feeder *f, pcm_channel *c, u_int8_t *b, u_int32_t count, struct
{
int i, j, k;
- k = f->source->feed(f->source, c, b, count / 2, stream);
+ k = FEEDER_FEED(f->source, c, b, count / 2, stream);
j = k - 1;
i = j * 2 + 1;
while (i > 0 && j >= 0) {
@@ -117,37 +121,33 @@ feed_8to16le(pcm_feeder *f, pcm_channel *c, u_int8_t *b, u_int32_t count, struct
return k * 2;
}
-static struct pcm_feederdesc desc_8to16le[] = {
+static struct pcm_feederdesc feeder_8to16le_desc[] = {
{FEEDER_FMT, AFMT_U8, AFMT_U16_LE, 0},
{FEEDER_FMT, AFMT_U8 | AFMT_STEREO, AFMT_U16_LE | AFMT_STEREO, 0},
{FEEDER_FMT, AFMT_S8, AFMT_S16_LE, 0},
{FEEDER_FMT, AFMT_S8 | AFMT_STEREO, AFMT_S16_LE | AFMT_STEREO, 0},
{0},
};
-static pcm_feeder feeder_8to16le = {
- "8to16le",
- 0,
- desc_8to16le,
- NULL,
- NULL,
- NULL,
- feed_8to16le,
+static kobj_method_t feeder_8to16le_methods[] = {
+ KOBJMETHOD(feeder_feed, feed_8to16le),
+ { 0, 0 }
};
-FEEDER_DECLARE(feeder_8to16le);
+FEEDER_DECLARE(feeder_8to16le, 0, NULL);
/*****************************************************************************/
static int
feed_16to8_init(pcm_feeder *f)
{
- f->data = malloc(FEEDBUFSZ, M_DEVBUF, M_NOWAIT);
- return (f->data == NULL);
+ f->data = malloc(FEEDBUFSZ, M_FMTFEEDER, M_WAITOK | M_ZERO);
+ return (f->data == NULL)? 0 : ENOMEM;
}
static int
feed_16to8_free(pcm_feeder *f)
{
- if (f->data) free(f->data, M_DEVBUF);
+ if (f->data)
+ free(f->data, M_FMTFEEDER);
f->data = NULL;
return 0;
}
@@ -158,7 +158,7 @@ feed_16leto8(pcm_feeder *f, pcm_channel *c, u_int8_t *b, u_int32_t count, struct
u_int32_t i = 0, toget = count * 2;
int j = 1, k;
- k = f->source->feed(f->source, c, f->data, min(toget, FEEDBUFSZ), stream);
+ k = FEEDER_FEED(f->source, c, f->data, min(toget, FEEDBUFSZ), stream);
while (j < k) {
b[i++] = ((u_int8_t *)f->data)[j];
j += 2;
@@ -166,30 +166,27 @@ feed_16leto8(pcm_feeder *f, pcm_channel *c, u_int8_t *b, u_int32_t count, struct
return i;
}
-static struct pcm_feederdesc desc_16leto8[] = {
+static struct pcm_feederdesc feeder_16leto8_desc[] = {
{FEEDER_FMT, AFMT_U16_LE, AFMT_U8, 0},
{FEEDER_FMT, AFMT_U16_LE | AFMT_STEREO, AFMT_U8 | AFMT_STEREO, 0},
{FEEDER_FMT, AFMT_S16_LE, AFMT_S8, 0},
{FEEDER_FMT, AFMT_S16_LE | AFMT_STEREO, AFMT_S8 | AFMT_STEREO, 0},
{0},
};
-static pcm_feeder feeder_16leto8 = {
- "16leto8",
- 1,
- desc_16leto8,
- feed_16to8_init,
- feed_16to8_free,
- NULL,
- feed_16leto8,
+static kobj_method_t feeder_16leto8_methods[] = {
+ KOBJMETHOD(feeder_init, feed_16to8_init),
+ KOBJMETHOD(feeder_free, feed_16to8_free),
+ KOBJMETHOD(feeder_feed, feed_16leto8),
+ { 0, 0 }
};
-FEEDER_DECLARE(feeder_16leto8);
+FEEDER_DECLARE(feeder_16leto8, 1, NULL);
/*****************************************************************************/
static int
feed_monotostereo8(pcm_feeder *f, pcm_channel *c, u_int8_t *b, u_int32_t count, struct uio *stream)
{
- int i, j, k = f->source->feed(f->source, c, b, count / 2, stream);
+ int i, j, k = FEEDER_FEED(f->source, c, b, count / 2, stream);
j = k - 1;
i = j * 2 + 1;
@@ -201,28 +198,23 @@ feed_monotostereo8(pcm_feeder *f, pcm_channel *c, u_int8_t *b, u_int32_t count,
return k * 2;
}
-static struct pcm_feederdesc desc_monotostereo8[] = {
+static struct pcm_feederdesc feeder_monotostereo8_desc[] = {
{FEEDER_FMT, AFMT_U8, AFMT_U8 | AFMT_STEREO, 0},
{FEEDER_FMT, AFMT_S8, AFMT_S8 | AFMT_STEREO, 0},
{0},
};
-static pcm_feeder feeder_monotostereo8 = {
- "monotostereo8",
- 0,
- desc_monotostereo8,
- NULL,
- NULL,
- NULL,
- feed_monotostereo8,
+static kobj_method_t feeder_monotostereo8_methods[] = {
+ KOBJMETHOD(feeder_feed, feed_monotostereo8),
+ { 0, 0 }
};
-FEEDER_DECLARE(feeder_monotostereo8);
+FEEDER_DECLARE(feeder_monotostereo8, 0, NULL);
/*****************************************************************************/
static int
feed_monotostereo16(pcm_feeder *f, pcm_channel *c, u_int8_t *b, u_int32_t count, struct uio *stream)
{
- int i, j, k = f->source->feed(f->source, c, b, count / 2, stream);
+ int i, j, k = FEEDER_FEED(f->source, c, b, count / 2, stream);
u_int8_t x, y;
j = k - 1;
@@ -238,37 +230,33 @@ feed_monotostereo16(pcm_feeder *f, pcm_channel *c, u_int8_t *b, u_int32_t count,
return k * 2;
}
-static struct pcm_feederdesc desc_monotostereo16[] = {
+static struct pcm_feederdesc feeder_monotostereo16_desc[] = {
{FEEDER_FMT, AFMT_U16_LE, AFMT_U16_LE | AFMT_STEREO, 0},
{FEEDER_FMT, AFMT_S16_LE, AFMT_S16_LE | AFMT_STEREO, 0},
{FEEDER_FMT, AFMT_U16_BE, AFMT_U16_BE | AFMT_STEREO, 0},
{FEEDER_FMT, AFMT_S16_BE, AFMT_S16_BE | AFMT_STEREO, 0},
{0},
};
-static pcm_feeder feeder_monotostereo16 = {
- "monotostereo16",
- 0,
- desc_monotostereo16,
- NULL,
- NULL,
- NULL,
- feed_monotostereo16,
+static kobj_method_t feeder_monotostereo16_methods[] = {
+ KOBJMETHOD(feeder_feed, feed_monotostereo16),
+ { 0, 0 }
};
-FEEDER_DECLARE(feeder_monotostereo16);
+FEEDER_DECLARE(feeder_monotostereo16, 0, NULL);
/*****************************************************************************/
static int
feed_stereotomono8_init(pcm_feeder *f)
{
- f->data = malloc(FEEDBUFSZ, M_DEVBUF, M_NOWAIT);
- return (f->data == NULL);
+ f->data = malloc(FEEDBUFSZ, M_FMTFEEDER, M_WAITOK | M_ZERO);
+ return (f->data == NULL)? 0 : ENOMEM;
}
static int
feed_stereotomono8_free(pcm_feeder *f)
{
- if (f->data) free(f->data, M_DEVBUF);
+ if (f->data)
+ free(f->data, M_FMTFEEDER);
f->data = NULL;
return 0;
}
@@ -279,7 +267,7 @@ feed_stereotomono8(pcm_feeder *f, pcm_channel *c, u_int8_t *b, u_int32_t count,
u_int32_t i = 0, toget = count * 2;
int j = 0, k;
- k = f->source->feed(f->source, c, f->data, min(toget, FEEDBUFSZ), stream);
+ k = FEEDER_FEED(f->source, c, f->data, min(toget, FEEDBUFSZ), stream);
while (j < k) {
b[i++] = ((u_int8_t *)f->data)[j];
j += 2;
@@ -287,35 +275,33 @@ feed_stereotomono8(pcm_feeder *f, pcm_channel *c, u_int8_t *b, u_int32_t count,
return i;
}
-static struct pcm_feederdesc desc_stereotomono8[] = {
+static struct pcm_feederdesc feeder_stereotomono8_desc[] = {
{FEEDER_FMT, AFMT_U8 | AFMT_STEREO, AFMT_U8, 0},
{FEEDER_FMT, AFMT_S8 | AFMT_STEREO, AFMT_S8, 0},
{0},
};
-static pcm_feeder feeder_stereotomono8 = {
- "stereotomono8",
- 1,
- desc_stereotomono8,
- feed_stereotomono8_init,
- feed_stereotomono8_free,
- NULL,
- feed_stereotomono8,
+static kobj_method_t feeder_stereotomono8_methods[] = {
+ KOBJMETHOD(feeder_init, feed_stereotomono8_init),
+ KOBJMETHOD(feeder_free, feed_stereotomono8_free),
+ KOBJMETHOD(feeder_feed, feed_stereotomono8),
+ { 0, 0 }
};
-FEEDER_DECLARE(feeder_stereotomono8);
+FEEDER_DECLARE(feeder_stereotomono8, 1, NULL);
/*****************************************************************************/
static int
feed_stereotomono16_init(pcm_feeder *f)
{
- f->data = malloc(FEEDBUFSZ, M_DEVBUF, M_NOWAIT);
- return (f->data == NULL);
+ f->data = malloc(FEEDBUFSZ, M_FMTFEEDER, M_WAITOK | M_ZERO);
+ return (f->data == NULL)? 0 : ENOMEM;
}
static int
feed_stereotomono16_free(pcm_feeder *f)
{
- if (f->data) free(f->data, M_DEVBUF);
+ if (f->data)
+ free(f->data, M_FMTFEEDER);
f->data = NULL;
return 0;
}
@@ -326,7 +312,7 @@ feed_stereotomono16(pcm_feeder *f, pcm_channel *c, u_int8_t *b, u_int32_t count,
u_int32_t i = 0, toget = count * 2;
int j = 0, k;
- k = f->source->feed(f->source, c, f->data, min(toget, FEEDBUFSZ), stream);
+ k = FEEDER_FEED(f->source, c, f->data, min(toget, FEEDBUFSZ), stream);
while (j < k) {
b[i++] = ((u_int8_t *)f->data)[j];
b[i++] = ((u_int8_t *)f->data)[j + 1];
@@ -335,23 +321,20 @@ feed_stereotomono16(pcm_feeder *f, pcm_channel *c, u_int8_t *b, u_int32_t count,
return i;
}
-static struct pcm_feederdesc desc_stereotomono16[] = {
+static struct pcm_feederdesc feeder_stereotomono16_desc[] = {
{FEEDER_FMT, AFMT_U16_LE | AFMT_STEREO, AFMT_U16_LE, 0},
{FEEDER_FMT, AFMT_S16_LE | AFMT_STEREO, AFMT_S16_LE, 0},
{FEEDER_FMT, AFMT_U16_BE | AFMT_STEREO, AFMT_U16_BE, 0},
{FEEDER_FMT, AFMT_S16_BE | AFMT_STEREO, AFMT_S16_BE, 0},
{0},
};
-static pcm_feeder feeder_stereotomono16 = {
- "stereotomono16",
- 1,
- desc_stereotomono16,
- feed_stereotomono16_init,
- feed_stereotomono16_free,
- NULL,
- feed_stereotomono16,
+static kobj_method_t feeder_stereotomono16_methods[] = {
+ KOBJMETHOD(feeder_init, feed_stereotomono16_init),
+ KOBJMETHOD(feeder_free, feed_stereotomono16_free),
+ KOBJMETHOD(feeder_feed, feed_stereotomono16),
+ { 0, 0 }
};
-FEEDER_DECLARE(feeder_stereotomono16);
+FEEDER_DECLARE(feeder_stereotomono16, 1, NULL);
/*****************************************************************************/
@@ -359,7 +342,7 @@ static int
feed_endian(pcm_feeder *f, pcm_channel *c, u_int8_t *b, u_int32_t count, struct uio *stream)
{
u_int8_t t;
- int i = 0, j = f->source->feed(f->source, c, b, count, stream);
+ int i = 0, j = FEEDER_FEED(f->source, c, b, count, stream);
while (i < j) {
t = b[i];
@@ -370,7 +353,7 @@ feed_endian(pcm_feeder *f, pcm_channel *c, u_int8_t *b, u_int32_t count, struct
return i;
}
-static struct pcm_feederdesc desc_endian[] = {
+static struct pcm_feederdesc feeder_endian_desc[] = {
{FEEDER_FMT, AFMT_U16_LE, AFMT_U16_BE, 0},
{FEEDER_FMT, AFMT_U16_LE | AFMT_STEREO, AFMT_U16_BE | AFMT_STEREO, 0},
{FEEDER_FMT, AFMT_S16_LE, AFMT_S16_BE, 0},
@@ -381,23 +364,18 @@ static struct pcm_feederdesc desc_endian[] = {
{FEEDER_FMT, AFMT_S16_BE | AFMT_STEREO, AFMT_S16_LE | AFMT_STEREO, 0},
{0},
};
-static pcm_feeder feeder_endian = {
- "endian",
- -1,
- desc_endian,
- NULL,
- NULL,
- NULL,
- feed_endian,
+static kobj_method_t feeder_endian_methods[] = {
+ KOBJMETHOD(feeder_feed, feed_endian),
+ { 0, 0 }
};
-FEEDER_DECLARE(feeder_endian);
+FEEDER_DECLARE(feeder_endian, 0, NULL);
/*****************************************************************************/
static int
feed_sign(pcm_feeder *f, pcm_channel *c, u_int8_t *b, u_int32_t count, struct uio *stream)
{
- int i = 0, j = f->source->feed(f->source, c, b, count, stream);
+ int i = 0, j = FEEDER_FEED(f->source, c, b, count, stream);
int ssz = (int)f->data, ofs = ssz - 1;
while (i < j) {
@@ -407,50 +385,38 @@ feed_sign(pcm_feeder *f, pcm_channel *c, u_int8_t *b, u_int32_t count, struct ui
return i;
}
-static struct pcm_feederdesc desc_sign8[] = {
+static struct pcm_feederdesc feeder_sign8_desc[] = {
{FEEDER_FMT, AFMT_U8, AFMT_S8, 0},
{FEEDER_FMT, AFMT_U8 | AFMT_STEREO, AFMT_S8 | AFMT_STEREO, 0},
{FEEDER_FMT, AFMT_S8, AFMT_U8, 0},
{FEEDER_FMT, AFMT_S8 | AFMT_STEREO, AFMT_U8 | AFMT_STEREO, 0},
{0},
};
-static pcm_feeder feeder_sign8 = {
- "sign8",
- 0,
- desc_sign8,
- NULL,
- NULL,
- NULL,
- feed_sign,
- (void *)1,
+static kobj_method_t feeder_sign8_methods[] = {
+ KOBJMETHOD(feeder_feed, feed_sign),
+ { 0, 0 }
};
-FEEDER_DECLARE(feeder_sign8);
+FEEDER_DECLARE(feeder_sign8, 0, (void *)1);
-static struct pcm_feederdesc desc_sign16le[] = {
+static struct pcm_feederdesc feeder_sign16le_desc[] = {
{FEEDER_FMT, AFMT_U16_LE, AFMT_S16_LE, 0},
{FEEDER_FMT, AFMT_U16_LE | AFMT_STEREO, AFMT_S16_LE | AFMT_STEREO, 0},
{FEEDER_FMT, AFMT_S16_LE, AFMT_U16_LE, 0},
{FEEDER_FMT, AFMT_S16_LE | AFMT_STEREO, AFMT_U16_LE | AFMT_STEREO, 0},
{0},
};
-static pcm_feeder feeder_sign16le = {
- "sign16le",
- -1,
- desc_sign16le,
- NULL,
- NULL,
- NULL,
- feed_sign,
- (void *)2,
+static kobj_method_t feeder_sign16le_methods[] = {
+ KOBJMETHOD(feeder_feed, feed_sign),
+ { 0, 0 }
};
-FEEDER_DECLARE(feeder_sign16le);
+FEEDER_DECLARE(feeder_sign16le, -1, (void *)2);
/*****************************************************************************/
static int
feed_table(pcm_feeder *f, pcm_channel *c, u_int8_t *b, u_int32_t count, struct uio *stream)
{
- int i = 0, j = f->source->feed(f->source, c, b, count, stream);
+ int i = 0, j = FEEDER_FEED(f->source, c, b, count, stream);
while (i < j) {
b[i] = ((u_int8_t *)f->data)[b[i]];
@@ -459,38 +425,26 @@ feed_table(pcm_feeder *f, pcm_channel *c, u_int8_t *b, u_int32_t count, struct u
return i;
}
-static struct pcm_feederdesc desc_ulawtou8[] = {
+static struct pcm_feederdesc feeder_ulawtou8_desc[] = {
{FEEDER_FMT, AFMT_MU_LAW, AFMT_U8, 0},
{FEEDER_FMT, AFMT_MU_LAW | AFMT_STEREO, AFMT_U8 | AFMT_STEREO, 0},
{0},
};
-static pcm_feeder feeder_ulawtou8 = {
- "ulawtou8",
- 0,
- desc_ulawtou8,
- NULL,
- NULL,
- NULL,
- feed_table,
- ulaw_to_u8,
+static kobj_method_t feeder_ulawtou8_methods[] = {
+ KOBJMETHOD(feeder_feed, feed_table),
+ { 0, 0 }
};
-FEEDER_DECLARE(feeder_ulawtou8);
+FEEDER_DECLARE(feeder_ulawtou8, 0, ulaw_to_u8);
-static struct pcm_feederdesc desc_u8toulaw[] = {
+static struct pcm_feederdesc feeder_u8toulaw_desc[] = {
{FEEDER_FMT, AFMT_U8, AFMT_MU_LAW, 0},
{FEEDER_FMT, AFMT_U8 | AFMT_STEREO, AFMT_MU_LAW | AFMT_STEREO, 0},
{0},
};
-static pcm_feeder feeder_u8toulaw = {
- "u8toulaw",
- 0,
- desc_u8toulaw,
- NULL,
- NULL,
- NULL,
- feed_table,
- u8_to_ulaw,
+static kobj_method_t feeder_u8toulaw_methods[] = {
+ KOBJMETHOD(feeder_feed, feed_table),
+ { 0, 0 }
};
-FEEDER_DECLARE(feeder_u8toulaw);
+FEEDER_DECLARE(feeder_u8toulaw, 0, u8_to_ulaw);
diff --git a/sys/dev/sound/pcm/feeder_if.m b/sys/dev/sound/pcm/feeder_if.m
new file mode 100644
index 0000000..d9c2c43
--- /dev/null
+++ b/sys/dev/sound/pcm/feeder_if.m
@@ -0,0 +1,71 @@
+#
+# Copyright (c) 2000 Cameron Grant <cg@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 AND CONTRIBUTORS ``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 OR CONTRIBUTORS 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$
+#
+
+#include <dev/sound/pcm/sound.h>
+
+INTERFACE feeder;
+
+CODE {
+
+ static int
+ feeder_noinit(pcm_feeder* feeder)
+ {
+ return 0;
+ }
+
+ static int
+ feeder_nofree(pcm_feeder* feeder)
+ {
+ return 0;
+ }
+
+};
+
+METHOD int init {
+ pcm_feeder* feeder;
+} DEFAULT feeder_noinit;
+
+METHOD int free {
+ pcm_feeder* feeder;
+} DEFAULT feeder_nofree;
+
+METHOD int set {
+ pcm_feeder* feeder;
+ int what;
+ int value;
+};
+
+METHOD int feed {
+ pcm_feeder* feeder;
+ pcm_channel* c;
+ u_int8_t* buffer;
+ u_int32_t count;
+ struct uio* stream;
+};
+
+
diff --git a/sys/dev/sound/pcm/mixer.c b/sys/dev/sound/pcm/mixer.c
index 47f141f..ddb161b 100644
--- a/sys/dev/sound/pcm/mixer.c
+++ b/sys/dev/sound/pcm/mixer.c
@@ -28,6 +28,10 @@
#include <dev/sound/pcm/sound.h>
+#include "mixer_if.h"
+
+MALLOC_DEFINE(M_MIXER, "mixer", "mixer");
+
static u_int16_t snd_mixerdefaults[SOUND_MIXER_NRDEVICES] = {
[SOUND_MIXER_VOLUME] = 75,
[SOUND_MIXER_BASS] = 50,
@@ -45,73 +49,144 @@ static u_int16_t snd_mixerdefaults[SOUND_MIXER_NRDEVICES] = {
};
static int
-mixer_set(snddev_info *d, unsigned dev, unsigned lev)
+mixer_set(snd_mixer *mixer, unsigned dev, unsigned lev)
{
- if (d == NULL || d->mixer.set == NULL) return -1;
- if ((dev < SOUND_MIXER_NRDEVICES) && (d->mixer.devs & (1 << dev))) {
- unsigned l = min((lev & 0x00ff), 100);
- unsigned r = min(((lev & 0xff00) >> 8), 100);
- int v = d->mixer.set(&d->mixer, dev, l, r);
- if (v >= 0) d->mixer.level[dev] = l | (r << 8);
- return 0;
- } else return -1;
+ unsigned l, r;
+ int v;
+
+ if ((dev >= SOUND_MIXER_NRDEVICES) || (0 == (mixer->devs & (1 << dev))))
+ return -1;
+
+ l = min((lev & 0x00ff), 100);
+ r = min(((lev & 0xff00) >> 8), 100);
+
+ v = MIXER_SET(mixer, dev, l, r);
+ if (v < 0)
+ return -1;
+
+ mixer->level[dev] = l | (r << 8);
+ return 0;
}
static int
-mixer_get(snddev_info *d, int dev)
+mixer_get(snd_mixer *mixer, int dev)
{
- if (d == NULL) return -1;
- if (dev < SOUND_MIXER_NRDEVICES && (d->mixer.devs & (1 << dev)))
- return d->mixer.level[dev];
+ if ((dev < SOUND_MIXER_NRDEVICES) && (mixer->devs & (1 << dev)))
+ return mixer->level[dev];
else return -1;
}
static int
-mixer_setrecsrc(snddev_info *d, u_int32_t src)
+mixer_setrecsrc(snd_mixer *mixer, u_int32_t src)
{
- if (d == NULL || d->mixer.setrecsrc == NULL) return -1;
- src &= d->mixer.recdevs;
- if (src == 0) src = SOUND_MASK_MIC;
- d->mixer.recsrc = d->mixer.setrecsrc(&d->mixer, src);
+ src &= mixer->recdevs;
+ if (src == 0)
+ src = SOUND_MASK_MIC;
+ mixer->recsrc = MIXER_SETRECSRC(mixer, src);
return 0;
}
static int
-mixer_getrecsrc(snddev_info *d)
+mixer_getrecsrc(snd_mixer *mixer)
+{
+ return mixer->recsrc;
+}
+
+void
+mix_setdevs(snd_mixer *m, u_int32_t v)
+{
+ m->devs = v;
+}
+
+void
+mix_setrecdevs(snd_mixer *m, u_int32_t v)
+{
+ m->recdevs = v;
+}
+
+u_int32_t
+mix_getdevs(snd_mixer *m)
+{
+ return m->devs;
+}
+
+u_int32_t
+mix_getrecdevs(snd_mixer *m)
+{
+ return m->recdevs;
+}
+
+void *
+mix_getdevinfo(snd_mixer *m)
{
- if (d == NULL) return -1;
- return d->mixer.recsrc;
+ return m->devinfo;
}
int
-mixer_init(device_t dev, snd_mixer *m, void *devinfo)
-{
- snddev_info *d = device_get_softc(dev);
- if (d == NULL) return -1;
- d->mixer = *m;
- d->mixer.devinfo = devinfo;
- bzero(&d->mixer.level, sizeof d->mixer.level);
- if (d->mixer.init != NULL && d->mixer.init(&d->mixer) == 0) {
- int i;
- for (i = 0; i < SOUND_MIXER_NRDEVICES; i++) {
- u_int16_t v = snd_mixerdefaults[i];
- mixer_set(d, i, v | (v << 8));
- }
- mixer_setrecsrc(d, SOUND_MASK_MIC);
- return 0;
- } else return -1;
+mixer_busy(snd_mixer *m, int busy)
+{
+ m->busy = busy;
+ return 0;
+}
+
+int
+mixer_isbusy(snd_mixer *m)
+{
+ return m->busy;
+}
+
+int
+mixer_init(device_t dev, kobj_class_t cls, void *devinfo)
+{
+ snddev_info *d;
+ snd_mixer *m;
+ u_int16_t v;
+ int i;
+
+ d = device_get_softc(dev);
+ m = (snd_mixer *)kobj_create(cls, M_MIXER, M_WAITOK | M_ZERO);
+
+ m->name = cls->name;
+ m->devinfo = devinfo;
+
+ if (MIXER_INIT(m))
+ goto bad;
+
+ for (i = 0; i < SOUND_MIXER_NRDEVICES; i++) {
+ v = snd_mixerdefaults[i];
+ mixer_set(m, i, v | (v << 8));
+ }
+
+ mixer_setrecsrc(m, SOUND_MASK_MIC);
+
+ d->mixer = m;
+
+ return 0;
+
+bad: kobj_delete((kobj_t)m, M_MIXER);
+ return -1;
}
int
mixer_uninit(device_t dev)
{
int i;
- snddev_info *d = device_get_softc(dev);
- if (d == NULL) return -1;
+ snddev_info *d;
+ snd_mixer *m;
+
+ d = device_get_softc(dev);
+ m = d->mixer;
+
for (i = 0; i < SOUND_MIXER_NRDEVICES; i++)
- mixer_set(d, i, 0);
- mixer_setrecsrc(d, SOUND_MASK_MIC);
- if (d->mixer.uninit != NULL) d->mixer.uninit(&d->mixer);
+ mixer_set(m, i, 0);
+
+ mixer_setrecsrc(m, SOUND_MASK_MIC);
+
+ MIXER_UNINIT(m);
+
+ kobj_delete((kobj_t)m, M_MIXER);
+ d->mixer = NULL;
+
return 0;
}
@@ -119,20 +194,21 @@ int
mixer_reinit(device_t dev)
{
int i;
- snddev_info *d = device_get_softc(dev);
- if (d == NULL) return -1;
-
- if (d->mixer.reinit != NULL)
- i = d->mixer.reinit(&d->mixer);
- else if (d->mixer.init != NULL)
- i = d->mixer.init(&d->mixer);
- else
- i = 0;
+ snddev_info *d;
+ snd_mixer *m;
+
+ d = device_get_softc(dev);
+ m = d->mixer;
+
+ i = MIXER_REINIT(m);
if (i)
return i;
+
for (i = 0; i < SOUND_MIXER_NRDEVICES; i++)
- mixer_set(d, i, d->mixer.level[i]);
- mixer_setrecsrc(d, d->mixer.recsrc);
+ mixer_set(m, i, m->level[i]);
+
+ mixer_setrecsrc(m, m->recsrc);
+
return 0;
}
@@ -140,35 +216,37 @@ int
mixer_ioctl(snddev_info *d, u_long cmd, caddr_t arg)
{
int ret, *arg_i = (int *)arg;
+ int v = -1, j = cmd & 0xff;
+ snd_mixer *m;
- if ((cmd & MIXER_WRITE(0)) == MIXER_WRITE(0)) {
- int j = cmd & 0xff;
+ m = d->mixer;
- if (j == SOUND_MIXER_RECSRC) ret = mixer_setrecsrc(d, *arg_i);
- else ret = mixer_set(d, j, *arg_i);
+ if ((cmd & MIXER_WRITE(0)) == MIXER_WRITE(0)) {
+ if (j == SOUND_MIXER_RECSRC)
+ ret = mixer_setrecsrc(m, *arg_i);
+ else
+ ret = mixer_set(m, j, *arg_i);
return (ret == 0)? 0 : ENXIO;
}
if ((cmd & MIXER_READ(0)) == MIXER_READ(0)) {
- int v = -1, j = cmd & 0xff;
-
switch (j) {
case SOUND_MIXER_DEVMASK:
case SOUND_MIXER_CAPS:
case SOUND_MIXER_STEREODEVS:
- v = d->mixer.devs;
+ v = m->devs;
break;
case SOUND_MIXER_RECMASK:
- v = d->mixer.recdevs;
+ v = m->recdevs;
break;
case SOUND_MIXER_RECSRC:
- v = mixer_getrecsrc(d);
+ v = mixer_getrecsrc(m);
break;
default:
- v = mixer_get(d, j);
+ v = mixer_get(m, j);
}
*arg_i = v;
return (v != -1)? 0 : ENXIO;
@@ -176,51 +254,6 @@ mixer_ioctl(snddev_info *d, u_long cmd, caddr_t arg)
return ENXIO;
}
-int
-mixer_busy(snddev_info *d, int busy)
-{
- if (d == NULL) return -1;
- d->mixer.busy = busy;
- return 0;
-}
-
-int
-mixer_isbusy(snddev_info *d)
-{
- if (d == NULL) return -1;
- return d->mixer.busy;
-}
-
-void
-mix_setdevs(snd_mixer *m, u_int32_t v)
-{
- m->devs = v;
-}
-
-void
-mix_setrecdevs(snd_mixer *m, u_int32_t v)
-{
- m->recdevs = v;
-}
-
-u_int32_t
-mix_getdevs(snd_mixer *m)
-{
- return m->devs;
-}
-
-u_int32_t
-mix_getrecdevs(snd_mixer *m)
-{
- return m->recdevs;
-}
-
-void *
-mix_getdevinfo(snd_mixer *m)
-{
- return m->devinfo;
-}
-
/*
* The various mixers use a variety of bitmasks etc. The Voxware
* driver had a very nice technique to describe a mixer and interface
diff --git a/sys/dev/sound/pcm/mixer.h b/sys/dev/sound/pcm/mixer.h
index eb1946b..08824fc 100644
--- a/sys/dev/sound/pcm/mixer.h
+++ b/sys/dev/sound/pcm/mixer.h
@@ -26,12 +26,12 @@
* $FreeBSD$
*/
-extern int mixer_init(device_t dev, snd_mixer *m, void *devinfo);
+extern int mixer_init(device_t dev, kobj_class_t cls, void *devinfo);
extern int mixer_uninit(device_t dev);
extern int mixer_reinit(device_t dev);
extern int mixer_ioctl(snddev_info *d, u_long cmd, caddr_t arg);
-extern int mixer_busy(snddev_info *d, int busy);
-extern int mixer_isbusy(snddev_info *d);
+extern int mixer_busy(snd_mixer *m, int busy);
+extern int mixer_isbusy(snd_mixer *m);
extern void change_bits(mixer_tab *t, u_char *regval, int dev, int chn, int newval);
@@ -40,3 +40,5 @@ void mix_setrecdevs(snd_mixer *m, u_int32_t v);
u_int32_t mix_getdevs(snd_mixer *m);
u_int32_t mix_getrecdevs(snd_mixer *m);
void *mix_getdevinfo(snd_mixer *m);
+
+#define MIXER_DECLARE(name) DEFINE_CLASS(name, name ## _methods, sizeof(snd_mixer))
diff --git a/sys/dev/sound/pcm/mixer_if.m b/sys/dev/sound/pcm/mixer_if.m
new file mode 100644
index 0000000..acc1c20
--- /dev/null
+++ b/sys/dev/sound/pcm/mixer_if.m
@@ -0,0 +1,68 @@
+#
+# Copyright (c) 2000 Cameron Grant <cg@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 AND CONTRIBUTORS ``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 OR CONTRIBUTORS 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$
+#
+
+#include <dev/sound/pcm/sound.h>
+
+INTERFACE mixer;
+
+CODE {
+
+ static int
+ mixer_noreinit(snd_mixer *m)
+ {
+ return 0;
+ }
+
+};
+
+METHOD int init {
+ snd_mixer *m;
+};
+
+METHOD int reinit {
+ snd_mixer *m;
+} DEFAULT mixer_noreinit;
+
+METHOD int uninit {
+ snd_mixer *m;
+};
+
+METHOD int set {
+ snd_mixer *m;
+ unsigned dev;
+ unsigned left;
+ unsigned right;
+};
+
+METHOD u_int32_t setrecsrc {
+ snd_mixer *m;
+ u_int32_t src
+};
+
+
+
diff --git a/sys/dev/sound/pcm/sound.c b/sys/dev/sound/pcm/sound.c
index 0458cd7..0aecfb0 100644
--- a/sys/dev/sound/pcm/sound.c
+++ b/sys/dev/sound/pcm/sound.c
@@ -149,12 +149,13 @@ SYSCTL_PROC(_hw, OID_AUTO, sndunit, CTLTYPE_INT | CTLFLAG_RW,
0, sizeof(int), sysctl_hw_sndunit, "I", "");
int
-pcm_addchan(device_t dev, int dir, pcm_channel *templ, void *devinfo)
+pcm_addchan(device_t dev, int dir, kobj_class_t cls, void *devinfo)
{
int unit = device_get_unit(dev), idx;
snddev_info *d = device_get_softc(dev);
pcm_channel *chns, *ch;
char *dirs;
+ int err;
dirs = ((dir == PCMDIR_PLAY)? "play" : "record");
chns = ((dir == PCMDIR_PLAY)? d->play : d->rec);
@@ -165,10 +166,11 @@ pcm_addchan(device_t dev, int dir, pcm_channel *templ, void *devinfo)
return 1;
}
ch = &chns[idx];
- *ch = *templ;
+ ch->methods = kobj_create(cls, M_DEVBUF, M_WAITOK);
ch->parent = d;
- if (chn_init(ch, devinfo, dir)) {
- device_printf(dev, "chn_init() for (%s:%d) failed\n", dirs, idx);
+ err = chn_init(ch, devinfo, dir);
+ if (err) {
+ device_printf(dev, "chn_init() for (%s:%d) failed: err = %d\n", dirs, idx, err);
return 1;
}
make_dev(&snd_cdevsw, PCMMKMINOR(unit, SND_DEV_DSP, d->chancount),
@@ -206,6 +208,8 @@ pcm_killchan(device_t dev, int dir)
device_printf(dev, "chn_kill() for (%s:%d) failed\n", dirs, idx);
return 1;
}
+ kobj_delete(ch->methods, M_DEVBUF);
+ ch->methods = NULL;
d->chancount--;
pdev = makedev(CDEV_MAJOR, PCMMKMINOR(unit, SND_DEV_DSP, d->chancount));
destroy_dev(pdev);
@@ -245,13 +249,6 @@ pcm_getdevinfo(device_t dev)
return d->devinfo;
}
-void
-pcm_setswap(device_t dev, pcm_swap_t *swap)
-{
- snddev_info *d = device_get_softc(dev);
- d->swap = swap;
-}
-
/* This is the generic init routine */
int
pcm_register(device_t dev, void *devinfo, int numplay, int numrec)
@@ -309,7 +306,6 @@ pcm_register(device_t dev, void *devinfo, int numplay, int numrec)
fkchan_setup(&d->fakechan);
chn_init(&d->fakechan, NULL, 0);
d->magic = MAGIC(unit); /* debugging... */
- d->swap = NULL;
return 0;
no:
@@ -335,7 +331,7 @@ pcm_unregister(device_t dev)
device_printf(dev, "unregister: channel busy");
return r;
}
- if (mixer_isbusy(d)) {
+ if (mixer_isbusy(d->mixer)) {
device_printf(dev, "unregister: mixer busy");
return EBUSY;
}
@@ -356,6 +352,7 @@ pcm_unregister(device_t dev)
if (d->rec) free(d->rec, M_DEVBUF);
if (d->ref) free(d->ref, M_DEVBUF);
+ fkchan_kill(&d->fakechan);
pcm_makelinks(NULL);
return 0;
}
@@ -417,7 +414,7 @@ sndopen(dev_t i_dev, int flags, int mode, struct proc *p)
return 0;
case SND_DEV_CTL:
- return d? mixer_busy(d, 1) : ENXIO;
+ return d? mixer_busy(d->mixer, 1) : ENXIO;
case SND_DEV_AUDIO:
case SND_DEV_DSP:
@@ -445,7 +442,7 @@ sndclose(dev_t i_dev, int flags, int mode, struct proc *p)
return 0;
case SND_DEV_CTL:
- return d? mixer_busy(d, 0) : ENXIO;
+ return d? mixer_busy(d->mixer, 0) : ENXIO;
case SND_DEV_AUDIO:
case SND_DEV_DSP:
diff --git a/sys/dev/sound/pcm/sound.h b/sys/dev/sound/pcm/sound.h
index b5745c6..01cdb93 100644
--- a/sys/dev/sound/pcm/sound.h
+++ b/sys/dev/sound/pcm/sound.h
@@ -119,6 +119,7 @@ struct isa_device { int dummy; };
#define AFMT_BIGENDIAN (AFMT_S16_BE | AFMT_U16_BE)
int fkchan_setup(pcm_channel *c);
+int fkchan_kill(pcm_channel *c);
/*
* Minor numbers for the sound driver.
@@ -161,14 +162,13 @@ int fkchan_setup(pcm_channel *c);
#define DEB(x)
#endif
-int pcm_addchan(device_t dev, int dir, pcm_channel *templ, void *devinfo);
+int pcm_addchan(device_t dev, int dir, kobj_class_t cls, void *devinfo);
int pcm_register(device_t dev, void *devinfo, int numplay, int numrec);
int pcm_unregister(device_t dev);
int pcm_setstatus(device_t dev, char *str);
u_int32_t pcm_getflags(device_t dev);
void pcm_setflags(device_t dev, u_int32_t val);
void *pcm_getdevinfo(device_t dev);
-void pcm_setswap(device_t dev, pcm_swap_t *swap);
#endif /* _KERNEL */
OpenPOWER on IntegriCloud