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

ALSA: usb-audio: add support for M-Audio FT C600

Adds quirks and mixer support for the M-Audio Fast Track C600 USB
audio interface. This device is very similar to the C400 - the C600
simply has some more inputs and outputs, so the existing C400 support
is extended to support this device as well.

Signed-off-by: Matt Gruskin <matthew.gruskin@gmail.com>
Signed-off-by: Takashi Iwai <tiwai@suse.de>

authored by

Matt Gruskin and committed by
Takashi Iwai
e9a25e04 b3667bd7

+139 -21
+1
sound/usb/mixer.c
··· 807 807 { 808 808 switch (cval->mixer->chip->usb_id) { 809 809 case USB_ID(0x0763, 0x2030): /* M-Audio Fast Track C400 */ 810 + case USB_ID(0x0763, 0x2031): /* M-Audio Fast Track C600 */ 810 811 if (strcmp(kctl->id.name, "Effect Duration") == 0) { 811 812 cval->min = 0x0000; 812 813 cval->max = 0xffff;
+4
sound/usb/mixer_maps.c
··· 380 380 .selector_map = c400_selectors, 381 381 }, 382 382 { 383 + .id = USB_ID(0x0763, 0x2031), 384 + .selector_map = c400_selectors, 385 + }, 386 + { 383 387 .id = USB_ID(0x08bb, 0x2702), 384 388 .map = linex_map, 385 389 .ignore_ctl_error = 1,
+56 -16
sound/usb/mixer_quirks.c
··· 637 637 } 638 638 639 639 /* M-Audio FastTrack Ultra quirks */ 640 - /* FTU Effect switch (also used by C400) */ 640 + /* FTU Effect switch (also used by C400/C600) */ 641 641 struct snd_ftu_eff_switch_priv_val { 642 642 struct usb_mixer_interface *mixer; 643 643 int cached_value; ··· 1029 1029 } 1030 1030 } 1031 1031 1032 - /* M-Audio Fast Track C400 */ 1033 - /* C400 volume controls, this control needs a volume quirk, see mixer.c */ 1032 + /* M-Audio Fast Track C400/C600 */ 1033 + /* C400/C600 volume controls, this control needs a volume quirk, see mixer.c */ 1034 1034 static int snd_c400_create_vol_ctls(struct usb_mixer_interface *mixer) 1035 1035 { 1036 1036 char name[64]; 1037 1037 unsigned int cmask, offset; 1038 1038 int out, chan, err; 1039 + int num_outs = 0; 1040 + int num_ins = 0; 1039 1041 1040 1042 const unsigned int id = 0x40; 1041 1043 const int val_type = USB_MIXER_S16; 1042 1044 const int control = 1; 1043 1045 1044 - for (chan = 0; chan < 10; chan++) { 1045 - for (out = 0; out < 6; out++) { 1046 - if (chan < 6) { 1046 + switch (mixer->chip->usb_id) { 1047 + case USB_ID(0x0763, 0x2030): 1048 + num_outs = 6; 1049 + num_ins = 4; 1050 + break; 1051 + case USB_ID(0x0763, 0x2031): 1052 + num_outs = 8; 1053 + num_ins = 6; 1054 + break; 1055 + } 1056 + 1057 + for (chan = 0; chan < num_outs + num_ins; chan++) { 1058 + for (out = 0; out < num_outs; out++) { 1059 + if (chan < num_outs) { 1047 1060 snprintf(name, sizeof(name), 1048 1061 "PCM%d-Out%d Playback Volume", 1049 1062 chan + 1, out + 1); 1050 1063 } else { 1051 1064 snprintf(name, sizeof(name), 1052 1065 "In%d-Out%d Playback Volume", 1053 - chan - 5, out + 1); 1066 + chan - num_outs + 1, out + 1); 1054 1067 } 1055 1068 1056 1069 cmask = (out == 0) ? 0 : 1 << (out - 1); 1057 - offset = chan * 6; 1070 + offset = chan * num_outs; 1058 1071 err = snd_create_std_mono_ctl_offset(mixer, id, control, 1059 1072 cmask, val_type, offset, name, 1060 1073 &snd_usb_mixer_vol_tlv); ··· 1123 1110 char name[64]; 1124 1111 unsigned int cmask; 1125 1112 int chan, err; 1113 + int num_outs = 0; 1114 + int num_ins = 0; 1126 1115 1127 1116 const unsigned int id = 0x42; 1128 1117 const int val_type = USB_MIXER_S16; 1129 1118 const int control = 1; 1130 1119 1131 - for (chan = 0; chan < 10; chan++) { 1132 - if (chan < 6) { 1120 + switch (mixer->chip->usb_id) { 1121 + case USB_ID(0x0763, 0x2030): 1122 + num_outs = 6; 1123 + num_ins = 4; 1124 + break; 1125 + case USB_ID(0x0763, 0x2031): 1126 + num_outs = 8; 1127 + num_ins = 6; 1128 + break; 1129 + } 1130 + 1131 + for (chan = 0; chan < num_outs + num_ins; chan++) { 1132 + if (chan < num_outs) { 1133 1133 snprintf(name, sizeof(name), 1134 1134 "Effect Send DOut%d", 1135 1135 chan + 1); 1136 1136 } else { 1137 1137 snprintf(name, sizeof(name), 1138 1138 "Effect Send AIn%d", 1139 - chan - 5); 1139 + chan - num_outs + 1); 1140 1140 } 1141 1141 1142 1142 cmask = (chan == 0) ? 0 : 1 << (chan - 1); ··· 1168 1142 char name[64]; 1169 1143 unsigned int cmask; 1170 1144 int chan, err; 1145 + int num_outs = 0; 1146 + int offset = 0; 1171 1147 1172 1148 const unsigned int id = 0x40; 1173 1149 const int val_type = USB_MIXER_S16; 1174 1150 const int control = 1; 1175 - const int chan_id[6] = { 0, 7, 2, 9, 4, 0xb }; 1176 - const unsigned int offset = 0x3c; 1177 - /* { 0x3c, 0x43, 0x3e, 0x45, 0x40, 0x47 } */ 1178 1151 1179 - for (chan = 0; chan < 6; chan++) { 1152 + switch (mixer->chip->usb_id) { 1153 + case USB_ID(0x0763, 0x2030): 1154 + num_outs = 6; 1155 + offset = 0x3c; 1156 + /* { 0x3c, 0x43, 0x3e, 0x45, 0x40, 0x47 } */ 1157 + break; 1158 + case USB_ID(0x0763, 0x2031): 1159 + num_outs = 8; 1160 + offset = 0x70; 1161 + /* { 0x70, 0x79, 0x72, 0x7b, 0x74, 0x7d, 0x76, 0x7f } */ 1162 + break; 1163 + } 1164 + 1165 + for (chan = 0; chan < num_outs; chan++) { 1180 1166 snprintf(name, sizeof(name), 1181 1167 "Effect Return %d", 1182 1168 chan + 1); 1183 1169 1184 - cmask = (chan_id[chan] == 0) ? 0 : 1 << (chan_id[chan] - 1); 1170 + cmask = (chan == 0) ? 0 : 1171 + 1 << (chan + (chan % 2) * num_outs - 1); 1185 1172 err = snd_create_std_mono_ctl_offset(mixer, id, control, 1186 1173 cmask, val_type, offset, name, 1187 1174 &snd_usb_mixer_vol_tlv); ··· 1338 1299 break; 1339 1300 1340 1301 case USB_ID(0x0763, 0x2030): /* M-Audio Fast Track C400 */ 1302 + case USB_ID(0x0763, 0x2031): /* M-Audio Fast Track C400 */ 1341 1303 err = snd_c400_create_mixer(mixer); 1342 1304 break; 1343 1305
+1
sound/usb/pcm.c
··· 367 367 368 368 switch (subs->stream->chip->usb_id) { 369 369 case USB_ID(0x0763, 0x2030): /* M-Audio Fast Track C400 */ 370 + case USB_ID(0x0763, 0x2031): /* M-Audio Fast Track C600 */ 370 371 if (is_playback) { 371 372 implicit_fb = 1; 372 373 ep = 0x81;
+71
sound/usb/quirks-table.h
··· 2326 2326 } 2327 2327 }, 2328 2328 { 2329 + USB_DEVICE_VENDOR_SPEC(0x0763, 0x2031), 2330 + .driver_info = (unsigned long) &(const struct snd_usb_audio_quirk) { 2331 + /* .vendor_name = "M-Audio", */ 2332 + /* .product_name = "Fast Track C600", */ 2333 + .ifnum = QUIRK_ANY_INTERFACE, 2334 + .type = QUIRK_COMPOSITE, 2335 + .data = &(const struct snd_usb_audio_quirk[]) { 2336 + { 2337 + .ifnum = 1, 2338 + .type = QUIRK_AUDIO_STANDARD_MIXER, 2339 + }, 2340 + /* Playback */ 2341 + { 2342 + .ifnum = 2, 2343 + .type = QUIRK_AUDIO_FIXED_ENDPOINT, 2344 + .data = &(const struct audioformat) { 2345 + .formats = SNDRV_PCM_FMTBIT_S24_3LE, 2346 + .channels = 8, 2347 + .iface = 2, 2348 + .altsetting = 1, 2349 + .altset_idx = 1, 2350 + .attributes = UAC_EP_CS_ATTR_SAMPLE_RATE, 2351 + .endpoint = 0x01, 2352 + .ep_attr = 0x09, 2353 + .rates = SNDRV_PCM_RATE_44100 | 2354 + SNDRV_PCM_RATE_48000 | 2355 + SNDRV_PCM_RATE_88200 | 2356 + SNDRV_PCM_RATE_96000, 2357 + .rate_min = 44100, 2358 + .rate_max = 96000, 2359 + .nr_rates = 4, 2360 + .rate_table = (unsigned int[]) { 2361 + 44100, 48000, 88200, 96000 2362 + }, 2363 + .clock = 0x80, 2364 + } 2365 + }, 2366 + /* Capture */ 2367 + { 2368 + .ifnum = 3, 2369 + .type = QUIRK_AUDIO_FIXED_ENDPOINT, 2370 + .data = &(const struct audioformat) { 2371 + .formats = SNDRV_PCM_FMTBIT_S24_3LE, 2372 + .channels = 6, 2373 + .iface = 3, 2374 + .altsetting = 1, 2375 + .altset_idx = 1, 2376 + .attributes = UAC_EP_CS_ATTR_SAMPLE_RATE, 2377 + .endpoint = 0x81, 2378 + .ep_attr = 0x05, 2379 + .rates = SNDRV_PCM_RATE_44100 | 2380 + SNDRV_PCM_RATE_48000 | 2381 + SNDRV_PCM_RATE_88200 | 2382 + SNDRV_PCM_RATE_96000, 2383 + .rate_min = 44100, 2384 + .rate_max = 96000, 2385 + .nr_rates = 4, 2386 + .rate_table = (unsigned int[]) { 2387 + 44100, 48000, 88200, 96000 2388 + }, 2389 + .clock = 0x80, 2390 + } 2391 + }, 2392 + /* MIDI */ 2393 + { 2394 + .ifnum = -1 /* Interface = 4 */ 2395 + } 2396 + } 2397 + } 2398 + }, 2399 + { 2329 2400 USB_DEVICE_VENDOR_SPEC(0x0763, 0x2080), 2330 2401 .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) { 2331 2402 /* .vendor_name = "M-Audio", */
+6 -5
sound/usb/quirks.c
··· 863 863 ep->skip_packets = 4; 864 864 865 865 /* 866 - * M-Audio Fast Track C400 - when packets are not skipped, real world 867 - * latency varies by approx. +/- 50 frames (at 96KHz) each time the 868 - * stream is (re)started. When skipping packets 16 at endpoint start 869 - * up, the real world latency is stable within +/- 1 frame (also 866 + * M-Audio Fast Track C400/C600 - when packets are not skipped, real 867 + * world latency varies by approx. +/- 50 frames (at 96KHz) each time 868 + * the stream is (re)started. When skipping packets 16 at endpoint 869 + * start up, the real world latency is stable within +/- 1 frame (also 870 870 * across power cycles). 871 871 */ 872 - if (ep->chip->usb_id == USB_ID(0x0763, 0x2030) && 872 + if ((ep->chip->usb_id == USB_ID(0x0763, 0x2030) || 873 + ep->chip->usb_id == USB_ID(0x0763, 0x2031)) && 873 874 ep->type == SND_USB_ENDPOINT_TYPE_DATA) 874 875 ep->skip_packets = 16; 875 876 }