diff options
author | cg <cg@FreeBSD.org> | 2001-06-26 21:54:55 +0000 |
---|---|---|
committer | cg <cg@FreeBSD.org> | 2001-06-26 21:54:55 +0000 |
commit | 773e1607789dcccaee7122556d14d6d3698355ca (patch) | |
tree | 531c0ff9e1974120e044731d59a54c9ea255ac2a /sys/dev | |
parent | aa831c7a7bf3742803e44b67cc2a0fb4aa3e26f8 (diff) | |
download | FreeBSD-src-773e1607789dcccaee7122556d14d6d3698355ca.zip FreeBSD-src-773e1607789dcccaee7122556d14d6d3698355ca.tar.gz |
add a tunable/sysctl, hw.snd.autovchans. if this is set to a value n where
n > 0, n vchans will be assigned to any devices that subsequently register
with a single playback channel.
Diffstat (limited to 'sys/dev')
-rw-r--r-- | sys/dev/sound/pcm/sound.c | 49 | ||||
-rw-r--r-- | sys/dev/sound/pcm/sound.h | 3 | ||||
-rw-r--r-- | sys/dev/sound/pcm/vchan.c | 5 |
3 files changed, 53 insertions, 4 deletions
diff --git a/sys/dev/sound/pcm/sound.c b/sys/dev/sound/pcm/sound.c index fe13d73..dff8cb9 100644 --- a/sys/dev/sound/pcm/sound.c +++ b/sys/dev/sound/pcm/sound.c @@ -37,6 +37,8 @@ devclass_t pcm_devclass; int snd_unit = 0; TUNABLE_INT("hw.snd.unit", &snd_unit); #endif +int snd_autovchans = 0; +TUNABLE_INT("hw.snd.autovchans", &snd_autovchans); SYSCTL_NODE(_hw, OID_AUTO, snd, CTLFLAG_RD, 0, "Sound driver"); @@ -157,7 +159,7 @@ pcm_chnref(struct pcm_channel *c, int ref) #ifdef USING_DEVFS static int -sysctl_hw_sndunit(SYSCTL_HANDLER_ARGS) +sysctl_hw_snd_unit(SYSCTL_HANDLER_ARGS) { struct snddev_info *d; int error, unit; @@ -175,9 +177,26 @@ sysctl_hw_sndunit(SYSCTL_HANDLER_ARGS) return (error); } SYSCTL_PROC(_hw_snd, OID_AUTO, unit, CTLTYPE_INT | CTLFLAG_RW, - 0, sizeof(int), sysctl_hw_sndunit, "I", ""); + 0, sizeof(int), sysctl_hw_snd_unit, "I", ""); #endif +static int +sysctl_hw_snd_autovchans(SYSCTL_HANDLER_ARGS) +{ + int v, error; + + v = snd_autovchans; + error = sysctl_handle_int(oidp, &v, sizeof(v), req); + if (error == 0 && req->newptr != NULL) { + if (v < 0 || v >= SND_MAXVCHANS) + return EINVAL; + snd_autovchans = v; + } + return (error); +} +SYSCTL_PROC(_hw_snd, OID_AUTO, autovchans, CTLTYPE_INT | CTLFLAG_RW, + 0, sizeof(int), sysctl_hw_snd_autovchans, "I", ""); + struct pcm_channel * pcm_chn_create(struct snddev_info *d, struct pcm_channel *parent, kobj_class_t cls, int dir, void *devinfo) { @@ -296,18 +315,36 @@ int pcm_addchan(device_t dev, int dir, kobj_class_t cls, void *devinfo) { struct snddev_info *d = device_get_softc(dev); - struct pcm_channel *ch; - int err; + struct pcm_channel *ch, *child; + struct pcmchan_children *pce; + int i, err; ch = pcm_chn_create(d, NULL, cls, dir, devinfo); if (!ch) { device_printf(d->dev, "pcm_chn_create(%s, %d, %p) failed\n", cls->name, dir, devinfo); return ENODEV; } + err = pcm_chn_add(d, ch); if (err) { device_printf(d->dev, "pcm_chn_add(%s) failed, err=%d\n", ch->name, err); pcm_chn_destroy(ch); + return err; + } + + if ((dir == PCMDIR_PLAY) && (d->flags & SD_F_AUTOVCHAN)) { + ch->flags |= CHN_F_BUSY; + for (i = 0; err == 0 && i < snd_autovchans; i++) + err = vchan_create(ch); + if (err) { + device_printf(d->dev, "vchan_create(%d) failed, err=%d\n", i - 1, err); + SLIST_FOREACH(pce, &ch->children, link) { + child = pce->channel; + vchan_destroy(child); + } + return err; + } + } return err; @@ -370,6 +407,7 @@ pcm_register(device_t dev, void *devinfo, int numplay, int numrec) d->lock = snd_mtxcreate(device_get_nameunit(dev)); snd_mtxlock(d->lock); + d->flags = 0; d->dev = dev; d->devinfo = devinfo; d->chancount = 0; @@ -393,6 +431,9 @@ pcm_register(device_t dev, void *devinfo, int numplay, int numrec) #endif if (numplay > 0) vchan_initsys(d); + if (numplay == 1) + d->flags |= SD_F_AUTOVCHAN; + snd_mtxunlock(d->lock); return 0; no: diff --git a/sys/dev/sound/pcm/sound.h b/sys/dev/sound/pcm/sound.h index b90fced..3136d7a 100644 --- a/sys/dev/sound/pcm/sound.h +++ b/sys/dev/sound/pcm/sound.h @@ -164,6 +164,7 @@ nomenclature: #define PCMMKMINOR(u, d, c) ((((c) & 0xff) << 16) | (((u) & 0x0f) << 4) | ((d) & 0x0f)) #define SD_F_SIMPLEX 0x00000001 +#define SD_F_AUTOVCHAN 0x00000002 #define SD_F_PRIO_RD 0x10000000 #define SD_F_PRIO_WR 0x20000000 #define SD_F_PRIO_SET (SD_F_PRIO_RD | SD_F_PRIO_WR) @@ -190,6 +191,8 @@ int fkchan_kill(struct pcm_channel *c); */ #define SND_CDEV_MAJOR 30 +#define SND_MAXVCHANS 255 + /* * Minor numbers for the sound driver. * diff --git a/sys/dev/sound/pcm/vchan.c b/sys/dev/sound/pcm/vchan.c index 3866ece..25e48c1 100644 --- a/sys/dev/sound/pcm/vchan.c +++ b/sys/dev/sound/pcm/vchan.c @@ -348,6 +348,11 @@ sysctl_hw_snd_vchans(SYSCTL_HANDLER_ARGS) err = sysctl_handle_int(oidp, &newcnt, sizeof(newcnt), req); if (err == 0 && req->newptr != NULL) { + if (newcnt < 0 || newcnt > SND_MAXVCHANS) { + snd_mtxunlock(d->lock); + return EINVAL; + } + if (newcnt > cnt) { /* add new vchans - find a parent channel first */ SLIST_FOREACH(sce, &d->channels, link) { |