mirror of
https://github.com/torvalds/linux.git
synced 2026-11-07 06:17:02 +01:00
ALSA: usb-audio: add Pioneer DJ DDJ-SZ support
The Pioneer DJ DDJ-SZ exposes its audio interface as USB vendor-specific class (0xFF) rather than USB Audio Class, so it needs a quirks-table entry like its sibling Pioneer devices (DJM-750, DJM-850, DJM-900NXS2, DJM-450, DJM-V10) already have. The device presents 10 channels of S24_3LE audio in both directions, fixed at 44.1kHz, on interface 0 altsetting 1: playback on endpoint 0x01, capture on endpoint 0x82. The unit contains its own analog mixer, and each playback channel pair feeds one of its physical channel strips: 0/1, 2/3, 4/5 and 6/7 feed strips 1-4 respectively, and 8/9 feed the booth output. The master output is produced in analog by that mixer and is not carried over USB at all. On the capture side, channels 8/9 are the mic input; capture channels 0-7 are not yet mapped to specific physical inputs. Implicit feedback needs no quirk flag here: is_pioneer_implicit_fb() in implicit.c already covers vendor 0x08e4 with a vendor-spec class interface and two endpoints, and the driver duly reports endpoint 0x82 as the playback sync endpoint. Activation reuses the existing pioneer_djm_set_format_quirk() used by the DJM-750/850/900NXS2/450/V10 (SET_INTERFACE to altsetting 1, then a UAC-shaped SET_CUR sample-rate control transfer) with this device's own captured wIndex (0x0082). Unlike those devices, the DDJ-SZ additionally needs a vendor "arm" sequence before its capture path produces real audio -- without it, capture opens and runs with no USB/ALSA errors but delivers silence (a hard zero on every channel) rather than any error, so this is easy to miss. The arm sequence is six vendor control transfers (bmRequestType=0x40, bRequest=3, varying wValue/wIndex, each followed by a bmRequestType=0xc0, bRequest=0 status read), replicated byte-for-byte from a USB capture of the official Windows driver. All of the above -- endpoint numbers, format, channel mapping, and the arm sequence bytes -- were determined by capturing and decoding real USB traffic from the Windows driver (USBPcap + Wireshark) during enumeration, playback, and mic recording, then verifying the format hypothesis against actual de-interleaved payload data rather than packet-size arithmetic alone. Both playback and capture have been verified working with real audio, not just clean enumeration. Signed-off-by: Hanh Kieu <hhkieu@gmail.com> Link: https://patch.msgid.link/20260903231641.18536-1-hhkieu@gmail.com Signed-off-by: Takashi Iwai <tiwai@suse.de>
This commit is contained in:
parent
a41da0bb08
commit
eccc0dc233
|
|
@ -3731,6 +3731,53 @@ YAMAHA_DEVICE(0x7010, "UB99"),
|
|||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
/*
|
||||
* Pioneer DJ DDJ-SZ
|
||||
* 10 channels playback & 10 channels capture @ 44.1kHz S24LE
|
||||
*/
|
||||
USB_DEVICE_VENDOR_SPEC(0x08e4, 0x0191),
|
||||
QUIRK_DRIVER_INFO {
|
||||
QUIRK_DATA_COMPOSITE {
|
||||
{
|
||||
QUIRK_DATA_AUDIOFORMAT(0) {
|
||||
.formats = SNDRV_PCM_FMTBIT_S24_3LE,
|
||||
.channels = 10,
|
||||
.iface = 0,
|
||||
.altsetting = 1,
|
||||
.altset_idx = 1,
|
||||
.endpoint = 0x01,
|
||||
.ep_attr = USB_ENDPOINT_XFER_ISOC|
|
||||
USB_ENDPOINT_SYNC_ASYNC,
|
||||
.rates = SNDRV_PCM_RATE_44100,
|
||||
.rate_min = 44100,
|
||||
.rate_max = 44100,
|
||||
.nr_rates = 1,
|
||||
.rate_table = (unsigned int[]) { 44100 }
|
||||
}
|
||||
},
|
||||
{
|
||||
QUIRK_DATA_AUDIOFORMAT(0) {
|
||||
.formats = SNDRV_PCM_FMTBIT_S24_3LE,
|
||||
.channels = 10,
|
||||
.iface = 0,
|
||||
.altsetting = 1,
|
||||
.altset_idx = 1,
|
||||
.endpoint = 0x82,
|
||||
.ep_idx = 1,
|
||||
.ep_attr = USB_ENDPOINT_XFER_ISOC|
|
||||
USB_ENDPOINT_SYNC_ASYNC,
|
||||
.rates = SNDRV_PCM_RATE_44100,
|
||||
.rate_min = 44100,
|
||||
.rate_max = 44100,
|
||||
.nr_rates = 1,
|
||||
.rate_table = (unsigned int[]) { 44100 }
|
||||
}
|
||||
},
|
||||
QUIRK_COMPOSITE_END
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
/*
|
||||
* Pioneer DJ DJM-750MK2
|
||||
|
|
|
|||
|
|
@ -1805,6 +1805,62 @@ static void set_format_emu_quirk(struct snd_usb_substream *subs,
|
|||
subs->pkt_offset_adj = (emu_samplerate_id >= EMU_QUIRK_SR_176400HZ) ? 4 : 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* The DDJ-SZ needs a vendor "arm" sequence before its capture path
|
||||
* produces real audio; without it capture runs with no USB or ALSA error
|
||||
* but delivers a hard zero on every channel. The sequence is replicated
|
||||
* byte-for-byte from a USB capture of the Windows driver: each write is
|
||||
* followed by a status read whose content is a fixed value regardless of
|
||||
* what was written, but the read is replicated too, since it is unclear
|
||||
* whether the device requires it to process the preceding write.
|
||||
*
|
||||
* This runs from snd_usb_set_format_quirk(), i.e. on every format setup
|
||||
* rather than once per device. Re-arming is harmless in practice and
|
||||
* keeps the device armed if it is reset behind our back.
|
||||
*/
|
||||
static void ddj_sz_arm_quirk(struct usb_device *dev)
|
||||
{
|
||||
static const struct {
|
||||
u16 value;
|
||||
u16 index;
|
||||
u8 read_len;
|
||||
} cmds[] = {
|
||||
{ 0x0100, 0x8002, 6 },
|
||||
{ 0x0200, 0x8002, 6 },
|
||||
{ 0x0303, 0x8002, 6 },
|
||||
{ 0x0403, 0x8002, 6 },
|
||||
{ 0x050a, 0x8002, 6 },
|
||||
{ 0x0000, 0x8003, 2 },
|
||||
};
|
||||
u8 buf[6];
|
||||
unsigned int i;
|
||||
int err;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(cmds); i++) {
|
||||
err = snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), 3,
|
||||
USB_DIR_OUT | USB_TYPE_VENDOR |
|
||||
USB_RECIP_DEVICE,
|
||||
cmds[i].value, cmds[i].index, NULL, 0);
|
||||
if (err < 0)
|
||||
goto err_out;
|
||||
|
||||
err = snd_usb_ctl_msg(dev, usb_rcvctrlpipe(dev, 0), 0,
|
||||
USB_DIR_IN | USB_TYPE_VENDOR |
|
||||
USB_RECIP_DEVICE,
|
||||
0x0000, cmds[i].index, buf,
|
||||
cmds[i].read_len);
|
||||
if (err < 0)
|
||||
goto err_out;
|
||||
}
|
||||
|
||||
return;
|
||||
|
||||
err_out:
|
||||
dev_warn(&dev->dev,
|
||||
"DDJ-SZ: arm sequence step %u failed (%d), capture may be silent\n",
|
||||
i, err);
|
||||
}
|
||||
|
||||
static int pioneer_djm_set_format_quirk(struct snd_usb_substream *subs,
|
||||
u16 windex)
|
||||
{
|
||||
|
|
@ -1986,6 +2042,10 @@ void snd_usb_set_format_quirk(struct snd_usb_substream *subs,
|
|||
case USB_ID(0x08e4, 0x0163): /* Pioneer DJM-850 */
|
||||
pioneer_djm_set_format_quirk(subs, 0x0086);
|
||||
break;
|
||||
case USB_ID(0x08e4, 0x0191): /* Pioneer DDJ-SZ */
|
||||
ddj_sz_arm_quirk(subs->dev);
|
||||
pioneer_djm_set_format_quirk(subs, 0x0082);
|
||||
break;
|
||||
case USB_ID(0x0dba, 0x5000):
|
||||
mbox3_set_format_quirk(subs, fmt); /* Digidesign Mbox 3 */
|
||||
break;
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user