aboutsummaryrefslogtreecommitdiffstats
path: root/sound/usb
diff options
context:
space:
mode:
authorMatt Gruskin <matthew.gruskin@gmail.com>2013-02-09 12:56:35 -0500
committerTakashi Iwai <tiwai@suse.de>2013-02-11 08:02:27 -0500
commite9a25e04b845aade311aaa268a696c5c4ff3eece (patch)
tree0a6a45cc6e8a231a063cd9db379c4ce34b6ec75a /sound/usb
parentb3667bd7579e6d4dfe709315f13cff9bc9ee9053 (diff)
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>
Diffstat (limited to 'sound/usb')
-rw-r--r--sound/usb/mixer.c1
-rw-r--r--sound/usb/mixer_maps.c4
-rw-r--r--sound/usb/mixer_quirks.c72
-rw-r--r--sound/usb/pcm.c1
-rw-r--r--sound/usb/quirks-table.h71
-rw-r--r--sound/usb/quirks.c11
6 files changed, 139 insertions, 21 deletions
diff --git a/sound/usb/mixer.c b/sound/usb/mixer.c
index e90daf8cdaa8..638e7f738018 100644
--- a/sound/usb/mixer.c
+++ b/sound/usb/mixer.c
@@ -807,6 +807,7 @@ static void volume_control_quirks(struct usb_mixer_elem_info *cval,
807{ 807{
808 switch (cval->mixer->chip->usb_id) { 808 switch (cval->mixer->chip->usb_id) {
809 case USB_ID(0x0763, 0x2030): /* M-Audio Fast Track C400 */ 809 case USB_ID(0x0763, 0x2030): /* M-Audio Fast Track C400 */
810 case USB_ID(0x0763, 0x2031): /* M-Audio Fast Track C600 */
810 if (strcmp(kctl->id.name, "Effect Duration") == 0) { 811 if (strcmp(kctl->id.name, "Effect Duration") == 0) {
811 cval->min = 0x0000; 812 cval->min = 0x0000;
812 cval->max = 0xffff; 813 cval->max = 0xffff;
diff --git a/sound/usb/mixer_maps.c b/sound/usb/mixer_maps.c
index 0e2ed3d05c45..cc2dd1f0decb 100644
--- a/sound/usb/mixer_maps.c
+++ b/sound/usb/mixer_maps.c
@@ -380,6 +380,10 @@ static struct usbmix_ctl_map usbmix_ctl_maps[] = {
380 .selector_map = c400_selectors, 380 .selector_map = c400_selectors,
381 }, 381 },
382 { 382 {
383 .id = USB_ID(0x0763, 0x2031),
384 .selector_map = c400_selectors,
385 },
386 {
383 .id = USB_ID(0x08bb, 0x2702), 387 .id = USB_ID(0x08bb, 0x2702),
384 .map = linex_map, 388 .map = linex_map,
385 .ignore_ctl_error = 1, 389 .ignore_ctl_error = 1,
diff --git a/sound/usb/mixer_quirks.c b/sound/usb/mixer_quirks.c
index 15520de1df56..497d2741d119 100644
--- a/sound/usb/mixer_quirks.c
+++ b/sound/usb/mixer_quirks.c
@@ -637,7 +637,7 @@ static int snd_nativeinstruments_create_mixer(struct usb_mixer_interface *mixer,
637} 637}
638 638
639/* M-Audio FastTrack Ultra quirks */ 639/* M-Audio FastTrack Ultra quirks */
640/* FTU Effect switch (also used by C400) */ 640/* FTU Effect switch (also used by C400/C600) */
641struct snd_ftu_eff_switch_priv_val { 641struct snd_ftu_eff_switch_priv_val {
642 struct usb_mixer_interface *mixer; 642 struct usb_mixer_interface *mixer;
643 int cached_value; 643 int cached_value;
@@ -1029,32 +1029,45 @@ void snd_emuusb_set_samplerate(struct snd_usb_audio *chip,
1029 } 1029 }
1030} 1030}
1031 1031
1032/* M-Audio Fast Track C400 */ 1032/* M-Audio Fast Track C400/C600 */
1033/* C400 volume controls, this control needs a volume quirk, see mixer.c */ 1033/* C400/C600 volume controls, this control needs a volume quirk, see mixer.c */
1034static int snd_c400_create_vol_ctls(struct usb_mixer_interface *mixer) 1034static int snd_c400_create_vol_ctls(struct usb_mixer_interface *mixer)
1035{ 1035{
1036 char name[64]; 1036 char name[64];
1037 unsigned int cmask, offset; 1037 unsigned int cmask, offset;
1038 int out, chan, err; 1038 int out, chan, err;
1039 int num_outs = 0;
1040 int num_ins = 0;
1039 1041
1040 const unsigned int id = 0x40; 1042 const unsigned int id = 0x40;
1041 const int val_type = USB_MIXER_S16; 1043 const int val_type = USB_MIXER_S16;
1042 const int control = 1; 1044 const int control = 1;
1043 1045
1044 for (chan = 0; chan < 10; chan++) { 1046 switch (mixer->chip->usb_id) {
1045 for (out = 0; out < 6; out++) { 1047 case USB_ID(0x0763, 0x2030):
1046 if (chan < 6) { 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 snprintf(name, sizeof(name), 1060 snprintf(name, sizeof(name),
1048 "PCM%d-Out%d Playback Volume", 1061 "PCM%d-Out%d Playback Volume",
1049 chan + 1, out + 1); 1062 chan + 1, out + 1);
1050 } else { 1063 } else {
1051 snprintf(name, sizeof(name), 1064 snprintf(name, sizeof(name),
1052 "In%d-Out%d Playback Volume", 1065 "In%d-Out%d Playback Volume",
1053 chan - 5, out + 1); 1066 chan - num_outs + 1, out + 1);
1054 } 1067 }
1055 1068
1056 cmask = (out == 0) ? 0 : 1 << (out - 1); 1069 cmask = (out == 0) ? 0 : 1 << (out - 1);
1057 offset = chan * 6; 1070 offset = chan * num_outs;
1058 err = snd_create_std_mono_ctl_offset(mixer, id, control, 1071 err = snd_create_std_mono_ctl_offset(mixer, id, control,
1059 cmask, val_type, offset, name, 1072 cmask, val_type, offset, name,
1060 &snd_usb_mixer_vol_tlv); 1073 &snd_usb_mixer_vol_tlv);
@@ -1110,20 +1123,33 @@ static int snd_c400_create_effect_vol_ctls(struct usb_mixer_interface *mixer)
1110 char name[64]; 1123 char name[64];
1111 unsigned int cmask; 1124 unsigned int cmask;
1112 int chan, err; 1125 int chan, err;
1126 int num_outs = 0;
1127 int num_ins = 0;
1113 1128
1114 const unsigned int id = 0x42; 1129 const unsigned int id = 0x42;
1115 const int val_type = USB_MIXER_S16; 1130 const int val_type = USB_MIXER_S16;
1116 const int control = 1; 1131 const int control = 1;
1117 1132
1118 for (chan = 0; chan < 10; chan++) { 1133 switch (mixer->chip->usb_id) {
1119 if (chan < 6) { 1134 case USB_ID(0x0763, 0x2030):
1135 num_outs = 6;
1136 num_ins = 4;
1137 break;
1138 case USB_ID(0x0763, 0x2031):
1139 num_outs = 8;
1140 num_ins = 6;
1141 break;
1142 }
1143
1144 for (chan = 0; chan < num_outs + num_ins; chan++) {
1145 if (chan < num_outs) {
1120 snprintf(name, sizeof(name), 1146 snprintf(name, sizeof(name),
1121 "Effect Send DOut%d", 1147 "Effect Send DOut%d",
1122 chan + 1); 1148 chan + 1);
1123 } else { 1149 } else {
1124 snprintf(name, sizeof(name), 1150 snprintf(name, sizeof(name),
1125 "Effect Send AIn%d", 1151 "Effect Send AIn%d",
1126 chan - 5); 1152 chan - num_outs + 1);
1127 } 1153 }
1128 1154
1129 cmask = (chan == 0) ? 0 : 1 << (chan - 1); 1155 cmask = (chan == 0) ? 0 : 1 << (chan - 1);
@@ -1142,20 +1168,33 @@ static int snd_c400_create_effect_ret_vol_ctls(struct usb_mixer_interface *mixer
1142 char name[64]; 1168 char name[64];
1143 unsigned int cmask; 1169 unsigned int cmask;
1144 int chan, err; 1170 int chan, err;
1171 int num_outs = 0;
1172 int offset = 0;
1145 1173
1146 const unsigned int id = 0x40; 1174 const unsigned int id = 0x40;
1147 const int val_type = USB_MIXER_S16; 1175 const int val_type = USB_MIXER_S16;
1148 const int control = 1; 1176 const int control = 1;
1149 const int chan_id[6] = { 0, 7, 2, 9, 4, 0xb };
1150 const unsigned int offset = 0x3c;
1151 /* { 0x3c, 0x43, 0x3e, 0x45, 0x40, 0x47 } */
1152 1177
1153 for (chan = 0; chan < 6; chan++) { 1178 switch (mixer->chip->usb_id) {
1179 case USB_ID(0x0763, 0x2030):
1180 num_outs = 6;
1181 offset = 0x3c;
1182 /* { 0x3c, 0x43, 0x3e, 0x45, 0x40, 0x47 } */
1183 break;
1184 case USB_ID(0x0763, 0x2031):
1185 num_outs = 8;
1186 offset = 0x70;
1187 /* { 0x70, 0x79, 0x72, 0x7b, 0x74, 0x7d, 0x76, 0x7f } */
1188 break;
1189 }
1190
1191 for (chan = 0; chan < num_outs; chan++) {
1154 snprintf(name, sizeof(name), 1192 snprintf(name, sizeof(name),
1155 "Effect Return %d", 1193 "Effect Return %d",
1156 chan + 1); 1194 chan + 1);
1157 1195
1158 cmask = (chan_id[chan] == 0) ? 0 : 1 << (chan_id[chan] - 1); 1196 cmask = (chan == 0) ? 0 :
1197 1 << (chan + (chan % 2) * num_outs - 1);
1159 err = snd_create_std_mono_ctl_offset(mixer, id, control, 1198 err = snd_create_std_mono_ctl_offset(mixer, id, control,
1160 cmask, val_type, offset, name, 1199 cmask, val_type, offset, name,
1161 &snd_usb_mixer_vol_tlv); 1200 &snd_usb_mixer_vol_tlv);
@@ -1299,6 +1338,7 @@ int snd_usb_mixer_apply_create_quirk(struct usb_mixer_interface *mixer)
1299 break; 1338 break;
1300 1339
1301 case USB_ID(0x0763, 0x2030): /* M-Audio Fast Track C400 */ 1340 case USB_ID(0x0763, 0x2030): /* M-Audio Fast Track C400 */
1341 case USB_ID(0x0763, 0x2031): /* M-Audio Fast Track C400 */
1302 err = snd_c400_create_mixer(mixer); 1342 err = snd_c400_create_mixer(mixer);
1303 break; 1343 break;
1304 1344
diff --git a/sound/usb/pcm.c b/sound/usb/pcm.c
index 81f70a719bb9..f94397b42aa5 100644
--- a/sound/usb/pcm.c
+++ b/sound/usb/pcm.c
@@ -367,6 +367,7 @@ static int set_format(struct snd_usb_substream *subs, struct audioformat *fmt)
367 367
368 switch (subs->stream->chip->usb_id) { 368 switch (subs->stream->chip->usb_id) {
369 case USB_ID(0x0763, 0x2030): /* M-Audio Fast Track C400 */ 369 case USB_ID(0x0763, 0x2030): /* M-Audio Fast Track C400 */
370 case USB_ID(0x0763, 0x2031): /* M-Audio Fast Track C600 */
370 if (is_playback) { 371 if (is_playback) {
371 implicit_fb = 1; 372 implicit_fb = 1;
372 ep = 0x81; 373 ep = 0x81;
diff --git a/sound/usb/quirks-table.h b/sound/usb/quirks-table.h
index 820580a6dfc3..c39f898b15d2 100644
--- a/sound/usb/quirks-table.h
+++ b/sound/usb/quirks-table.h
@@ -2326,6 +2326,77 @@ YAMAHA_DEVICE(0x7010, "UB99"),
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 USB_DEVICE_VENDOR_SPEC(0x0763, 0x2080), 2400 USB_DEVICE_VENDOR_SPEC(0x0763, 0x2080),
2330 .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) { 2401 .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) {
2331 /* .vendor_name = "M-Audio", */ 2402 /* .vendor_name = "M-Audio", */
diff --git a/sound/usb/quirks.c b/sound/usb/quirks.c
index 2c971858d6b7..7d7ad0b0620e 100644
--- a/sound/usb/quirks.c
+++ b/sound/usb/quirks.c
@@ -863,13 +863,14 @@ void snd_usb_endpoint_start_quirk(struct snd_usb_endpoint *ep)
863 ep->skip_packets = 4; 863 ep->skip_packets = 4;
864 864
865 /* 865 /*
866 * M-Audio Fast Track C400 - when packets are not skipped, real world 866 * M-Audio Fast Track C400/C600 - when packets are not skipped, real
867 * latency varies by approx. +/- 50 frames (at 96KHz) each time the 867 * world latency varies by approx. +/- 50 frames (at 96KHz) each time
868 * stream is (re)started. When skipping packets 16 at endpoint start 868 * the stream is (re)started. When skipping packets 16 at endpoint
869 * up, the real world latency is stable within +/- 1 frame (also 869 * start up, the real world latency is stable within +/- 1 frame (also
870 * across power cycles). 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 ep->type == SND_USB_ENDPOINT_TYPE_DATA) 874 ep->type == SND_USB_ENDPOINT_TYPE_DATA)
874 ep->skip_packets = 16; 875 ep->skip_packets = 16;
875} 876}