The branch main has been updated by christos:

URL: 
https://cgit.FreeBSD.org/src/commit/?id=e372211be5c56e218e974a4478be9aa80bfca064

commit e372211be5c56e218e974a4478be9aa80bfca064
Author:     Christos Margiolis <chris...@freebsd.org>
AuthorDate: 2025-03-30 17:45:34 +0000
Commit:     Christos Margiolis <chris...@freebsd.org>
CommitDate: 2025-03-30 17:45:34 +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
---
 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.

Reply via email to