]> git.ipfire.org Git - thirdparty/kernel/stable.git/commitdiff
ALSA: usb-audio: Add quirk for RME Digiface USB
authorCyan Nyan <cyan.vtb@gmail.com>
Tue, 3 Sep 2024 10:52:29 +0000 (19:52 +0900)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Thu, 10 Oct 2024 10:00:23 +0000 (12:00 +0200)
[ Upstream commit c032044e9672408c534d64a6df2b1ba14449e948 ]

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>
sound/usb/quirks-table.h
sound/usb/quirks.c

index 8d22de8bc2a96f5bd3b53cea9164b051bfe97b11..631b9ab80f6cd09a4145a02c374b140b8f85a917 100644 (file)
@@ -3604,6 +3604,175 @@ YAMAHA_DEVICE(0x7010, "UB99"),
                }
        }
 },
-
+{
+       /* Only claim interface 0 */
+       .match_flags = USB_DEVICE_ID_MATCH_VENDOR |
+                      USB_DEVICE_ID_MATCH_PRODUCT |
+                      USB_DEVICE_ID_MATCH_INT_CLASS |
+                      USB_DEVICE_ID_MATCH_INT_NUMBER,
+       .idVendor = 0x2a39,
+       .idProduct = 0x3f8c,
+       .bInterfaceClass = USB_CLASS_VENDOR_SPEC,
+       .bInterfaceNumber = 0,
+       QUIRK_DRIVER_INFO {
+               QUIRK_DATA_COMPOSITE {
+                       /*
+                        * Three modes depending on sample rate band,
+                        * with different channel counts for in/out
+                        */
+                       {
+                               QUIRK_DATA_AUDIOFORMAT(0) {
+                                       .formats = SNDRV_PCM_FMTBIT_S32_LE,
+                                       .channels = 34, // outputs
+                                       .fmt_bits = 24,
+                                       .iface = 0,
+                                       .altsetting = 1,
+                                       .altset_idx = 1,
+                                       .endpoint = 0x02,
+                                       .ep_idx = 1,
+                                       .ep_attr = USB_ENDPOINT_XFER_ISOC |
+                                               USB_ENDPOINT_SYNC_ASYNC,
+                                       .rates = SNDRV_PCM_RATE_32000 |
+                                               SNDRV_PCM_RATE_44100 |
+                                               SNDRV_PCM_RATE_48000,
+                                       .rate_min = 32000,
+                                       .rate_max = 48000,
+                                       .nr_rates = 3,
+                                       .rate_table = (unsigned int[]) {
+                                               32000, 44100, 48000,
+                                       },
+                                       .sync_ep = 0x81,
+                                       .sync_iface = 0,
+                                       .sync_altsetting = 1,
+                                       .sync_ep_idx = 0,
+                                       .implicit_fb = 1,
+                               },
+                       },
+                       {
+                               QUIRK_DATA_AUDIOFORMAT(0) {
+                                       .formats = SNDRV_PCM_FMTBIT_S32_LE,
+                                       .channels = 18, // outputs
+                                       .fmt_bits = 24,
+                                       .iface = 0,
+                                       .altsetting = 1,
+                                       .altset_idx = 1,
+                                       .endpoint = 0x02,
+                                       .ep_idx = 1,
+                                       .ep_attr = USB_ENDPOINT_XFER_ISOC |
+                                               USB_ENDPOINT_SYNC_ASYNC,
+                                       .rates = SNDRV_PCM_RATE_64000 |
+                                               SNDRV_PCM_RATE_88200 |
+                                               SNDRV_PCM_RATE_96000,
+                                       .rate_min = 64000,
+                                       .rate_max = 96000,
+                                       .nr_rates = 3,
+                                       .rate_table = (unsigned int[]) {
+                                               64000, 88200, 96000,
+                                       },
+                                       .sync_ep = 0x81,
+                                       .sync_iface = 0,
+                                       .sync_altsetting = 1,
+                                       .sync_ep_idx = 0,
+                                       .implicit_fb = 1,
+                               },
+                       },
+                       {
+                               QUIRK_DATA_AUDIOFORMAT(0) {
+                                       .formats = SNDRV_PCM_FMTBIT_S32_LE,
+                                       .channels = 10, // outputs
+                                       .fmt_bits = 24,
+                                       .iface = 0,
+                                       .altsetting = 1,
+                                       .altset_idx = 1,
+                                       .endpoint = 0x02,
+                                       .ep_idx = 1,
+                                       .ep_attr = USB_ENDPOINT_XFER_ISOC |
+                                               USB_ENDPOINT_SYNC_ASYNC,
+                                       .rates = SNDRV_PCM_RATE_KNOT |
+                                               SNDRV_PCM_RATE_176400 |
+                                               SNDRV_PCM_RATE_192000,
+                                       .rate_min = 128000,
+                                       .rate_max = 192000,
+                                       .nr_rates = 3,
+                                       .rate_table = (unsigned int[]) {
+                                               128000, 176400, 192000,
+                                       },
+                                       .sync_ep = 0x81,
+                                       .sync_iface = 0,
+                                       .sync_altsetting = 1,
+                                       .sync_ep_idx = 0,
+                                       .implicit_fb = 1,
+                               },
+                       },
+                       {
+                               QUIRK_DATA_AUDIOFORMAT(0) {
+                                       .formats = SNDRV_PCM_FMTBIT_S32_LE,
+                                       .channels = 32, // inputs
+                                       .fmt_bits = 24,
+                                       .iface = 0,
+                                       .altsetting = 1,
+                                       .altset_idx = 1,
+                                       .endpoint = 0x81,
+                                       .ep_attr = USB_ENDPOINT_XFER_ISOC |
+                                               USB_ENDPOINT_SYNC_ASYNC,
+                                       .rates = SNDRV_PCM_RATE_32000 |
+                                               SNDRV_PCM_RATE_44100 |
+                                               SNDRV_PCM_RATE_48000,
+                                       .rate_min = 32000,
+                                       .rate_max = 48000,
+                                       .nr_rates = 3,
+                                       .rate_table = (unsigned int[]) {
+                                               32000, 44100, 48000,
+                                       }
+                               }
+                       },
+                       {
+                               QUIRK_DATA_AUDIOFORMAT(0) {
+                                       .formats = SNDRV_PCM_FMTBIT_S32_LE,
+                                       .channels = 16, // inputs
+                                       .fmt_bits = 24,
+                                       .iface = 0,
+                                       .altsetting = 1,
+                                       .altset_idx = 1,
+                                       .endpoint = 0x81,
+                                       .ep_attr = USB_ENDPOINT_XFER_ISOC |
+                                               USB_ENDPOINT_SYNC_ASYNC,
+                                       .rates = SNDRV_PCM_RATE_64000 |
+                                               SNDRV_PCM_RATE_88200 |
+                                               SNDRV_PCM_RATE_96000,
+                                       .rate_min = 64000,
+                                       .rate_max = 96000,
+                                       .nr_rates = 3,
+                                       .rate_table = (unsigned int[]) {
+                                               64000, 88200, 96000,
+                                       }
+                               }
+                       },
+                       {
+                               QUIRK_DATA_AUDIOFORMAT(0) {
+                                       .formats = SNDRV_PCM_FMTBIT_S32_LE,
+                                       .channels = 8, // inputs
+                                       .fmt_bits = 24,
+                                       .iface = 0,
+                                       .altsetting = 1,
+                                       .altset_idx = 1,
+                                       .endpoint = 0x81,
+                                       .ep_attr = USB_ENDPOINT_XFER_ISOC |
+                                               USB_ENDPOINT_SYNC_ASYNC,
+                                       .rates = SNDRV_PCM_RATE_KNOT |
+                                               SNDRV_PCM_RATE_176400 |
+                                               SNDRV_PCM_RATE_192000,
+                                       .rate_min = 128000,
+                                       .rate_max = 192000,
+                                       .nr_rates = 3,
+                                       .rate_table = (unsigned int[]) {
+                                               128000, 176400, 192000,
+                                       }
+                               }
+                       },
+                       QUIRK_COMPOSITE_END
+               }
+       }
+},
 #undef USB_DEVICE_VENDOR_SPEC
 #undef USB_AUDIO_DEVICE
index e7b68c67852e92ef851d7f820dfd6c522e2c0e24..73da862a012c6e7240815a293911a077cf9384bf 100644 (file)
@@ -1389,6 +1389,27 @@ static int snd_usb_motu_m_series_boot_quirk(struct usb_device *dev)
        return 0;
 }
 
+static int snd_usb_rme_digiface_boot_quirk(struct usb_device *dev)
+{
+       /* Disable mixer, internal clock, all outputs ADAT, 48kHz, TMS off */
+       snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
+                       16, 0x40, 0x2410, 0x7fff, NULL, 0);
+       snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
+                       18, 0x40, 0x0104, 0xffff, NULL, 0);
+
+       /* Disable loopback for all inputs */
+       for (int ch = 0; ch < 32; ch++)
+               snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
+                               22, 0x40, 0x400, ch, NULL, 0);
+
+       /* Unity gain for all outputs */
+       for (int ch = 0; ch < 34; ch++)
+               snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
+                               21, 0x40, 0x9000, 0x100 + ch, NULL, 0);
+
+       return 0;
+}
+
 /*
  * Setup quirks
  */
@@ -1616,6 +1637,8 @@ int snd_usb_apply_boot_quirk(struct usb_device *dev,
                    get_iface_desc(intf->altsetting)->bInterfaceNumber < 3)
                        return snd_usb_motu_microbookii_boot_quirk(dev);
                break;
+       case USB_ID(0x2a39, 0x3f8c): /* RME Digiface USB */
+               return snd_usb_rme_digiface_boot_quirk(dev);
        }
 
        return 0;
@@ -1771,6 +1794,38 @@ static void mbox3_set_format_quirk(struct snd_usb_substream *subs,
                dev_warn(&subs->dev->dev, "MBOX3: Couldn't set the sample rate");
 }
 
+static const int rme_digiface_rate_table[] = {
+       32000, 44100, 48000, 0,
+       64000, 88200, 96000, 0,
+       128000, 176400, 192000, 0,
+};
+
+static int rme_digiface_set_format_quirk(struct snd_usb_substream *subs)
+{
+       unsigned int cur_rate = subs->data_endpoint->cur_rate;
+       u16 val;
+       int speed_mode;
+       int id;
+
+       for (id = 0; id < ARRAY_SIZE(rme_digiface_rate_table); id++) {
+               if (rme_digiface_rate_table[id] == cur_rate)
+                       break;
+       }
+
+       if (id >= ARRAY_SIZE(rme_digiface_rate_table))
+               return -EINVAL;
+
+       /* 2, 3, 4 for 1x, 2x, 4x */
+       speed_mode = (id >> 2) + 2;
+       val = (id << 3) | (speed_mode << 12);
+
+       /* Set the sample rate */
+       snd_usb_ctl_msg(subs->stream->chip->dev,
+               usb_sndctrlpipe(subs->stream->chip->dev, 0),
+               16, 0x40, val, 0x7078, NULL, 0);
+       return 0;
+}
+
 void snd_usb_set_format_quirk(struct snd_usb_substream *subs,
                              const struct audioformat *fmt)
 {
@@ -1795,6 +1850,9 @@ void snd_usb_set_format_quirk(struct snd_usb_substream *subs,
        case USB_ID(0x0dba, 0x5000):
                mbox3_set_format_quirk(subs, fmt); /* Digidesign Mbox 3 */
                break;
+       case USB_ID(0x2a39, 0x3f8c): /* RME Digiface USB */
+               rme_digiface_set_format_quirk(subs);
+               break;
        }
 }