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>
This commit is contained in:
parent
b3667bd757
commit
e9a25e04b8
@ -807,6 +807,7 @@ static void volume_control_quirks(struct usb_mixer_elem_info *cval,
|
||||
{
|
||||
switch (cval->mixer->chip->usb_id) {
|
||||
case USB_ID(0x0763, 0x2030): /* M-Audio Fast Track C400 */
|
||||
case USB_ID(0x0763, 0x2031): /* M-Audio Fast Track C600 */
|
||||
if (strcmp(kctl->id.name, "Effect Duration") == 0) {
|
||||
cval->min = 0x0000;
|
||||
cval->max = 0xffff;
|
||||
|
@ -379,6 +379,10 @@ static struct usbmix_ctl_map usbmix_ctl_maps[] = {
|
||||
.id = USB_ID(0x0763, 0x2030),
|
||||
.selector_map = c400_selectors,
|
||||
},
|
||||
{
|
||||
.id = USB_ID(0x0763, 0x2031),
|
||||
.selector_map = c400_selectors,
|
||||
},
|
||||
{
|
||||
.id = USB_ID(0x08bb, 0x2702),
|
||||
.map = linex_map,
|
||||
|
@ -637,7 +637,7 @@ static int snd_nativeinstruments_create_mixer(struct usb_mixer_interface *mixer,
|
||||
}
|
||||
|
||||
/* M-Audio FastTrack Ultra quirks */
|
||||
/* FTU Effect switch (also used by C400) */
|
||||
/* FTU Effect switch (also used by C400/C600) */
|
||||
struct snd_ftu_eff_switch_priv_val {
|
||||
struct usb_mixer_interface *mixer;
|
||||
int cached_value;
|
||||
@ -1029,32 +1029,45 @@ void snd_emuusb_set_samplerate(struct snd_usb_audio *chip,
|
||||
}
|
||||
}
|
||||
|
||||
/* M-Audio Fast Track C400 */
|
||||
/* C400 volume controls, this control needs a volume quirk, see mixer.c */
|
||||
/* M-Audio Fast Track C400/C600 */
|
||||
/* C400/C600 volume controls, this control needs a volume quirk, see mixer.c */
|
||||
static int snd_c400_create_vol_ctls(struct usb_mixer_interface *mixer)
|
||||
{
|
||||
char name[64];
|
||||
unsigned int cmask, offset;
|
||||
int out, chan, err;
|
||||
int num_outs = 0;
|
||||
int num_ins = 0;
|
||||
|
||||
const unsigned int id = 0x40;
|
||||
const int val_type = USB_MIXER_S16;
|
||||
const int control = 1;
|
||||
|
||||
for (chan = 0; chan < 10; chan++) {
|
||||
for (out = 0; out < 6; out++) {
|
||||
if (chan < 6) {
|
||||
switch (mixer->chip->usb_id) {
|
||||
case USB_ID(0x0763, 0x2030):
|
||||
num_outs = 6;
|
||||
num_ins = 4;
|
||||
break;
|
||||
case USB_ID(0x0763, 0x2031):
|
||||
num_outs = 8;
|
||||
num_ins = 6;
|
||||
break;
|
||||
}
|
||||
|
||||
for (chan = 0; chan < num_outs + num_ins; chan++) {
|
||||
for (out = 0; out < num_outs; out++) {
|
||||
if (chan < num_outs) {
|
||||
snprintf(name, sizeof(name),
|
||||
"PCM%d-Out%d Playback Volume",
|
||||
chan + 1, out + 1);
|
||||
} else {
|
||||
snprintf(name, sizeof(name),
|
||||
"In%d-Out%d Playback Volume",
|
||||
chan - 5, out + 1);
|
||||
chan - num_outs + 1, out + 1);
|
||||
}
|
||||
|
||||
cmask = (out == 0) ? 0 : 1 << (out - 1);
|
||||
offset = chan * 6;
|
||||
offset = chan * num_outs;
|
||||
err = snd_create_std_mono_ctl_offset(mixer, id, control,
|
||||
cmask, val_type, offset, name,
|
||||
&snd_usb_mixer_vol_tlv);
|
||||
@ -1110,20 +1123,33 @@ static int snd_c400_create_effect_vol_ctls(struct usb_mixer_interface *mixer)
|
||||
char name[64];
|
||||
unsigned int cmask;
|
||||
int chan, err;
|
||||
int num_outs = 0;
|
||||
int num_ins = 0;
|
||||
|
||||
const unsigned int id = 0x42;
|
||||
const int val_type = USB_MIXER_S16;
|
||||
const int control = 1;
|
||||
|
||||
for (chan = 0; chan < 10; chan++) {
|
||||
if (chan < 6) {
|
||||
switch (mixer->chip->usb_id) {
|
||||
case USB_ID(0x0763, 0x2030):
|
||||
num_outs = 6;
|
||||
num_ins = 4;
|
||||
break;
|
||||
case USB_ID(0x0763, 0x2031):
|
||||
num_outs = 8;
|
||||
num_ins = 6;
|
||||
break;
|
||||
}
|
||||
|
||||
for (chan = 0; chan < num_outs + num_ins; chan++) {
|
||||
if (chan < num_outs) {
|
||||
snprintf(name, sizeof(name),
|
||||
"Effect Send DOut%d",
|
||||
chan + 1);
|
||||
} else {
|
||||
snprintf(name, sizeof(name),
|
||||
"Effect Send AIn%d",
|
||||
chan - 5);
|
||||
chan - num_outs + 1);
|
||||
}
|
||||
|
||||
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
|
||||
char name[64];
|
||||
unsigned int cmask;
|
||||
int chan, err;
|
||||
int num_outs = 0;
|
||||
int offset = 0;
|
||||
|
||||
const unsigned int id = 0x40;
|
||||
const int val_type = USB_MIXER_S16;
|
||||
const int control = 1;
|
||||
const int chan_id[6] = { 0, 7, 2, 9, 4, 0xb };
|
||||
const unsigned int offset = 0x3c;
|
||||
/* { 0x3c, 0x43, 0x3e, 0x45, 0x40, 0x47 } */
|
||||
|
||||
for (chan = 0; chan < 6; chan++) {
|
||||
switch (mixer->chip->usb_id) {
|
||||
case USB_ID(0x0763, 0x2030):
|
||||
num_outs = 6;
|
||||
offset = 0x3c;
|
||||
/* { 0x3c, 0x43, 0x3e, 0x45, 0x40, 0x47 } */
|
||||
break;
|
||||
case USB_ID(0x0763, 0x2031):
|
||||
num_outs = 8;
|
||||
offset = 0x70;
|
||||
/* { 0x70, 0x79, 0x72, 0x7b, 0x74, 0x7d, 0x76, 0x7f } */
|
||||
break;
|
||||
}
|
||||
|
||||
for (chan = 0; chan < num_outs; chan++) {
|
||||
snprintf(name, sizeof(name),
|
||||
"Effect Return %d",
|
||||
chan + 1);
|
||||
|
||||
cmask = (chan_id[chan] == 0) ? 0 : 1 << (chan_id[chan] - 1);
|
||||
cmask = (chan == 0) ? 0 :
|
||||
1 << (chan + (chan % 2) * num_outs - 1);
|
||||
err = snd_create_std_mono_ctl_offset(mixer, id, control,
|
||||
cmask, val_type, offset, name,
|
||||
&snd_usb_mixer_vol_tlv);
|
||||
@ -1299,6 +1338,7 @@ int snd_usb_mixer_apply_create_quirk(struct usb_mixer_interface *mixer)
|
||||
break;
|
||||
|
||||
case USB_ID(0x0763, 0x2030): /* M-Audio Fast Track C400 */
|
||||
case USB_ID(0x0763, 0x2031): /* M-Audio Fast Track C400 */
|
||||
err = snd_c400_create_mixer(mixer);
|
||||
break;
|
||||
|
||||
|
@ -367,6 +367,7 @@ static int set_format(struct snd_usb_substream *subs, struct audioformat *fmt)
|
||||
|
||||
switch (subs->stream->chip->usb_id) {
|
||||
case USB_ID(0x0763, 0x2030): /* M-Audio Fast Track C400 */
|
||||
case USB_ID(0x0763, 0x2031): /* M-Audio Fast Track C600 */
|
||||
if (is_playback) {
|
||||
implicit_fb = 1;
|
||||
ep = 0x81;
|
||||
|
@ -2325,6 +2325,77 @@ YAMAHA_DEVICE(0x7010, "UB99"),
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
USB_DEVICE_VENDOR_SPEC(0x0763, 0x2031),
|
||||
.driver_info = (unsigned long) &(const struct snd_usb_audio_quirk) {
|
||||
/* .vendor_name = "M-Audio", */
|
||||
/* .product_name = "Fast Track C600", */
|
||||
.ifnum = QUIRK_ANY_INTERFACE,
|
||||
.type = QUIRK_COMPOSITE,
|
||||
.data = &(const struct snd_usb_audio_quirk[]) {
|
||||
{
|
||||
.ifnum = 1,
|
||||
.type = QUIRK_AUDIO_STANDARD_MIXER,
|
||||
},
|
||||
/* Playback */
|
||||
{
|
||||
.ifnum = 2,
|
||||
.type = QUIRK_AUDIO_FIXED_ENDPOINT,
|
||||
.data = &(const struct audioformat) {
|
||||
.formats = SNDRV_PCM_FMTBIT_S24_3LE,
|
||||
.channels = 8,
|
||||
.iface = 2,
|
||||
.altsetting = 1,
|
||||
.altset_idx = 1,
|
||||
.attributes = UAC_EP_CS_ATTR_SAMPLE_RATE,
|
||||
.endpoint = 0x01,
|
||||
.ep_attr = 0x09,
|
||||
.rates = SNDRV_PCM_RATE_44100 |
|
||||
SNDRV_PCM_RATE_48000 |
|
||||
SNDRV_PCM_RATE_88200 |
|
||||
SNDRV_PCM_RATE_96000,
|
||||
.rate_min = 44100,
|
||||
.rate_max = 96000,
|
||||
.nr_rates = 4,
|
||||
.rate_table = (unsigned int[]) {
|
||||
44100, 48000, 88200, 96000
|
||||
},
|
||||
.clock = 0x80,
|
||||
}
|
||||
},
|
||||
/* Capture */
|
||||
{
|
||||
.ifnum = 3,
|
||||
.type = QUIRK_AUDIO_FIXED_ENDPOINT,
|
||||
.data = &(const struct audioformat) {
|
||||
.formats = SNDRV_PCM_FMTBIT_S24_3LE,
|
||||
.channels = 6,
|
||||
.iface = 3,
|
||||
.altsetting = 1,
|
||||
.altset_idx = 1,
|
||||
.attributes = UAC_EP_CS_ATTR_SAMPLE_RATE,
|
||||
.endpoint = 0x81,
|
||||
.ep_attr = 0x05,
|
||||
.rates = SNDRV_PCM_RATE_44100 |
|
||||
SNDRV_PCM_RATE_48000 |
|
||||
SNDRV_PCM_RATE_88200 |
|
||||
SNDRV_PCM_RATE_96000,
|
||||
.rate_min = 44100,
|
||||
.rate_max = 96000,
|
||||
.nr_rates = 4,
|
||||
.rate_table = (unsigned int[]) {
|
||||
44100, 48000, 88200, 96000
|
||||
},
|
||||
.clock = 0x80,
|
||||
}
|
||||
},
|
||||
/* MIDI */
|
||||
{
|
||||
.ifnum = -1 /* Interface = 4 */
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
USB_DEVICE_VENDOR_SPEC(0x0763, 0x2080),
|
||||
.driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) {
|
||||
|
@ -863,13 +863,14 @@ void snd_usb_endpoint_start_quirk(struct snd_usb_endpoint *ep)
|
||||
ep->skip_packets = 4;
|
||||
|
||||
/*
|
||||
* M-Audio Fast Track C400 - when packets are not skipped, real world
|
||||
* latency varies by approx. +/- 50 frames (at 96KHz) each time the
|
||||
* stream is (re)started. When skipping packets 16 at endpoint start
|
||||
* up, the real world latency is stable within +/- 1 frame (also
|
||||
* M-Audio Fast Track C400/C600 - when packets are not skipped, real
|
||||
* world latency varies by approx. +/- 50 frames (at 96KHz) each time
|
||||
* the stream is (re)started. When skipping packets 16 at endpoint
|
||||
* start up, the real world latency is stable within +/- 1 frame (also
|
||||
* across power cycles).
|
||||
*/
|
||||
if (ep->chip->usb_id == USB_ID(0x0763, 0x2030) &&
|
||||
if ((ep->chip->usb_id == USB_ID(0x0763, 0x2030) ||
|
||||
ep->chip->usb_id == USB_ID(0x0763, 0x2031)) &&
|
||||
ep->type == SND_USB_ENDPOINT_TYPE_DATA)
|
||||
ep->skip_packets = 16;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user