mirror of
https://github.com/freebsd/freebsd-src
synced 2024-07-21 10:19:04 +00:00
snd_hdspe(4): Per device sysctl for sample rate.
Some hardware setups require a specific sample rate due to devices being connected to digital ports (AES, S/PDIF, ADAT). Add a per device sysctl "sample_rate" to let the user override sample rate requests from the pcm infrastructure, when needed. Differential Revision: https://reviews.freebsd.org/D43659
This commit is contained in:
parent
0c0ec5c8cc
commit
6c892b79de
|
@ -22,7 +22,7 @@
|
|||
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
.\" SUCH DAMAGE.
|
||||
.\"
|
||||
.Dd January 19, 2024
|
||||
.Dd January 29, 2024
|
||||
.Dt SND_HDSPE 4
|
||||
.Os
|
||||
.Sh NAME
|
||||
|
@ -76,6 +76,10 @@ To adjust the following sysctl identifiers for a specific sound card, insert
|
|||
the respective device number in place of
|
||||
.Ql 0 .
|
||||
.Bl -tag -width indent
|
||||
.It Va dev.hdspe.0.sample_rate
|
||||
Set a fixed sample rate from 32000, 44100, 48000, up to 192000.
|
||||
This is usually required for digital connections (AES, S/PDIF, ADAT).
|
||||
The default value of 0 adjusts the sample rate according to pcm device settings.
|
||||
.It Va dev.hdspe.0.period
|
||||
The number of samples processed per interrupt, from 32, 64, 128, up to 4096.
|
||||
Setting a lower value here results in less latency, but increases system load
|
||||
|
|
|
@ -814,6 +814,9 @@ hdspechan_setspeed(kobj_t obj, void *data, uint32_t speed)
|
|||
if (hdspe_running(sc) == 1)
|
||||
goto end;
|
||||
|
||||
if (sc->force_speed > 0)
|
||||
speed = sc->force_speed;
|
||||
|
||||
/* First look for equal frequency. */
|
||||
for (i = 0; rate_map[i].speed != 0; i++) {
|
||||
if (rate_map[i].speed == speed)
|
||||
|
|
|
@ -228,6 +228,41 @@ hdspe_map_dmabuf(struct sc_info *sc)
|
|||
}
|
||||
}
|
||||
|
||||
static int
|
||||
hdspe_sysctl_sample_rate(SYSCTL_HANDLER_ARGS)
|
||||
{
|
||||
struct sc_info *sc = oidp->oid_arg1;
|
||||
int error;
|
||||
unsigned int speed, multiplier;
|
||||
|
||||
speed = sc->force_speed;
|
||||
|
||||
/* Process sysctl (unsigned) integer request. */
|
||||
error = sysctl_handle_int(oidp, &speed, 0, req);
|
||||
if (error != 0 || req->newptr == NULL)
|
||||
return (error);
|
||||
|
||||
/* Speed from 32000 to 192000, 0 falls back to pcm speed setting. */
|
||||
sc->force_speed = 0;
|
||||
if (speed > 0) {
|
||||
multiplier = 1;
|
||||
if (speed > (96000 + 128000) / 2)
|
||||
multiplier = 4;
|
||||
else if (speed > (48000 + 64000) / 2)
|
||||
multiplier = 2;
|
||||
|
||||
if (speed < ((32000 + 44100) / 2) * multiplier)
|
||||
sc->force_speed = 32000 * multiplier;
|
||||
else if (speed < ((44100 + 48000) / 2) * multiplier)
|
||||
sc->force_speed = 44100 * multiplier;
|
||||
else
|
||||
sc->force_speed = 48000 * multiplier;
|
||||
}
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
hdspe_sysctl_period(SYSCTL_HANDLER_ARGS)
|
||||
{
|
||||
|
@ -455,6 +490,7 @@ hdspe_init(struct sc_info *sc)
|
|||
|
||||
/* Set rate. */
|
||||
sc->speed = HDSPE_SPEED_DEFAULT;
|
||||
sc->force_speed = 0;
|
||||
sc->ctrl_register &= ~HDSPE_FREQ_MASK;
|
||||
sc->ctrl_register |= HDSPE_FREQ_MASK_DEFAULT;
|
||||
hdspe_write_4(sc, HDSPE_CONTROL_REG, sc->ctrl_register);
|
||||
|
@ -562,6 +598,12 @@ hdspe_attach(device_t dev)
|
|||
sc, 0, hdspe_sysctl_period, "A",
|
||||
"Force period of samples per interrupt (32, 64, ... 4096)");
|
||||
|
||||
SYSCTL_ADD_PROC(device_get_sysctl_ctx(dev),
|
||||
SYSCTL_CHILDREN(device_get_sysctl_tree(dev)), OID_AUTO,
|
||||
"sample_rate", CTLTYPE_UINT | CTLFLAG_RW | CTLFLAG_MPSAFE,
|
||||
sc, 0, hdspe_sysctl_sample_rate, "A",
|
||||
"Force sample rate (32000, 44100, 48000, ... 192000)");
|
||||
|
||||
return (bus_generic_attach(dev));
|
||||
}
|
||||
|
||||
|
|
|
@ -228,6 +228,7 @@ struct sc_info {
|
|||
uint32_t period;
|
||||
uint32_t speed;
|
||||
uint32_t force_period;
|
||||
uint32_t force_speed;
|
||||
};
|
||||
|
||||
#define hdspe_read_1(sc, regno) \
|
||||
|
|
Loading…
Reference in a new issue