Skip to content
This repository was archived by the owner on Oct 31, 2024. It is now read-only.

Commit d1bccce

Browse files
CyanNyangregkh
authored andcommitted
ALSA: usb-audio: Add quirk for RME Digiface USB
[ Upstream commit c032044 ] 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> Signed-off-by: Sasha Levin <sashal@kernel.org>
1 parent 307ae9e commit d1bccce

File tree

2 files changed

+228
-1
lines changed

2 files changed

+228
-1
lines changed

sound/usb/quirks-table.h

+170-1
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

+58
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)