summaryrefslogtreecommitdiffstats
path: root/sys/dev/sound/pcm/channel.c
diff options
context:
space:
mode:
Diffstat (limited to 'sys/dev/sound/pcm/channel.c')
-rw-r--r--sys/dev/sound/pcm/channel.c87
1 files changed, 45 insertions, 42 deletions
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);
OpenPOWER on IntegriCloud