/* * create a stream for an interface with proper descriptors
*/ staticint create_standard_audio_quirk(struct snd_usb_audio *chip, struct usb_interface *iface, struct usb_driver *driver, conststruct snd_usb_audio_quirk *quirk)
{ struct usb_host_interface *alts; struct usb_interface_descriptor *altsd; int err;
alts = &iface->altsetting[0];
altsd = get_iface_desc(alts);
err = snd_usb_parse_audio_interface(chip, altsd->bInterfaceNumber); if (err < 0) {
usb_audio_err(chip, "cannot setup if %d: error %d\n",
altsd->bInterfaceNumber, err); return err;
} /* reset the current interface */
usb_set_interface(chip->dev, altsd->bInterfaceNumber, 0); return 0;
}
/* create the audio stream and the corresponding endpoints from the fixed * audioformat object; this is used for quirks with the fixed EPs
*/ staticint add_audio_stream_from_fixed_fmt(struct snd_usb_audio *chip, struct audioformat *fp)
{ int stream, err;
/* * Most Roland/Yamaha audio streaming interfaces have more or less * standard descriptors, but older devices might lack descriptors, and * future ones might change, so ensure that we fail silently if the * interface doesn't look exactly right.
*/
/* must have a non-zero altsetting for streaming */ if (iface->num_altsetting < 2) return -ENODEV;
alts = &iface->altsetting[1];
altsd = get_iface_desc(alts);
/* must have an isochronous endpoint for streaming */ if (altsd->bNumEndpoints < 1) return -ENODEV;
epd = get_endpoint(alts, 0); if (!usb_endpoint_xfer_isoc(epd)) return -ENODEV;
/* must have format descriptors */
ashd = snd_usb_find_csint_desc(alts->extra, alts->extralen, NULL,
UAC_AS_GENERAL);
fmtd = snd_usb_find_csint_desc(alts->extra, alts->extralen, NULL,
UAC_FORMAT_TYPE); if (!ashd || ashd->bLength < 7 ||
!fmtd || fmtd->bLength < 8) return -ENODEV;
/* must have at least one bulk/interrupt endpoint for streaming */ if (altsd->bNumEndpoints < 1) return -ENODEV;
epd = get_endpoint(alts, 0); if (!usb_endpoint_xfer_bulk(epd) &&
!usb_endpoint_xfer_int(epd)) return -ENODEV;
switch (USB_ID_VENDOR(chip->usb_id)) { case 0x0499: /* Yamaha */
err = create_yamaha_midi_quirk(chip, iface, driver, alts); if (err != -ENODEV) return err; break; case 0x0582: /* Roland */
err = create_roland_midi_quirk(chip, iface, driver, alts); if (err != -ENODEV) return err; break;
}
/* * Create a stream for an Edirol UA-700/UA-25/UA-4FX interface. * The only way to detect the sample rate is by looking at wMaxPacketSize.
*/ staticint create_uaxx_quirk(struct snd_usb_audio *chip, struct usb_interface *iface, struct usb_driver *driver, conststruct snd_usb_audio_quirk *quirk)
{ staticconststruct audioformat ua_format = {
.formats = SNDRV_PCM_FMTBIT_S24_3LE,
.channels = 2,
.fmt_type = UAC_FORMAT_TYPE_I,
.altsetting = 1,
.altset_idx = 1,
.rates = SNDRV_PCM_RATE_CONTINUOUS,
}; struct usb_host_interface *alts; struct usb_interface_descriptor *altsd; struct audioformat *fp; int err;
/* both PCM and MIDI interfaces have 2 or more altsettings */ if (iface->num_altsetting < 2) return -ENXIO;
alts = &iface->altsetting[1];
altsd = get_iface_desc(alts);
staticint snd_usb_fasttrackpro_boot_quirk(struct usb_device *dev)
{ int err;
if (dev->actconfig->desc.bConfigurationValue == 1) {
dev_info(&dev->dev, "Fast Track Pro switching to config #2\n"); /* This function has to be available by the usb core module. * if it is not avialable the boot quirk has to be left out * and the configuration has to be set by udev or hotplug * rules
*/
err = usb_driver_set_configuration(dev, 2); if (err < 0)
dev_dbg(&dev->dev, "error usb_driver_set_configuration: %d\n",
err); /* Always return an error, so that we stop creating a device that will just be destroyed and recreated with a new
configuration */ return -ENODEV;
} else
dev_info(&dev->dev, "Fast Track Pro config OK\n");
return 0;
}
/* * C-Media CM106/CM106+ have four 16-bit internal registers that are nicely * documented in the device's data sheet.
*/ staticint snd_usb_cm106_write_int_reg(struct usb_device *dev, int reg, u16 value)
{
u8 buf[4];
buf[0] = 0x20;
buf[1] = value & 0xff;
buf[2] = (value >> 8) & 0xff;
buf[3] = reg; return snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), USB_REQ_SET_CONFIGURATION,
USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_ENDPOINT,
0, 0, &buf, 4);
}
staticint snd_usb_cm106_boot_quirk(struct usb_device *dev)
{ /* * Enable line-out driver mode, set headphone source to front * channels, enable stereo mic.
*/ return snd_usb_cm106_write_int_reg(dev, 2, 0x8004);
}
/* quirk for Plantronics GameCom 780 with CM6302 chip */ staticint snd_usb_gamecon780_boot_quirk(struct usb_device *dev)
{ /* set the initial volume and don't change; other values are either * too loud or silent due to firmware bug (bko#65251)
*/
u8 buf[2] = { 0x74, 0xe3 }; return snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), UAC_SET_CUR,
USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_OUT,
UAC_FU_VOLUME << 8, 9 << 8, buf, 2);
}
/* * Novation Twitch DJ controller * Focusrite Novation Saffire 6 USB audio card
*/ staticint snd_usb_novation_boot_quirk(struct usb_device *dev)
{ /* preemptively set up the device because otherwise the
* raw MIDI endpoints are not active */
usb_set_interface(dev, 0, 1); return 0;
}
/* * This call will put the synth in "USB send" mode, i.e it will send MIDI * messages through USB (this is disabled at startup). The synth will * acknowledge by sending a sysex on endpoint 0x85 and by displaying a USB * sign on its LCD. Values here are chosen based on sniffing USB traffic * under Windows.
*/ staticint snd_usb_accessmusic_boot_quirk(struct usb_device *dev)
{ int err, actual_length; /* "midi send" enable */ staticconst u8 seq[] = { 0x4e, 0x73, 0x52, 0x01 }; void *buf;
/* * Some sound cards from Native Instruments are in fact compliant to the USB * audio standard of version 2 and other approved USB standards, even though * they come up as vendor-specific device when first connected. * * However, they can be told to come up with a new set of descriptors * upon their next enumeration, and the interfaces announced by the new * descriptors will then be handled by the kernel's class drivers. As the * product ID will also change, no further checks are required.
*/
staticint snd_usb_nativeinstruments_boot_quirk(struct usb_device *dev)
{ int ret;
/* return -EAGAIN, so the creation of an audio interface for this * temporary device is aborted. The device will reconnect with a
* new product ID */ return -EAGAIN;
}
/* Digidesign Mbox 2 needs to load firmware onboard * and driver must wait a few seconds for initialisation.
*/
#define MBOX2_FIRMWARE_SIZE 646 #define MBOX2_BOOT_LOADING 0x01 /* Hard coded into the device */ #define MBOX2_BOOT_READY 0x02 /* Hard coded into the device */
staticint snd_usb_mbox2_boot_quirk(struct usb_device *dev)
{ struct usb_host_config *config = dev->actconfig; struct usb_device_descriptor *new_device_descriptor __free(kfree) = NULL; int err;
u8 bootresponse[0x12]; int fwsize; int count;
staticint snd_usb_axefx3_boot_quirk(struct usb_device *dev)
{ int err;
dev_dbg(&dev->dev, "Waiting for Axe-Fx III to boot up...\n");
/* If the Axe-Fx III has not fully booted, it will timeout when trying * to enable the audio streaming interface. A more generous timeout is * used here to detect when the Axe-Fx III has finished booting as the * set interface message will be acked once it has
*/
err = usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
USB_REQ_SET_INTERFACE, USB_RECIP_INTERFACE,
1, 1, NULL, 0, 120000); if (err < 0) {
dev_err(&dev->dev, "failed waiting for Axe-Fx III to boot: %d\n", err); return err;
}
dev_dbg(&dev->dev, "Axe-Fx III is now ready\n");
err = usb_set_interface(dev, 1, 0); if (err < 0)
dev_dbg(&dev->dev, "error stopping Axe-Fx III interface: %d\n", err);
return 0;
}
staticvoid mbox3_setup_defaults(struct usb_device *dev)
{ /* The Mbox 3 is "little endian" */ /* max volume is: 0x0000. */ /* min volume is: 0x0080 (shown in little endian form) */
com_buff[0] = 0x00;
com_buff[1] = 0x80; /* S/PDIF fx returns left channel */
snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
1, 0x21, 0x0122, 0x4001, &com_buff, 2); /* S/PDIF fx returns right channel */
snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
1, 0x21, 0x0123, 0x4001, &com_buff, 2);
/* Set the dropdown "Effect" to the first option */ /* Room1 = 0x00 */ /* Room2 = 0x01 */ /* Room3 = 0x02 */ /* Hall 1 = 0x03 */ /* Hall 2 = 0x04 */ /* Plate = 0x05 */ /* Delay = 0x06 */ /* Echo = 0x07 */
com_buff[0] = 0x00;
snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
1, 0x21, 0x0200, 0x4301, &com_buff, 1); /* max is 0xff */ /* min is 0x00 */
/* Set the effect duration to 0 */ /* max is 0xffff */ /* min is 0x0000 */
com_buff[0] = 0x00;
com_buff[1] = 0x00;
snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
1, 0x21, 0x0400, 0x4301, &com_buff, 2);
/* Set the effect volume and feedback to 0 */ /* max is 0xff */ /* min is 0x00 */
com_buff[0] = 0x00; /* feedback: */
snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
1, 0x21, 0x0500, 0x4301, &com_buff, 1); /* volume: */
snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
1, 0x21, 0x0300, 0x4301, &com_buff, 1);
dev_info(&dev->dev, "Waiting for MOTU Microbook II to boot up...\n");
/* First we tell the device which sample rate to use. */
memcpy(buf, set_samplerate_seq, sizeof(set_samplerate_seq));
actual_length = sizeof(set_samplerate_seq);
err = snd_usb_motu_microbookii_communicate(dev, buf, MICROBOOK_BUF_SIZE,
&actual_length);
if (err < 0) {
dev_err(&dev->dev, "failed setting the sample rate for Motu MicroBook II: %d\n",
err); goto free_buf;
}
/* Then we poll every 100 ms until the device informs of its readiness. */ while (true) { if (++poll_attempts > 100) {
dev_err(&dev->dev, "failed booting Motu MicroBook II: timeout\n");
err = -ENODEV; goto free_buf;
}
/* the device signals its readiness through a message of the * form * XX 06 00 00 00 00 0b 18 00 00 00 01 * If the device is not yet ready to accept audio data, the * last byte of that sequence is 00.
*/ if (actual_length == 12 && buf[actual_length - 1] == 1) break;
/* Disable loopback for all inputs */ for (int ch = 0; ch < 32; ch++)
snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
22, 0x40, 0x400, ch, NULL, 0);
/* Unity gain for all outputs */ for (int ch = 0; ch < 34; ch++)
snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
21, 0x40, 0x9000, 0x100 + ch, NULL, 0);
return 0;
}
/* * Setup quirks
*/ #define MAUDIO_SET 0x01 /* parse device_setup */ #define MAUDIO_SET_COMPATIBLE 0x80 /* use only "win-compatible" interfaces */ #define MAUDIO_SET_DTS 0x02 /* enable DTS Digital Output */ #define MAUDIO_SET_96K 0x04 /* 48-96kHz rate if set, 8-48kHz otherwise */ #define MAUDIO_SET_24B 0x08 /* 24bits sample if set, 16bits otherwise */ #define MAUDIO_SET_DI 0x10 /* enable Digital Input */ #define MAUDIO_SET_MASK 0x1f /* bit mask for setup value */ #define MAUDIO_SET_24B_48K_DI 0x19 /* 24bits+48kHz+Digital Input */ #define MAUDIO_SET_24B_48K_NOTDI 0x09 /* 24bits+48kHz+No Digital Input */ #define MAUDIO_SET_16B_48K_DI 0x11 /* 16bits+48kHz+Digital Input */ #define MAUDIO_SET_16B_48K_NOTDI 0x01 /* 16bits+48kHz+No Digital Input */
staticint quattro_skip_setting_quirk(struct snd_usb_audio *chip, int iface, int altno)
{ /* Reset ALL ifaces to 0 altsetting. * Call it for every possible altsetting of every interface.
*/
usb_set_interface(chip->dev, iface, 0); if (chip->setup & MAUDIO_SET) { if (chip->setup & MAUDIO_SET_COMPATIBLE) { if (iface != 1 && iface != 2) return 1; /* skip all interfaces but 1 and 2 */
} else { unsignedint mask; if (iface == 1 || iface == 2) return 1; /* skip interfaces 1 and 2 */ if ((chip->setup & MAUDIO_SET_96K) && altno != 1) return 1; /* skip this altsetting */
mask = chip->setup & MAUDIO_SET_MASK; if (mask == MAUDIO_SET_24B_48K_DI && altno != 2) return 1; /* skip this altsetting */ if (mask == MAUDIO_SET_24B_48K_NOTDI && altno != 3) return 1; /* skip this altsetting */ if (mask == MAUDIO_SET_16B_48K_NOTDI && altno != 4) return 1; /* skip this altsetting */
}
}
usb_audio_dbg(chip, "using altsetting %d for interface %d config %d\n",
altno, iface, chip->setup); return 0; /* keep this altsetting */
}
staticint audiophile_skip_setting_quirk(struct snd_usb_audio *chip, int iface, int altno)
{ /* Reset ALL ifaces to 0 altsetting. * Call it for every possible altsetting of every interface.
*/
usb_set_interface(chip->dev, iface, 0);
if (chip->setup & MAUDIO_SET) { unsignedint mask; if ((chip->setup & MAUDIO_SET_DTS) && altno != 6) return 1; /* skip this altsetting */ if ((chip->setup & MAUDIO_SET_96K) && altno != 1) return 1; /* skip this altsetting */
mask = chip->setup & MAUDIO_SET_MASK; if (mask == MAUDIO_SET_24B_48K_DI && altno != 2) return 1; /* skip this altsetting */ if (mask == MAUDIO_SET_24B_48K_NOTDI && altno != 3) return 1; /* skip this altsetting */ if (mask == MAUDIO_SET_16B_48K_DI && altno != 4) return 1; /* skip this altsetting */ if (mask == MAUDIO_SET_16B_48K_NOTDI && altno != 5) return 1; /* skip this altsetting */
}
return 0; /* keep this altsetting */
}
staticint fasttrackpro_skip_setting_quirk(struct snd_usb_audio *chip, int iface, int altno)
{ /* Reset ALL ifaces to 0 altsetting. * Call it for every possible altsetting of every interface.
*/
usb_set_interface(chip->dev, iface, 0);
/* possible configuration where both inputs and only one output is *used is not supported by the current setup
*/ if (chip->setup & (MAUDIO_SET | MAUDIO_SET_24B)) { if (chip->setup & MAUDIO_SET_96K) { if (altno != 3 && altno != 6) return 1;
} elseif (chip->setup & MAUDIO_SET_DI) { if (iface == 4) return 1; /* no analog input */ if (altno != 2 && altno != 5) return 1; /* enable only altsets 2 and 5 */
} else { if (iface == 5) return 1; /* disable digialt input */ if (altno != 2 && altno != 5) return 1; /* enalbe only altsets 2 and 5 */
}
} else { /* keep only 16-Bit mode */ if (altno != 1) return 1;
}
usb_audio_dbg(chip, "using altsetting %d for interface %d config %d\n",
altno, iface, chip->setup); return 0; /* keep this altsetting */
}
staticint s1810c_skip_setting_quirk(struct snd_usb_audio *chip, int iface, int altno)
{ /* * Altno settings: * * Playback (Interface 1): * 1: 6 Analog + 2 S/PDIF * 2: 6 Analog + 2 S/PDIF * 3: 6 Analog * * Capture (Interface 2): * 1: 8 Analog + 2 S/PDIF + 8 ADAT * 2: 8 Analog + 2 S/PDIF + 4 ADAT * 3: 8 Analog
*/
/* * I'll leave 2 as the default one and * use device_setup to switch to the * other two.
*/ if ((chip->setup == 0 || chip->setup > 2) && altno != 2) return 1; elseif (chip->setup == 1 && altno != 1) return 1; elseif (chip->setup == 2 && altno != 3) return 1;
return 0;
}
int snd_usb_apply_interface_quirk(struct snd_usb_audio *chip, int iface, int altno)
{ /* audiophile usb: skip altsets incompatible with device_setup */ if (chip->usb_id == USB_ID(0x0763, 0x2003)) return audiophile_skip_setting_quirk(chip, iface, altno); /* quattro usb: skip altsets incompatible with device_setup */ if (chip->usb_id == USB_ID(0x0763, 0x2001)) return quattro_skip_setting_quirk(chip, iface, altno); /* fasttrackpro usb: skip altsets incompatible with device_setup */ if (chip->usb_id == USB_ID(0x0763, 0x2012)) return fasttrackpro_skip_setting_quirk(chip, iface, altno); /* presonus studio 1810c: skip altsets incompatible with device_setup */ if (chip->usb_id == USB_ID(0x194f, 0x010c)) return s1810c_skip_setting_quirk(chip, iface, altno);
return 0;
}
int snd_usb_apply_boot_quirk(struct usb_device *dev, struct usb_interface *intf, conststruct snd_usb_audio_quirk *quirk, unsignedint id)
{ switch (id) { case USB_ID(0x041e, 0x3000): /* SB Extigy needs special boot-up sequence */ /* if more models come, this will go to the quirk list. */ return snd_usb_extigy_boot_quirk(dev, intf);
case USB_ID(0x041e, 0x3020): /* SB Audigy 2 NX needs its own boot-up magic, too */ return snd_usb_audigy2nx_boot_quirk(dev);
/* When capture is active * sample rate shouldn't be changed * by playback substream
*/ if (subs->direction == SNDRV_PCM_STREAM_PLAYBACK) { if (subs->stream->substream[SNDRV_PCM_STREAM_CAPTURE].cur_audiofmt) return;
}
// Get current rate from card and check if changing it is needed
snd_usb_ctl_msg(subs->dev, usb_rcvctrlpipe(subs->dev, 0),
0x01, 0x21 | USB_DIR_IN, 0x0100, 0x8101, &buff4, 4);
current_rate = le32_to_cpu(buff4);
dev_dbg(&subs->dev->dev, "MBOX3: Current configured sample rate: %d", current_rate); if (current_rate == new_rate) {
dev_dbg(&subs->dev->dev, "MBOX3: No change needed (current rate:%d == new rate:%d)",
current_rate, new_rate); return;
}
// Set new rate
dev_info(&subs->dev->dev, "MBOX3: Changing sample rate to: %d", new_rate);
buff4 = cpu_to_le32(new_rate);
snd_usb_ctl_msg(subs->dev, usb_sndctrlpipe(subs->dev, 0),
0x01, 0x21, 0x0100, 0x8101, &buff4, 4);
// Set clock source to Internal
snd_usb_ctl_msg(subs->dev, usb_sndctrlpipe(subs->dev, 0),
0x01, 0x21, 0x0100, 0x8001, &buff1, 1);
// Check whether the change was successful
buff4 = 0;
snd_usb_ctl_msg(subs->dev, usb_rcvctrlpipe(subs->dev, 0),
0x01, 0x21 | USB_DIR_IN, 0x0100, 0x8101, &buff4, 4); if (new_rate != le32_to_cpu(buff4))
dev_warn(&subs->dev->dev, "MBOX3: Couldn't set the sample rate");
}
staticint rme_digiface_set_format_quirk(struct snd_usb_substream *subs)
{ unsignedint cur_rate = subs->data_endpoint->cur_rate;
u16 val; int speed_mode; int id;
for (id = 0; id < ARRAY_SIZE(rme_digiface_rate_table); id++) { if (rme_digiface_rate_table[id] == cur_rate) break;
}
if (id >= ARRAY_SIZE(rme_digiface_rate_table)) return -EINVAL;
/* 2, 3, 4 for 1x, 2x, 4x */
speed_mode = (id >> 2) + 2;
val = (id << 3) | (speed_mode << 12);
/* Set the sample rate */
snd_usb_ctl_msg(subs->stream->chip->dev,
usb_sndctrlpipe(subs->stream->chip->dev, 0),
16, 0x40, val, 0x7078, NULL, 0); return 0;
}
void snd_usb_set_format_quirk(struct snd_usb_substream *subs, conststruct audioformat *fmt)
{ switch (subs->stream->chip->usb_id) { case USB_ID(0x041e, 0x3f02): /* E-Mu 0202 USB */ case USB_ID(0x041e, 0x3f04): /* E-Mu 0404 USB */ case USB_ID(0x041e, 0x3f0a): /* E-Mu Tracker Pre */ case USB_ID(0x041e, 0x3f19): /* E-Mu 0204 USB */
set_format_emu_quirk(subs, fmt); break; case USB_ID(0x534d, 0x0021): /* MacroSilicon MS2100/MS2106 */ case USB_ID(0x534d, 0x2109): /* MacroSilicon MS2109 */
subs->stream_offset_adj = 2; break; case USB_ID(0x2b73, 0x000a): /* Pioneer DJM-900NXS2 */ case USB_ID(0x2b73, 0x0013): /* Pioneer DJM-450 */ case USB_ID(0x2b73, 0x0034): /* Pioneer DJM-V10 */
pioneer_djm_set_format_quirk(subs, 0x0082); break; case USB_ID(0x08e4, 0x017f): /* Pioneer DJM-750 */ case USB_ID(0x08e4, 0x0163): /* Pioneer DJM-850 */
pioneer_djm_set_format_quirk(subs, 0x0086); break; case USB_ID(0x0dba, 0x5000):
mbox3_set_format_quirk(subs, fmt); /* Digidesign Mbox 3 */ break; case USB_ID(0x2a39, 0x3f8c): /* RME Digiface USB */ case USB_ID(0x2a39, 0x3fa0): /* RME Digiface USB (alternate) */
rme_digiface_set_format_quirk(subs); break;
}
}
int snd_usb_select_mode_quirk(struct snd_usb_audio *chip, conststruct audioformat *fmt)
{ struct usb_device *dev = chip->dev; int err;
if (chip->quirk_flags & QUIRK_FLAG_ITF_USB_DSD_DAC) { /* First switch to alt set 0, otherwise the mode switch cmd * will not be accepted by the DAC
*/
err = usb_set_interface(dev, fmt->iface, 0); if (err < 0) return err;
msleep(20); /* Delay needed after setting the interface */
void snd_usb_endpoint_start_quirk(struct snd_usb_endpoint *ep)
{ /* * "Playback Design" products send bogus feedback data at the start * of the stream. Ignore them.
*/ if (USB_ID_VENDOR(ep->chip->usb_id) == 0x23ba &&
ep->type == SND_USB_ENDPOINT_TYPE_SYNC)
ep->skip_packets = 4;
/* * 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) ||
ep->chip->usb_id == USB_ID(0x0763, 0x2031)) &&
ep->type == SND_USB_ENDPOINT_TYPE_DATA)
ep->skip_packets = 16;
/* Work around devices that report unreasonable feedback data */ if ((ep->chip->usb_id == USB_ID(0x0644, 0x8038) || /* TEAC UD-H01 */
ep->chip->usb_id == USB_ID(0x1852, 0x5034)) && /* T+A Dac8 */
ep->syncmaxsize == 4)
ep->tenor_fb_quirk = 1;
}
/* * snd_usb_interface_dsd_format_quirks() is called from format.c to * augment the PCM format bit-field for DSD types. The UAC standards * don't have a designated bit field to denote DSD-capable interfaces, * hence all hardware that is known to support this format has to be * listed here.
*/
u64 snd_usb_interface_dsd_format_quirks(struct snd_usb_audio *chip, struct audioformat *fp, unsignedint sample_bytes)
{ struct usb_interface *iface;
/* Playback Designs */ if (USB_ID_VENDOR(chip->usb_id) == 0x23ba &&
USB_ID_PRODUCT(chip->usb_id) < 0x0110) { switch (fp->altsetting) { case 1:
fp->dsd_dop = true; return SNDRV_PCM_FMTBIT_DSD_U16_LE; case 2:
fp->dsd_bitrev = true; return SNDRV_PCM_FMTBIT_DSD_U8; case 3:
fp->dsd_bitrev = true; return SNDRV_PCM_FMTBIT_DSD_U16_LE;
}
}
/* XMOS based USB DACs */ switch (chip->usb_id) { case USB_ID(0x139f, 0x5504): /* Nagra DAC */ case USB_ID(0x20b1, 0x3089): /* Mola-Mola DAC */ case USB_ID(0x2522, 0x0007): /* LH Labs Geek Out 1V5 */ case USB_ID(0x2522, 0x0009): /* LH Labs Geek Pulse X Inifinity 2V0 */ case USB_ID(0x2522, 0x0012): /* LH Labs VI DAC Infinity */ case USB_ID(0x2772, 0x0230): /* Pro-Ject Pre Box S2 Digital */ if (fp->altsetting == 2) return SNDRV_PCM_FMTBIT_DSD_U32_BE; break;
case USB_ID(0x0d8c, 0x0316): /* Hegel HD12 DSD */ case USB_ID(0x10cb, 0x0103): /* The Bit Opus #3; with fp->dsd_raw */ case USB_ID(0x16d0, 0x06b2): /* NuPrime DAC-10 */ case USB_ID(0x16d0, 0x06b4): /* NuPrime Audio HD-AVP/AVA */ case USB_ID(0x16d0, 0x0733): /* Furutech ADL Stratos */ case USB_ID(0x16d0, 0x09d8): /* NuPrime IDA-8 */ case USB_ID(0x16d0, 0x09db): /* NuPrime Audio DAC-9 */ case USB_ID(0x16d0, 0x09dd): /* Encore mDSD */ case USB_ID(0x1db5, 0x0003): /* Bryston BDA3 */ case USB_ID(0x20a0, 0x4143): /* WaveIO USB Audio 2.0 */ case USB_ID(0x22e1, 0xca01): /* HDTA Serenade DSD */ case USB_ID(0x249c, 0x9326): /* M2Tech Young MkIII */ case USB_ID(0x2616, 0x0106): /* PS Audio NuWave DAC */ case USB_ID(0x2622, 0x0041): /* Audiolab M-DAC+ */ case USB_ID(0x278b, 0x5100): /* Rotel RC-1590 */ case USB_ID(0x27f7, 0x3002): /* W4S DAC-2v2SE */ case USB_ID(0x29a2, 0x0086): /* Mutec MC3+ USB */ case USB_ID(0x6b42, 0x0042): /* MSB Technology */ if (fp->altsetting == 3) return SNDRV_PCM_FMTBIT_DSD_U32_BE; break;
/* Amanero Combo384 USB based DACs with native DSD support */ case USB_ID(0x16d0, 0x071a): /* Amanero - Combo384 */ if (fp->altsetting == 2) { switch (le16_to_cpu(chip->dev->descriptor.bcdDevice)) { case 0x199: return SNDRV_PCM_FMTBIT_DSD_U32_LE; case 0x19b: case 0x203: return SNDRV_PCM_FMTBIT_DSD_U32_BE; default: break;
}
} break; case USB_ID(0x16d0, 0x0a23): if (fp->altsetting == 2) return SNDRV_PCM_FMTBIT_DSD_U32_BE; break;
default: break;
}
/* ITF-USB DSD based DACs */ if (chip->quirk_flags & QUIRK_FLAG_ITF_USB_DSD_DAC) {
iface = usb_ifnum_to_if(chip->dev, fp->iface);
/* Altsetting 2 support native DSD if the num of altsets is * three (0-2), * Altsetting 3 support native DSD if the num of altsets is * four (0-3).
*/ if (fp->altsetting == iface->num_altsetting - 1) return SNDRV_PCM_FMTBIT_DSD_U32_BE;
}
/* Mostly generic method to detect many DSD-capable implementations */ if ((chip->quirk_flags & QUIRK_FLAG_DSD_RAW) && fp->dsd_raw) return SNDRV_PCM_FMTBIT_DSD_U32_BE;
return 0;
}
void snd_usb_audioformat_attributes_quirk(struct snd_usb_audio *chip, struct audioformat *fp, int stream)
{ switch (chip->usb_id) { case USB_ID(0x0a92, 0x0053): /* AudioTrak Optoplay */ /* Optoplay sets the sample rate attribute although * it seems not supporting it in fact.
*/
fp->attributes &= ~UAC_EP_CS_ATTR_SAMPLE_RATE; break; case USB_ID(0x041e, 0x3020): /* Creative SB Audigy 2 NX */ case USB_ID(0x0763, 0x2003): /* M-Audio Audiophile USB */ /* doesn't set the sample rate attribute, but supports it */
fp->attributes |= UAC_EP_CS_ATTR_SAMPLE_RATE; break; case USB_ID(0x0763, 0x2001): /* M-Audio Quattro USB */ case USB_ID(0x0763, 0x2012): /* M-Audio Fast Track Pro USB */ case USB_ID(0x047f, 0x0ca1): /* plantronics headset */ case USB_ID(0x077d, 0x07af): /* Griffin iMic (note that there is
an older model 77d:223) */ /* * plantronics headset and Griffin iMic have set adaptive-in * although it's really not...
*/
fp->ep_attr &= ~USB_ENDPOINT_SYNCTYPE; if (stream == SNDRV_PCM_STREAM_PLAYBACK)
fp->ep_attr |= USB_ENDPOINT_SYNC_ADAPTIVE; else
fp->ep_attr |= USB_ENDPOINT_SYNC_SYNC; break; case USB_ID(0x07fd, 0x0004): /* MOTU MicroBook IIc */ /* * MaxPacketsOnly attribute is erroneously set in endpoint * descriptors. As a result this card produces noise with * all sample rates other than 96 kHz.
*/
fp->attributes &= ~UAC_EP_CS_ATTR_FILL_MAX; break; case USB_ID(0x1224, 0x2a25): /* Jieli Technology USB PHY 2.0 */ /* mic works only when ep packet size is set to wMaxPacketSize */
fp->attributes |= UAC_EP_CS_ATTR_FILL_MAX; break; case USB_ID(0x3511, 0x2b1e): /* Opencomm2 UC USB Bluetooth dongle */ /* mic works only when ep pitch control is not set */ if (stream == SNDRV_PCM_STREAM_CAPTURE)
fp->attributes &= ~UAC_EP_CS_ATTR_PITCH_CONTROL; break;
}
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.