Skip to content

Commit

Permalink
snd_hdspe(4): Optional unified pcm device.
Browse files Browse the repository at this point in the history
Add a sysctl tunable to unify all physical ports of an HDSPe sound card
into one pcm device, with up to 14 (AIO) or 36 (RayDAT) channels. This
makes all ports available in multi-channel audio software.

Differential Revision:	https://reviews.freebsd.org/D43798
  • Loading branch information
0EVSG authored and bukinr committed Feb 25, 2024
1 parent 32fdcff commit dc15f02
Show file tree
Hide file tree
Showing 3 changed files with 50 additions and 4 deletions.
23 changes: 22 additions & 1 deletion share/man/man4/snd_hdspe.4
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
.\" SUCH DAMAGE.
.\"
.Dd January 29, 2024
.Dd February 9, 2024
.Dt SND_HDSPE 4
.Os
.Sh NAME
Expand Down Expand Up @@ -64,8 +64,29 @@ By default, each
.Xr pcm 4
device corresponds to a physical port on the sound card.
For ADAT ports, 8 channel, 4 channel and 2 channel formats are supported.
The effective number of ADAT channels is 8 channels at single speed
(32kHz-48kHz), 4 channels at double speed (64kHz-96kHz), and 2 channels at
quad speed (128kHz-192kHz).
Depending on sample rate and channel format selected, not all pcm channels can
be mapped to ADAT channels and vice versa.
.Sh LOADER TUNABLES
These settings can be entered at the
.Xr loader 8
prompt or in
.Xr loader.conf 5 .
.Bl -tag -width indent
.It Va hw.hdspe.unified_pcm
If set to 1, all physical ports are combined into one unified pcm device.
When opened in multi-channel audio software, this makes all ports available
at the same time, and fully synchronized.
For resulting channel numbers consult the following table:
.El
.Bl -column "HDSPe RayDAT" "Single Speed" "Double Speed" "Quad Speed"
.Sy "Sound Card" Ta Sy "Single Speed" Ta Sy "Double Speed" Ta Sy "Quad Speed"
.It "" Ta "Play | Rec" Ta "Play | Rec" Ta "Play | Rec"
.It HDSPe AIO Ta " 16 | 14" Ta " 12 | 10" Ta " 10 | 8"
.It HDSPe RayDAT Ta " 36 | 36" Ta " 20 | 20" Ta " 12 | 12"
.El
.Sh SYSCTL TUNABLES
These settings and informational values can be accessed at runtime with the
.Xr sysctl 8
Expand Down
9 changes: 8 additions & 1 deletion sys/dev/sound/pci/hdspe-pcm.c
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,8 @@

#include <mixer_if.h>

#define HDSPE_MATRIX_MAX 8

struct hdspe_latency {
uint32_t n;
uint32_t period;
Expand Down Expand Up @@ -1007,6 +1009,7 @@ hdspe_pcm_attach(device_t dev)
char status[SND_STATUSLEN];
struct sc_pcminfo *scp;
const char *buf;
uint32_t pcm_flags;
int err;
int play, rec;

Expand All @@ -1025,7 +1028,11 @@ hdspe_pcm_attach(device_t dev)
* We don't register interrupt handler with snd_setup_intr
* in pcm device. Mark pcm device as MPSAFE manually.
*/
pcm_setflags(dev, pcm_getflags(dev) | SD_F_MPSAFE);
pcm_flags = pcm_getflags(dev) | SD_F_MPSAFE;
if (hdspe_channel_count(scp->hc->ports, 8) > HDSPE_MATRIX_MAX)
/* Disable vchan conversion, too many channels. */
pcm_flags |= SD_F_BITPERFECT;
pcm_setflags(dev, pcm_flags);

play = (hdspe_channel_play_ports(scp->hc)) ? 1 : 0;
rec = (hdspe_channel_rec_ports(scp->hc)) ? 1 : 0;
Expand Down
22 changes: 20 additions & 2 deletions sys/dev/sound/pci/hdspe.c
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,14 @@

#include <mixer_if.h>

static bool hdspe_unified_pcm = false;

static SYSCTL_NODE(_hw, OID_AUTO, hdspe, CTLFLAG_RW | CTLFLAG_MPSAFE, 0,
"PCI HDSPe");

SYSCTL_BOOL(_hw_hdspe, OID_AUTO, unified_pcm, CTLFLAG_RWTUN,
&hdspe_unified_pcm, 0, "Combine physical ports in one unified pcm device");

static struct hdspe_clock_source hdspe_clock_source_table_rd[] = {
{ "internal", 0 << 1 | 1, HDSPE_STATUS1_CLOCK(15), 0, 0 },
{ "word", 0 << 1 | 0, HDSPE_STATUS1_CLOCK( 0), 1 << 24, 1 << 25 },
Expand Down Expand Up @@ -78,6 +86,11 @@ static struct hdspe_channel chan_map_aio[] = {
{ 0, NULL },
};

static struct hdspe_channel chan_map_aio_uni[] = {
{ HDSPE_CHAN_AIO_ALL, "all" },
{ 0, NULL },
};

static struct hdspe_channel chan_map_rd[] = {
{ HDSPE_CHAN_RAY_AES, "aes" },
{ HDSPE_CHAN_RAY_SPDIF, "s/pdif" },
Expand All @@ -88,6 +101,11 @@ static struct hdspe_channel chan_map_rd[] = {
{ 0, NULL },
};

static struct hdspe_channel chan_map_rd_uni[] = {
{ HDSPE_CHAN_RAY_ALL, "all" },
{ 0, NULL },
};

static void
hdspe_intr(void *p)
{
Expand Down Expand Up @@ -538,11 +556,11 @@ hdspe_attach(device_t dev)
switch (rev) {
case PCI_REVISION_AIO:
sc->type = HDSPE_AIO;
chan_map = chan_map_aio;
chan_map = hdspe_unified_pcm ? chan_map_aio_uni : chan_map_aio;
break;
case PCI_REVISION_RAYDAT:
sc->type = HDSPE_RAYDAT;
chan_map = chan_map_rd;
chan_map = hdspe_unified_pcm ? chan_map_rd_uni : chan_map_rd;
break;
default:
return (ENXIO);
Expand Down

0 comments on commit dc15f02

Please sign in to comment.