git: e4c0d796141b - stable/14 - sound: Fix vchanrate and vchanformat
- Go to: [ bottom of page ] [ top of archives ] [ this month ]
Date: Sun, 06 Apr 2025 00:28:27 UTC
The branch stable/14 has been updated by christos:
URL: https://cgit.FreeBSD.org/src/commit/?id=e4c0d796141b6611780fdff3063f744bbd49b282
commit e4c0d796141b6611780fdff3063f744bbd49b282
Author: Christos Margiolis <christos@FreeBSD.org>
AuthorDate: 2025-03-30 17:45:34 +0000
Commit: Christos Margiolis <christos@FreeBSD.org>
CommitDate: 2025-04-06 00:28:14 +0000
sound: Fix vchanrate and vchanformat
Make vchanrate and vchanformat reflect the primary channel's software
buffer's rate and format respectively. Fix previous inconsistencies.
Get rid of the initializations in vchan_create() and move them to
chn_init().
Without the feeder_rate_round check in sysctl_dev_pcm_vchanrate(), we
can set the software rate to anything between feeder_rate_min and
feeder_rate_max. If we keep the check, however, the rate is limited to
whatever the driver's min/max is, which can be a problem if, for
example, the driver supports only a single rate, in which case we won't
be able to set anything other than the driver rate.
Sponsored by: The FreeBSD Foundation
MFC after: 1 week
Differential Revision: https://reviews.freebsd.org/D48961
(cherry picked from commit e372211be5c56e218e974a4478be9aa80bfca064)
---
sys/dev/sound/pcm/channel.c | 12 +++++--
sys/dev/sound/pcm/vchan.c | 82 ++-------------------------------------------
2 files changed, 13 insertions(+), 81 deletions(-)
diff --git a/sys/dev/sound/pcm/channel.c b/sys/dev/sound/pcm/channel.c
index 287e2f07d8a1..4a96505ada66 100644
--- a/sys/dev/sound/pcm/channel.c
+++ b/sys/dev/sound/pcm/channel.c
@@ -1176,7 +1176,7 @@ chn_init(struct snddev_info *d, struct pcm_channel *parent, kobj_class_t cls,
struct feeder_class *fc;
struct snd_dbuf *b, *bs;
char buf[CHN_NAMELEN];
- int err, i, direction;
+ int err, i, direction, *vchanrate, *vchanformat;
PCM_BUSYASSERT(d);
PCM_LOCKASSERT(d);
@@ -1189,6 +1189,8 @@ chn_init(struct snddev_info *d, struct pcm_channel *parent, kobj_class_t cls,
if (dir == PCMDIR_PLAY_VIRTUAL)
d->pvchancount++;
direction = PCMDIR_PLAY;
+ vchanrate = &d->pvchanrate;
+ vchanformat = &d->pvchanformat;
break;
case PCMDIR_REC:
d->reccount++;
@@ -1197,6 +1199,8 @@ chn_init(struct snddev_info *d, struct pcm_channel *parent, kobj_class_t cls,
if (dir == PCMDIR_REC_VIRTUAL)
d->rvchancount++;
direction = PCMDIR_REC;
+ vchanrate = &d->rvchanrate;
+ vchanformat = &d->rvchanformat;
break;
default:
device_printf(d->dev,
@@ -1301,8 +1305,12 @@ chn_init(struct snddev_info *d, struct pcm_channel *parent, kobj_class_t cls,
PCM_LOCK(d);
CHN_INSERT_SORT_ASCEND(d, c, channels.pcm);
- if ((c->flags & CHN_F_VIRTUAL) == 0)
+ if ((c->flags & CHN_F_VIRTUAL) == 0) {
CHN_INSERT_SORT_ASCEND(d, c, channels.pcm.primary);
+ /* Initialize the *vchanrate/vchanformat parameters. */
+ *vchanrate = sndbuf_getspd(c->bufsoft);
+ *vchanformat = sndbuf_getfmt(c->bufsoft);
+ }
return (c);
diff --git a/sys/dev/sound/pcm/vchan.c b/sys/dev/sound/pcm/vchan.c
index 7064f1e51125..1f184f21807e 100644
--- a/sys/dev/sound/pcm/vchan.c
+++ b/sys/dev/sound/pcm/vchan.c
@@ -405,7 +405,6 @@ sysctl_dev_pcm_vchanrate(SYSCTL_HANDLER_ARGS)
{
struct snddev_info *d;
struct pcm_channel *c, *ch;
- struct pcmchan_caps *caps;
int *vchanrate, direction, ret, newspd, restart;
d = devclass_get_softc(pcm_devclass, VCHAN_SYSCTL_UNIT(oidp->oid_arg1));
@@ -467,13 +466,6 @@ sysctl_dev_pcm_vchanrate(SYSCTL_HANDLER_ARGS)
} else
restart = 0;
- if (feeder_rate_round) {
- caps = chn_getcaps(c);
- RANGE(newspd, caps->minspeed, caps->maxspeed);
- newspd = CHANNEL_SETSPEED(c->methods,
- c->devinfo, newspd);
- }
-
ret = chn_reset(c, c->format, newspd);
if (ret == 0) {
if (restart != 0) {
@@ -488,7 +480,7 @@ sysctl_dev_pcm_vchanrate(SYSCTL_HANDLER_ARGS)
}
}
}
- *vchanrate = c->speed;
+ *vchanrate = sndbuf_getspd(c->bufsoft);
CHN_UNLOCK(c);
}
@@ -583,7 +575,7 @@ sysctl_dev_pcm_vchanformat(SYSCTL_HANDLER_ARGS)
}
}
}
- *vchanformat = c->format;
+ *vchanformat = sndbuf_getfmt(c->bufsoft);
CHN_UNLOCK(c);
}
@@ -607,11 +599,9 @@ vchan_create(struct pcm_channel *parent, struct pcm_channel **child)
struct pcm_channel *ch;
struct pcmchan_caps *parent_caps;
uint32_t vchanfmt, vchanspd;
- int ret, direction, r;
- bool save;
+ int ret, direction;
ret = 0;
- save = false;
d = parent->parentsnddev;
PCM_BUSYASSERT(d);
@@ -659,75 +649,9 @@ vchan_create(struct pcm_channel *parent, struct pcm_channel **child)
goto fail;
}
- if (vchanfmt == 0) {
- const char *vfmt;
-
- CHN_UNLOCK(parent);
- r = resource_string_value(device_get_name(parent->dev),
- device_get_unit(parent->dev), VCHAN_FMT_HINT(direction),
- &vfmt);
- CHN_LOCK(parent);
- if (r != 0)
- vfmt = NULL;
- if (vfmt != NULL) {
- vchanfmt = snd_str2afmt(vfmt);
- if (vchanfmt != 0 && !(vchanfmt & AFMT_VCHAN))
- vchanfmt = 0;
- }
- if (vchanfmt == 0)
- vchanfmt = VCHAN_DEFAULT_FORMAT;
- save = true;
- }
-
- if (vchanspd == 0) {
- /*
- * This is very sad. Few soundcards advertised as being
- * able to do (insanely) higher/lower speed, but in
- * reality, they simply can't. At least, we give user chance
- * to set sane value via kernel hints or sysctl.
- */
- CHN_UNLOCK(parent);
- r = resource_int_value(device_get_name(parent->dev),
- device_get_unit(parent->dev), VCHAN_SPD_HINT(direction),
- &vchanspd);
- CHN_LOCK(parent);
- if (r != 0) {
- /* No saved value, no hint, NOTHING. */
- vchanspd = VCHAN_DEFAULT_RATE;
- RANGE(vchanspd, parent_caps->minspeed,
- parent_caps->maxspeed);
- }
- save = true;
- }
-
- /*
- * Limit the speed between feeder_rate_min <-> feeder_rate_max.
- */
- RANGE(vchanspd, feeder_rate_min, feeder_rate_max);
-
- if (feeder_rate_round) {
- RANGE(vchanspd, parent_caps->minspeed,
- parent_caps->maxspeed);
- vchanspd = CHANNEL_SETSPEED(parent->methods,
- parent->devinfo, vchanspd);
- }
-
if ((ret = chn_reset(parent, vchanfmt, vchanspd)) != 0)
goto fail;
- if (save) {
- /*
- * Save new value.
- */
- if (direction == PCMDIR_PLAY_VIRTUAL) {
- d->pvchanformat = parent->format;
- d->pvchanrate = parent->speed;
- } else {
- d->rvchanformat = parent->format;
- d->rvchanrate = parent->speed;
- }
- }
-
/*
* If the parent channel supports digital format,
* enable passthrough mode.