diff options
author | Matt Gruskin <matthew.gruskin@gmail.com> | 2013-02-09 12:56:35 -0500 |
---|---|---|
committer | Takashi Iwai <tiwai@suse.de> | 2013-02-11 08:02:27 -0500 |
commit | e9a25e04b845aade311aaa268a696c5c4ff3eece (patch) | |
tree | 0a6a45cc6e8a231a063cd9db379c4ce34b6ec75a /sound/usb | |
parent | b3667bd7579e6d4dfe709315f13cff9bc9ee9053 (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.c | 1 | ||||
-rw-r--r-- | sound/usb/mixer_maps.c | 4 | ||||
-rw-r--r-- | sound/usb/mixer_quirks.c | 72 | ||||
-rw-r--r-- | sound/usb/pcm.c | 1 | ||||
-rw-r--r-- | sound/usb/quirks-table.h | 71 | ||||
-rw-r--r-- | sound/usb/quirks.c | 11 |
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) */ |
641 | struct snd_ftu_eff_switch_priv_val { | 641 | struct 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 */ |
1034 | static int snd_c400_create_vol_ctls(struct usb_mixer_interface *mixer) | 1034 | static 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 | } |