summaryrefslogtreecommitdiff
path: root/sys/dev
diff options
context:
space:
mode:
authorAriff Abdullah <ariff@FreeBSD.org>2005-10-26 21:18:41 +0000
committerAriff Abdullah <ariff@FreeBSD.org>2005-10-26 21:18:41 +0000
commit22ff0d37bed858c18d98a96dc3036a048a04110c (patch)
tree93c79424134a2b31bd50f32a168ec80d0e64203e /sys/dev
parentf66ce35e97a3129c988b81ed0ce5f6f57465b89f (diff)
Notes
Diffstat (limited to 'sys/dev')
-rw-r--r--sys/dev/sound/pcm/vchan.c32
1 files changed, 30 insertions, 2 deletions
diff --git a/sys/dev/sound/pcm/vchan.c b/sys/dev/sound/pcm/vchan.c
index 91a114e65706..9b9e102f8f92 100644
--- a/sys/dev/sound/pcm/vchan.c
+++ b/sys/dev/sound/pcm/vchan.c
@@ -251,7 +251,8 @@ vchan_create(struct pcm_channel *parent)
struct snddev_info *d = parent->parentsnddev;
struct pcmchan_children *pce;
struct pcm_channel *child;
- int err, first;
+ struct pcmchan_caps *parent_caps;
+ int err, first, speed;
CHN_UNLOCK(parent);
@@ -295,7 +296,20 @@ vchan_create(struct pcm_channel *parent)
err = chn_reset(parent, AFMT_STEREO | AFMT_S16_LE);
if (err)
printf("chn_reset: %d\n", err);
- err = chn_setspeed(parent, 44100);
+ speed = 44100;
+ parent_caps = chn_getcaps(parent);
+ if (parent_caps != NULL) {
+ /*
+ * Limit speed based on driver caps.
+ * This is supposed to help fixed rate, non-VRA
+ * AC97 cards.
+ */
+ if (speed < parent_caps->minspeed)
+ speed = parent_caps->minspeed;
+ if (speed > parent_caps->maxspeed)
+ speed = parent_caps->maxspeed;
+ }
+ err = chn_setspeed(parent, speed);
if (err)
printf("chn_setspeed: %d\n", err);
}
@@ -309,6 +323,7 @@ vchan_destroy(struct pcm_channel *c)
struct pcm_channel *parent = c->parentchannel;
struct snddev_info *d = parent->parentsnddev;
struct pcmchan_children *pce;
+ struct snddev_channel *sce;
int err, last;
CHN_LOCK(parent);
@@ -329,6 +344,19 @@ vchan_destroy(struct pcm_channel *c)
CHN_UNLOCK(parent);
return EINVAL;
gotch:
+ SLIST_FOREACH(sce, &d->channels, link) {
+ if (sce->channel == c) {
+ if (sce->dsp_devt)
+ destroy_dev(sce->dsp_devt);
+ if (sce->dspW_devt)
+ destroy_dev(sce->dspW_devt);
+ if (sce->audio_devt)
+ destroy_dev(sce->audio_devt);
+ if (sce->dspr_devt)
+ destroy_dev(sce->dspr_devt);
+ break;
+ }
+ }
SLIST_REMOVE(&parent->children, pce, pcmchan_children, link);
free(pce, M_DEVBUF);