Skip to content

Commit c34ddb3

Browse files
CyanNyanjannau
authored andcommitted
ALSA: usb-audio: Add quirk for RME Digiface USB
Add trivial support for audio streaming on the RME Digiface USB. Binds only to the first interface to allow userspace to directly drive the complex I/O and matrix mixer controls. Signed-off-by: Cyan Nyan <cyan.vtb@gmail.com> [Lina: Added 2x/4x sample rate support & boot/format quirks] Co-developed-by: Asahi Lina <lina@asahilina.net> Signed-off-by: Asahi Lina <lina@asahilina.net> Link: https://patch.msgid.link/20240903-rme-digiface-v2-1-71b06c912e97@asahilina.net Signed-off-by: Takashi Iwai <tiwai@suse.de>
1 parent d2c34a4 commit c34ddb3

2 files changed

Lines changed: 228 additions & 1 deletion

File tree

sound/usb/quirks-table.h

Lines changed: 170 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3604,6 +3604,175 @@ YAMAHA_DEVICE(0x7010, "UB99"),
36043604
}
36053605
}
36063606
},
3607-
3607+
{
3608+
/* Only claim interface 0 */
3609+
.match_flags = USB_DEVICE_ID_MATCH_VENDOR |
3610+
USB_DEVICE_ID_MATCH_PRODUCT |
3611+
USB_DEVICE_ID_MATCH_INT_CLASS |
3612+
USB_DEVICE_ID_MATCH_INT_NUMBER,
3613+
.idVendor = 0x2a39,
3614+
.idProduct = 0x3f8c,
3615+
.bInterfaceClass = USB_CLASS_VENDOR_SPEC,
3616+
.bInterfaceNumber = 0,
3617+
QUIRK_DRIVER_INFO {
3618+
QUIRK_DATA_COMPOSITE {
3619+
/*
3620+
* Three modes depending on sample rate band,
3621+
* with different channel counts for in/out
3622+
*/
3623+
{
3624+
QUIRK_DATA_AUDIOFORMAT(0) {
3625+
.formats = SNDRV_PCM_FMTBIT_S32_LE,
3626+
.channels = 34, // outputs
3627+
.fmt_bits = 24,
3628+
.iface = 0,
3629+
.altsetting = 1,
3630+
.altset_idx = 1,
3631+
.endpoint = 0x02,
3632+
.ep_idx = 1,
3633+
.ep_attr = USB_ENDPOINT_XFER_ISOC |
3634+
USB_ENDPOINT_SYNC_ASYNC,
3635+
.rates = SNDRV_PCM_RATE_32000 |
3636+
SNDRV_PCM_RATE_44100 |
3637+
SNDRV_PCM_RATE_48000,
3638+
.rate_min = 32000,
3639+
.rate_max = 48000,
3640+
.nr_rates = 3,
3641+
.rate_table = (unsigned int[]) {
3642+
32000, 44100, 48000,
3643+
},
3644+
.sync_ep = 0x81,
3645+
.sync_iface = 0,
3646+
.sync_altsetting = 1,
3647+
.sync_ep_idx = 0,
3648+
.implicit_fb = 1,
3649+
},
3650+
},
3651+
{
3652+
QUIRK_DATA_AUDIOFORMAT(0) {
3653+
.formats = SNDRV_PCM_FMTBIT_S32_LE,
3654+
.channels = 18, // outputs
3655+
.fmt_bits = 24,
3656+
.iface = 0,
3657+
.altsetting = 1,
3658+
.altset_idx = 1,
3659+
.endpoint = 0x02,
3660+
.ep_idx = 1,
3661+
.ep_attr = USB_ENDPOINT_XFER_ISOC |
3662+
USB_ENDPOINT_SYNC_ASYNC,
3663+
.rates = SNDRV_PCM_RATE_64000 |
3664+
SNDRV_PCM_RATE_88200 |
3665+
SNDRV_PCM_RATE_96000,
3666+
.rate_min = 64000,
3667+
.rate_max = 96000,
3668+
.nr_rates = 3,
3669+
.rate_table = (unsigned int[]) {
3670+
64000, 88200, 96000,
3671+
},
3672+
.sync_ep = 0x81,
3673+
.sync_iface = 0,
3674+
.sync_altsetting = 1,
3675+
.sync_ep_idx = 0,
3676+
.implicit_fb = 1,
3677+
},
3678+
},
3679+
{
3680+
QUIRK_DATA_AUDIOFORMAT(0) {
3681+
.formats = SNDRV_PCM_FMTBIT_S32_LE,
3682+
.channels = 10, // outputs
3683+
.fmt_bits = 24,
3684+
.iface = 0,
3685+
.altsetting = 1,
3686+
.altset_idx = 1,
3687+
.endpoint = 0x02,
3688+
.ep_idx = 1,
3689+
.ep_attr = USB_ENDPOINT_XFER_ISOC |
3690+
USB_ENDPOINT_SYNC_ASYNC,
3691+
.rates = SNDRV_PCM_RATE_KNOT |
3692+
SNDRV_PCM_RATE_176400 |
3693+
SNDRV_PCM_RATE_192000,
3694+
.rate_min = 128000,
3695+
.rate_max = 192000,
3696+
.nr_rates = 3,
3697+
.rate_table = (unsigned int[]) {
3698+
128000, 176400, 192000,
3699+
},
3700+
.sync_ep = 0x81,
3701+
.sync_iface = 0,
3702+
.sync_altsetting = 1,
3703+
.sync_ep_idx = 0,
3704+
.implicit_fb = 1,
3705+
},
3706+
},
3707+
{
3708+
QUIRK_DATA_AUDIOFORMAT(0) {
3709+
.formats = SNDRV_PCM_FMTBIT_S32_LE,
3710+
.channels = 32, // inputs
3711+
.fmt_bits = 24,
3712+
.iface = 0,
3713+
.altsetting = 1,
3714+
.altset_idx = 1,
3715+
.endpoint = 0x81,
3716+
.ep_attr = USB_ENDPOINT_XFER_ISOC |
3717+
USB_ENDPOINT_SYNC_ASYNC,
3718+
.rates = SNDRV_PCM_RATE_32000 |
3719+
SNDRV_PCM_RATE_44100 |
3720+
SNDRV_PCM_RATE_48000,
3721+
.rate_min = 32000,
3722+
.rate_max = 48000,
3723+
.nr_rates = 3,
3724+
.rate_table = (unsigned int[]) {
3725+
32000, 44100, 48000,
3726+
}
3727+
}
3728+
},
3729+
{
3730+
QUIRK_DATA_AUDIOFORMAT(0) {
3731+
.formats = SNDRV_PCM_FMTBIT_S32_LE,
3732+
.channels = 16, // inputs
3733+
.fmt_bits = 24,
3734+
.iface = 0,
3735+
.altsetting = 1,
3736+
.altset_idx = 1,
3737+
.endpoint = 0x81,
3738+
.ep_attr = USB_ENDPOINT_XFER_ISOC |
3739+
USB_ENDPOINT_SYNC_ASYNC,
3740+
.rates = SNDRV_PCM_RATE_64000 |
3741+
SNDRV_PCM_RATE_88200 |
3742+
SNDRV_PCM_RATE_96000,
3743+
.rate_min = 64000,
3744+
.rate_max = 96000,
3745+
.nr_rates = 3,
3746+
.rate_table = (unsigned int[]) {
3747+
64000, 88200, 96000,
3748+
}
3749+
}
3750+
},
3751+
{
3752+
QUIRK_DATA_AUDIOFORMAT(0) {
3753+
.formats = SNDRV_PCM_FMTBIT_S32_LE,
3754+
.channels = 8, // inputs
3755+
.fmt_bits = 24,
3756+
.iface = 0,
3757+
.altsetting = 1,
3758+
.altset_idx = 1,
3759+
.endpoint = 0x81,
3760+
.ep_attr = USB_ENDPOINT_XFER_ISOC |
3761+
USB_ENDPOINT_SYNC_ASYNC,
3762+
.rates = SNDRV_PCM_RATE_KNOT |
3763+
SNDRV_PCM_RATE_176400 |
3764+
SNDRV_PCM_RATE_192000,
3765+
.rate_min = 128000,
3766+
.rate_max = 192000,
3767+
.nr_rates = 3,
3768+
.rate_table = (unsigned int[]) {
3769+
128000, 176400, 192000,
3770+
}
3771+
}
3772+
},
3773+
QUIRK_COMPOSITE_END
3774+
}
3775+
}
3776+
},
36083777
#undef USB_DEVICE_VENDOR_SPEC
36093778
#undef USB_AUDIO_DEVICE

sound/usb/quirks.c

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1389,6 +1389,27 @@ static int snd_usb_motu_m_series_boot_quirk(struct usb_device *dev)
13891389
return 0;
13901390
}
13911391

1392+
static int snd_usb_rme_digiface_boot_quirk(struct usb_device *dev)
1393+
{
1394+
/* Disable mixer, internal clock, all outputs ADAT, 48kHz, TMS off */
1395+
snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
1396+
16, 0x40, 0x2410, 0x7fff, NULL, 0);
1397+
snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
1398+
18, 0x40, 0x0104, 0xffff, NULL, 0);
1399+
1400+
/* Disable loopback for all inputs */
1401+
for (int ch = 0; ch < 32; ch++)
1402+
snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
1403+
22, 0x40, 0x400, ch, NULL, 0);
1404+
1405+
/* Unity gain for all outputs */
1406+
for (int ch = 0; ch < 34; ch++)
1407+
snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
1408+
21, 0x40, 0x9000, 0x100 + ch, NULL, 0);
1409+
1410+
return 0;
1411+
}
1412+
13921413
/*
13931414
* Setup quirks
13941415
*/
@@ -1616,6 +1637,8 @@ int snd_usb_apply_boot_quirk(struct usb_device *dev,
16161637
get_iface_desc(intf->altsetting)->bInterfaceNumber < 3)
16171638
return snd_usb_motu_microbookii_boot_quirk(dev);
16181639
break;
1640+
case USB_ID(0x2a39, 0x3f8c): /* RME Digiface USB */
1641+
return snd_usb_rme_digiface_boot_quirk(dev);
16191642
}
16201643

16211644
return 0;
@@ -1771,6 +1794,38 @@ static void mbox3_set_format_quirk(struct snd_usb_substream *subs,
17711794
dev_warn(&subs->dev->dev, "MBOX3: Couldn't set the sample rate");
17721795
}
17731796

1797+
static const int rme_digiface_rate_table[] = {
1798+
32000, 44100, 48000, 0,
1799+
64000, 88200, 96000, 0,
1800+
128000, 176400, 192000, 0,
1801+
};
1802+
1803+
static int rme_digiface_set_format_quirk(struct snd_usb_substream *subs)
1804+
{
1805+
unsigned int cur_rate = subs->data_endpoint->cur_rate;
1806+
u16 val;
1807+
int speed_mode;
1808+
int id;
1809+
1810+
for (id = 0; id < ARRAY_SIZE(rme_digiface_rate_table); id++) {
1811+
if (rme_digiface_rate_table[id] == cur_rate)
1812+
break;
1813+
}
1814+
1815+
if (id >= ARRAY_SIZE(rme_digiface_rate_table))
1816+
return -EINVAL;
1817+
1818+
/* 2, 3, 4 for 1x, 2x, 4x */
1819+
speed_mode = (id >> 2) + 2;
1820+
val = (id << 3) | (speed_mode << 12);
1821+
1822+
/* Set the sample rate */
1823+
snd_usb_ctl_msg(subs->stream->chip->dev,
1824+
usb_sndctrlpipe(subs->stream->chip->dev, 0),
1825+
16, 0x40, val, 0x7078, NULL, 0);
1826+
return 0;
1827+
}
1828+
17741829
void snd_usb_set_format_quirk(struct snd_usb_substream *subs,
17751830
const struct audioformat *fmt)
17761831
{
@@ -1795,6 +1850,9 @@ void snd_usb_set_format_quirk(struct snd_usb_substream *subs,
17951850
case USB_ID(0x0dba, 0x5000):
17961851
mbox3_set_format_quirk(subs, fmt); /* Digidesign Mbox 3 */
17971852
break;
1853+
case USB_ID(0x2a39, 0x3f8c): /* RME Digiface USB */
1854+
rme_digiface_set_format_quirk(subs);
1855+
break;
17981856
}
17991857
}
18001858

0 commit comments

Comments
 (0)