Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

ALSA: usb-audio: Add Pioneer DJ DJM-V10 support

Pioneer DJ DJM-V10 is a high end mixer that acts like a USB sound card.
The MIDI controller part is standard but the PCM part is "vendor specific".
Input and output is enabled by this patch:
- 12 channels (6 stereo) in each direction
- 44 100 / 48 000 / 96 000 Hz
- S24_3LE

Capture channels can be configured through alsamixer.
Playback channels are fixed and controlled by hardware knobs on the mixer.

Signed-off-by: František Kučera <franta-linux@frantovo.cz>
Link: https://patch.msgid.link/20250421155953.4440-1-konference@frantovo.cz
Signed-off-by: Takashi Iwai <tiwai@suse.de>

authored by

František Kučera and committed by
Takashi Iwai
171bb512 05100d16

+111 -3
+59 -3
sound/usb/mixer_quirks.c
··· 3525 3525 #define SND_DJM_CAP_RECOUT 0x0a 3526 3526 #define SND_DJM_CAP_RECOUT_NOMIC 0x0e 3527 3527 #define SND_DJM_CAP_NONE 0x0f 3528 + #define SND_DJM_CAP_FXSEND 0x10 3528 3529 #define SND_DJM_CAP_CH1PFADER 0x11 3529 3530 #define SND_DJM_CAP_CH2PFADER 0x12 3530 3531 #define SND_DJM_CAP_CH3PFADER 0x13 3531 3532 #define SND_DJM_CAP_CH4PFADER 0x14 3533 + #define SND_DJM_CAP_EXT1SEND 0x21 3534 + #define SND_DJM_CAP_EXT2SEND 0x22 3532 3535 #define SND_DJM_CAP_CH1PREFADER 0x31 3533 3536 #define SND_DJM_CAP_CH2PREFADER 0x32 3534 3537 #define SND_DJM_CAP_CH3PREFADER 0x33 ··· 3562 3559 #define SND_DJM_750MK2_IDX 0x4 3563 3560 #define SND_DJM_450_IDX 0x5 3564 3561 #define SND_DJM_A9_IDX 0x6 3562 + #define SND_DJM_V10_IDX 0x7 3565 3563 3566 3564 3567 3565 #define SND_DJM_CTL(_name, suffix, _default_value, _windex) { \ ··· 3602 3598 } 3603 3599 }; 3604 3600 3605 - // The DJM-A9 has different capture levels than other, older models 3606 - static const char *snd_djm_get_label_caplevel_a9(u16 wvalue) 3601 + // Models like DJM-A9 or DJM-V10 have different capture levels than others 3602 + static const char *snd_djm_get_label_caplevel_high(u16 wvalue) 3607 3603 { 3608 3604 switch (wvalue) { 3609 3605 case 0x0000: return "+15dB"; ··· 3631 3627 case SND_DJM_CAP_RECOUT_NOMIC: return "Rec Out without Mic"; 3632 3628 case SND_DJM_CAP_AUX: return "Aux"; 3633 3629 case SND_DJM_CAP_NONE: return "None"; 3630 + case SND_DJM_CAP_FXSEND: return "FX SEND"; 3634 3631 case SND_DJM_CAP_CH1PREFADER: return "Pre Fader Ch1"; 3635 3632 case SND_DJM_CAP_CH2PREFADER: return "Pre Fader Ch2"; 3636 3633 case SND_DJM_CAP_CH3PREFADER: return "Pre Fader Ch3"; ··· 3640 3635 case SND_DJM_CAP_CH2PFADER: return "Post Fader Ch2"; 3641 3636 case SND_DJM_CAP_CH3PFADER: return "Post Fader Ch3"; 3642 3637 case SND_DJM_CAP_CH4PFADER: return "Post Fader Ch4"; 3638 + case SND_DJM_CAP_EXT1SEND: return "EXT1 SEND"; 3639 + case SND_DJM_CAP_EXT2SEND: return "EXT2 SEND"; 3643 3640 default: return NULL; 3644 3641 } 3645 3642 }; ··· 3660 3653 static const char *snd_djm_get_label_caplevel(u8 device_idx, u16 wvalue) 3661 3654 { 3662 3655 switch (device_idx) { 3663 - case SND_DJM_A9_IDX: return snd_djm_get_label_caplevel_a9(wvalue); 3656 + case SND_DJM_A9_IDX: return snd_djm_get_label_caplevel_high(wvalue); 3657 + case SND_DJM_V10_IDX: return snd_djm_get_label_caplevel_high(wvalue); 3664 3658 default: return snd_djm_get_label_caplevel_common(wvalue); 3665 3659 } 3666 3660 }; ··· 3861 3853 SND_DJM_CTL("Ch4 Input", a9_cap5, 2, SND_DJM_WINDEX_CAP) 3862 3854 }; 3863 3855 3856 + // DJM-V10 3857 + static const u16 snd_djm_opts_v10_cap_level[] = { 3858 + 0x0000, 0x0100, 0x0200, 0x0300, 0x0400, 0x0500 3859 + }; 3860 + static const u16 snd_djm_opts_v10_cap1[] = { 3861 + 0x0103, 3862 + 0x0100, 0x0102, 0x0106, 0x0110, 0x0107, 3863 + 0x0108, 0x0109, 0x010a, 0x0121, 0x0122 3864 + }; 3865 + static const u16 snd_djm_opts_v10_cap2[] = { 3866 + 0x0200, 0x0202, 0x0206, 0x0210, 0x0207, 3867 + 0x0208, 0x0209, 0x020a, 0x0221, 0x0222 3868 + }; 3869 + static const u16 snd_djm_opts_v10_cap3[] = { 3870 + 0x0303, 3871 + 0x0300, 0x0302, 0x0306, 0x0310, 0x0307, 3872 + 0x0308, 0x0309, 0x030a, 0x0321, 0x0322 3873 + }; 3874 + static const u16 snd_djm_opts_v10_cap4[] = { 3875 + 0x0403, 3876 + 0x0400, 0x0402, 0x0406, 0x0410, 0x0407, 3877 + 0x0408, 0x0409, 0x040a, 0x0421, 0x0422 3878 + }; 3879 + static const u16 snd_djm_opts_v10_cap5[] = { 3880 + 0x0500, 0x0502, 0x0506, 0x0510, 0x0507, 3881 + 0x0508, 0x0509, 0x050a, 0x0521, 0x0522 3882 + }; 3883 + static const u16 snd_djm_opts_v10_cap6[] = { 3884 + 0x0603, 3885 + 0x0600, 0x0602, 0x0606, 0x0610, 0x0607, 3886 + 0x0608, 0x0609, 0x060a, 0x0621, 0x0622 3887 + }; 3888 + 3889 + static const struct snd_djm_ctl snd_djm_ctls_v10[] = { 3890 + SND_DJM_CTL("Master Capture Level Capture Switch", v10_cap_level, 0, SND_DJM_WINDEX_CAPLVL), 3891 + SND_DJM_CTL("Capture Ch1 Capture Switch", v10_cap1, 2, SND_DJM_WINDEX_CAP), 3892 + SND_DJM_CTL("Capture Ch2 Capture Switch", v10_cap2, 2, SND_DJM_WINDEX_CAP), 3893 + SND_DJM_CTL("Capture Ch3 Capture Switch", v10_cap3, 0, SND_DJM_WINDEX_CAP), 3894 + SND_DJM_CTL("Capture Ch4 Capture Switch", v10_cap4, 0, SND_DJM_WINDEX_CAP), 3895 + SND_DJM_CTL("Capture Ch5 Capture Switch", v10_cap5, 0, SND_DJM_WINDEX_CAP), 3896 + SND_DJM_CTL("Capture Ch6 Capture Switch", v10_cap6, 0, SND_DJM_WINDEX_CAP) 3897 + // playback channels are fixed and controlled by hardware knobs on the mixer 3898 + }; 3899 + 3864 3900 static const struct snd_djm_device snd_djm_devices[] = { 3865 3901 [SND_DJM_250MK2_IDX] = SND_DJM_DEVICE(250mk2), 3866 3902 [SND_DJM_750_IDX] = SND_DJM_DEVICE(750), ··· 3913 3861 [SND_DJM_750MK2_IDX] = SND_DJM_DEVICE(750mk2), 3914 3862 [SND_DJM_450_IDX] = SND_DJM_DEVICE(450), 3915 3863 [SND_DJM_A9_IDX] = SND_DJM_DEVICE(a9), 3864 + [SND_DJM_V10_IDX] = SND_DJM_DEVICE(v10), 3916 3865 }; 3917 3866 3918 3867 ··· 4203 4150 break; 4204 4151 case USB_ID(0x2b73, 0x003c): /* Pioneer DJ / AlphaTheta DJM-A9 */ 4205 4152 err = snd_djm_controls_create(mixer, SND_DJM_A9_IDX); 4153 + break; 4154 + case USB_ID(0x2b73, 0x0034): /* Pioneer DJ DJM-V10 */ 4155 + err = snd_djm_controls_create(mixer, SND_DJM_V10_IDX); 4206 4156 break; 4207 4157 } 4208 4158
+51
sound/usb/quirks-table.h
··· 3187 3187 } 3188 3188 } 3189 3189 }, 3190 + { 3191 + /* 3192 + * Pioneer DJ DJM-V10 3193 + */ 3194 + USB_DEVICE_VENDOR_SPEC(0x2b73, 0x0034), 3195 + QUIRK_DRIVER_INFO { 3196 + QUIRK_DATA_COMPOSITE { 3197 + { 3198 + QUIRK_DATA_AUDIOFORMAT(0) { 3199 + .formats = SNDRV_PCM_FMTBIT_S24_3LE, 3200 + .channels = 12, // outputs 3201 + .iface = 0, 3202 + .altsetting = 1, 3203 + .altset_idx = 1, 3204 + .endpoint = 0x01, 3205 + .ep_attr = USB_ENDPOINT_XFER_ISOC| 3206 + USB_ENDPOINT_SYNC_ASYNC, 3207 + .rates = SNDRV_PCM_RATE_44100| 3208 + SNDRV_PCM_RATE_48000| 3209 + SNDRV_PCM_RATE_96000, 3210 + .rate_min = 44100, 3211 + .rate_max = 96000, 3212 + .nr_rates = 3, 3213 + .rate_table = (unsigned int[]) { 44100, 48000, 96000 } 3214 + } 3215 + }, 3216 + { 3217 + QUIRK_DATA_AUDIOFORMAT(0) { 3218 + .formats = SNDRV_PCM_FMTBIT_S24_3LE, 3219 + .channels = 12, // inputs 3220 + .iface = 0, 3221 + .altsetting = 1, 3222 + .altset_idx = 1, 3223 + .endpoint = 0x82, 3224 + .ep_idx = 1, 3225 + .ep_attr = USB_ENDPOINT_XFER_ISOC| 3226 + USB_ENDPOINT_SYNC_ASYNC| 3227 + USB_ENDPOINT_USAGE_IMPLICIT_FB, 3228 + .rates = SNDRV_PCM_RATE_44100| 3229 + SNDRV_PCM_RATE_48000| 3230 + SNDRV_PCM_RATE_96000, 3231 + .rate_min = 44100, 3232 + .rate_max = 96000, 3233 + .nr_rates = 3, 3234 + .rate_table = (unsigned int[]) { 44100, 48000, 96000 } 3235 + } 3236 + }, 3237 + QUIRK_COMPOSITE_END 3238 + } 3239 + } 3240 + }, 3190 3241 3191 3242 /* 3192 3243 * MacroSilicon MS2100/MS2106 based AV capture cards
+1
sound/usb/quirks.c
··· 1872 1872 break; 1873 1873 case USB_ID(0x2b73, 0x000a): /* Pioneer DJM-900NXS2 */ 1874 1874 case USB_ID(0x2b73, 0x0013): /* Pioneer DJM-450 */ 1875 + case USB_ID(0x2b73, 0x0034): /* Pioneer DJM-V10 */ 1875 1876 pioneer_djm_set_format_quirk(subs, 0x0082); 1876 1877 break; 1877 1878 case USB_ID(0x08e4, 0x017f): /* Pioneer DJM-750 */