git: ecb0a2ed2f40 - stable/14 - sound: Refactor sndstat_get_caps()
- Go to: [ bottom of page ] [ top of archives ] [ this month ]
Date: Wed, 10 Jul 2024 16:49:11 UTC
The branch stable/14 has been updated by christos: URL: https://cgit.FreeBSD.org/src/commit/?id=ecb0a2ed2f40ed51b97c17e0be5529b4183dfa32 commit ecb0a2ed2f40ed51b97c17e0be5529b4183dfa32 Author: Christos Margiolis <christos@FreeBSD.org> AuthorDate: 2024-07-06 18:23:09 +0000 Commit: Christos Margiolis <christos@FreeBSD.org> CommitDate: 2024-07-10 16:48:13 +0000 sound: Refactor sndstat_get_caps() The current implementation of sndstat_get_caps() does not work properly when VCHANs are enabled, as it skips all information about physical channels, and also assigns the min/max rates and channels to same values, which is usually not the case. A device either supports any sample rate within the [feeder_rate_min, feeder_rate_max] range, or [hw_rate_min, hw_rate_max] range when the device is opened in exclusive or bitperfect mode. The number of channels can also vary and is not always the same for both min and max. Refactor the whole function to resemble the way we handle fetching of these values in dsp_oss_audioinfo() and dsp_oss_engineinfo(). Sponsored by: The FreeBSD Foundation MFC after: 2 days Reviewed by: dev_submerge.ch Differential Revision: https://reviews.freebsd.org/D45872 (cherry picked from commit 9d8b93bc9ccea82b648ffa9354200c9e4d3f211b) --- sys/dev/sound/pcm/sndstat.c | 44 +++++++++++++++++--------------------------- 1 file changed, 17 insertions(+), 27 deletions(-) diff --git a/sys/dev/sound/pcm/sndstat.c b/sys/dev/sound/pcm/sndstat.c index 3be376e1da01..5b770810d19b 100644 --- a/sys/dev/sound/pcm/sndstat.c +++ b/sys/dev/sound/pcm/sndstat.c @@ -323,47 +323,37 @@ sndstat_write(struct cdev *i_dev, struct uio *buf, int flag) } static void -sndstat_get_caps(struct snddev_info *d, bool play, uint32_t *min_rate, +sndstat_get_caps(struct snddev_info *d, int dir, uint32_t *min_rate, uint32_t *max_rate, uint32_t *fmts, uint32_t *minchn, uint32_t *maxchn) { struct pcm_channel *c; - int dir; - - dir = play ? PCMDIR_PLAY : PCMDIR_REC; - - if (play && d->pvchancount > 0) { - *min_rate = *max_rate = d->pvchanrate; - *fmts = AFMT_ENCODING(d->pvchanformat); - *minchn = *maxchn = AFMT_CHANNEL(d->pvchanformat); - return; - } else if (!play && d->rvchancount > 0) { - *min_rate = *max_rate = d->rvchanrate; - *fmts = AFMT_ENCODING(d->rvchanformat); - *minchn = *maxchn = AFMT_CHANNEL(d->rvchanformat); - return; - } + struct pcmchan_caps *caps; + int i; *fmts = 0; *min_rate = UINT32_MAX; *max_rate = 0; *minchn = UINT32_MAX; *maxchn = 0; - CHN_FOREACH(c, d, channels.pcm) { - struct pcmchan_caps *caps; - int i; - if (c->direction != dir || (c->flags & CHN_F_VIRTUAL) != 0) + CHN_FOREACH(c, d, channels.pcm) { + if (c->direction != dir) continue; - CHN_LOCK(c); caps = chn_getcaps(c); - *min_rate = min(caps->minspeed, *min_rate); - *max_rate = max(caps->maxspeed, *max_rate); for (i = 0; caps->fmtlist[i]; i++) { *fmts |= AFMT_ENCODING(caps->fmtlist[i]); *minchn = min(AFMT_CHANNEL(caps->fmtlist[i]), *minchn); *maxchn = max(AFMT_CHANNEL(caps->fmtlist[i]), *maxchn); } + if ((c->flags & CHN_F_EXCLUSIVE) || + (pcm_getflags(d->dev) & SD_F_BITPERFECT)) { + *min_rate = min(*min_rate, caps->minspeed); + *max_rate = max(*max_rate, caps->maxspeed); + } else { + *min_rate = min(*min_rate, feeder_rate_min); + *max_rate = max(*max_rate, feeder_rate_max); + } CHN_UNLOCK(c); } if (*min_rate == UINT32_MAX) @@ -422,8 +412,8 @@ sndstat_build_sound4_nvlist(struct snddev_info *d, nvlist_t **dip) nvlist_add_number(di, SNDST_DSPS_PCHAN, d->playcount); nvlist_add_number(di, SNDST_DSPS_RCHAN, d->reccount); if (d->playcount > 0) { - sndstat_get_caps(d, true, &minrate, &maxrate, &fmts, &minchn, - &maxchn); + sndstat_get_caps(d, PCMDIR_PLAY, &minrate, &maxrate, &fmts, + &minchn, &maxchn); nvlist_add_number(di, "pminrate", minrate); nvlist_add_number(di, "pmaxrate", maxrate); nvlist_add_number(di, "pfmts", fmts); @@ -435,8 +425,8 @@ sndstat_build_sound4_nvlist(struct snddev_info *d, nvlist_t **dip) nvlist_move_nvlist(di, SNDST_DSPS_INFO_PLAY, diinfo); } if (d->reccount > 0) { - sndstat_get_caps(d, false, &minrate, &maxrate, &fmts, &minchn, - &maxchn); + sndstat_get_caps(d, PCMDIR_REC, &minrate, &maxrate, &fmts, + &minchn, &maxchn); nvlist_add_number(di, "rminrate", minrate); nvlist_add_number(di, "rmaxrate", maxrate); nvlist_add_number(di, "rfmts", fmts);