From: Jonathan Seth Mainguy <jon@soh.re>
To: linux-sound@vger.kernel.org
Cc: perex@perex.cz, tiwai@suse.com, niklas@aldervall.se,
linux-kernel@vger.kernel.org, Jonathan Seth Mainguy <jon@soh.re>
Subject: [PATCH 4/4] ALSA: usb-audio: set Roland Capture rate during stream preparation
Date: Fri, 28 Aug 2026 20:50:01 -0400 [thread overview]
Message-ID: <20260829005001.534571-5-jon@soh.re> (raw)
In-Reply-To: <20260829005001.534571-1-jon@soh.re>
Roland OCTA-CAPTURE and QUAD-CAPTURE select their hardware clock with
a vendor control request. Streaming fails when the hardware clock differs
from the rate selected for the USB endpoint.
During stream preparation, read the hardware rate and send the rate
request only when it differs from the selected endpoint rate. The control
transfer can complete before the device reports the new clock rate, so
poll readback every 25 ms and continue as soon as it matches. Forty
attempts avoid hammering the control endpoint while bounding an
unresponsive transition to one second.
Run the transaction from the existing format-setup quirk, after ALSA has
selected the endpoint rate and before data URBs are submitted. Hold the
USB-audio device mutex so playback and capture preparation cannot issue
overlapping clock changes.
Apply the quirk to:
0582:0120 Roland OCTA-CAPTURE
0582:012f Roland QUAD-CAPTURE
Tested on physical OCTA-CAPTURE and QUAD-CAPTURE units. Rate changes
followed by full-duplex streaming succeeded at 44.1, 48, 96 and 192 kHz
on both. External digital clocking on the OCTA-CAPTURE was tested at all
supported rates: 44.1, 48 and 96 kHz. The OCTA-CAPTURE disables its
digital input and output at 192 kHz, so external clocking is unavailable
at that rate.
Signed-off-by: Jonathan Seth Mainguy <jon@soh.re>
---
sound/usb/quirks.c | 74 ++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 74 insertions(+)
diff --git a/sound/usb/quirks.c b/sound/usb/quirks.c
index 91938172912a..4936d66f9591 100644
--- a/sound/usb/quirks.c
+++ b/sound/usb/quirks.c
@@ -3,6 +3,7 @@
*/
#include <linux/cleanup.h>
+#include <linux/delay.h>
#include <linux/err.h>
#include <linux/init.h>
#include <linux/slab.h>
@@ -1855,6 +1856,75 @@ static int rme_digiface_set_format_quirk(struct snd_usb_substream *subs)
return 0;
}
+#define ROLAND_CAPTURE_RATE_REQUEST 3
+#define ROLAND_CAPTURE_RATE_READ_VALUE 0x0001
+#define ROLAND_CAPTURE_RATE_WRITE_VALUE 0x0008
+#define ROLAND_CAPTURE_RATE_WRITE_PREFIX 0x40
+#define ROLAND_CAPTURE_RATE_RETRIES 40
+#define ROLAND_CAPTURE_RATE_POLL_MS 25
+
+/*
+ * OCTA-CAPTURE and QUAD-CAPTURE use the same vendor request for their
+ * hardware clock. A read returns the 24-bit little-endian rate followed by
+ * a transition-status byte. A write carries 0x40 followed by the rate.
+ */
+static int roland_capture_read_rate(struct usb_device *dev, u32 *rate)
+{
+ u8 data[4];
+ int err;
+
+ err = snd_usb_ctl_msg(dev, usb_rcvctrlpipe(dev, 0),
+ ROLAND_CAPTURE_RATE_REQUEST,
+ USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
+ ROLAND_CAPTURE_RATE_READ_VALUE, 0,
+ data, sizeof(data));
+ if (err != sizeof(data))
+ return err < 0 ? err : -EIO;
+
+ *rate = combine_triple(data);
+ return 0;
+}
+
+static void roland_capture_set_rate(struct snd_usb_substream *subs)
+{
+ struct snd_usb_audio *chip = subs->stream->chip;
+ struct usb_device *dev = chip->dev;
+ u32 rate = subs->data_endpoint->cur_rate;
+ u32 current_rate;
+ u8 data[4];
+ int err;
+ int i;
+
+ /* Serialize playback and capture endpoint starts during a clock change. */
+ guard(mutex)(&chip->mutex);
+ err = roland_capture_read_rate(dev, ¤t_rate);
+ if (!err && current_rate == rate)
+ return;
+
+ data[0] = ROLAND_CAPTURE_RATE_WRITE_PREFIX;
+ data[1] = rate;
+ data[2] = rate >> 8;
+ data[3] = rate >> 16;
+ err = snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
+ ROLAND_CAPTURE_RATE_REQUEST,
+ USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
+ ROLAND_CAPTURE_RATE_WRITE_VALUE, 0,
+ data, sizeof(data));
+ if (err != sizeof(data)) {
+ usb_audio_warn(chip, "cannot set Roland sample rate to %u Hz: %d\n",
+ rate, err < 0 ? err : -EIO);
+ return;
+ }
+
+ for (i = 0; i < ROLAND_CAPTURE_RATE_RETRIES; i++) {
+ err = roland_capture_read_rate(dev, ¤t_rate);
+ if (!err && current_rate == rate)
+ return;
+ msleep(ROLAND_CAPTURE_RATE_POLL_MS);
+ }
+ usb_audio_warn(chip, "Roland sample rate did not reach %u Hz\n", rate);
+}
+
void snd_usb_set_format_quirk(struct snd_usb_substream *subs,
const struct audioformat *fmt)
{
@@ -1885,6 +1955,10 @@ void snd_usb_set_format_quirk(struct snd_usb_substream *subs,
case USB_ID(0x2a39, 0x3fa0): /* RME Digiface USB (alternate) */
rme_digiface_set_format_quirk(subs);
break;
+ case USB_ID(0x0582, 0x0120): /* Roland OCTA-CAPTURE */
+ case USB_ID(0x0582, 0x012f): /* Roland QUAD-CAPTURE */
+ roland_capture_set_rate(subs);
+ break;
}
}
--
2.55.0
next prev parent reply other threads:[~2026-08-29 0:51 UTC|newest]
Thread overview: 6+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-08-29 0:49 [PATCH 0/4] ALSA: usb-audio: support Roland Capture sample rates Jonathan Seth Mainguy
2026-08-29 0:49 ` [PATCH 1/4] ALSA: usb-audio: add Roland OCTA-CAPTURE multirate support Jonathan Seth Mainguy
2026-08-29 0:49 ` [PATCH 2/4] ALSA: usb-audio: expose OCTA-CAPTURE control MIDI cables Jonathan Seth Mainguy
2026-08-29 0:50 ` [PATCH 3/4] ALSA: usb-audio: add Roland QUAD-CAPTURE multirate support Jonathan Seth Mainguy
2026-08-29 0:50 ` Jonathan Seth Mainguy [this message]
2026-08-31 8:30 ` [PATCH 0/4] ALSA: usb-audio: support Roland Capture sample rates Takashi Iwai
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20260829005001.534571-5-jon@soh.re \
--to=jon@soh.re \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-sound@vger.kernel.org \
--cc=niklas@aldervall.se \
--cc=perex@perex.cz \
--cc=tiwai@suse.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox