[PATCH 00/15] ALSA: usb-audio: Introduce and convert to quirk_flags
As more and more device-specific workarounds came up and gathered in various places, it becomes harder to manage. Now it's time to clean up and collect workarounds more consistently and make them more easily applicable.
This patch set introduces a new bitmap flags, quirk_flags, to contain various device-specific quirks. Those are separate one from the quirks in quirks-table.h; the quirks-table.h entries are for more intrusive stuff that needs the descriptor override, while the new quirk_flags is for easier ones that are tied with the vendor:product IDs.
Takashi
===
Takashi Iwai (15): ALSA: usb-audio: Introduce quirk_flags field ALSA: usb-audio: Move media-controller API quirk into quirk_flags ALSA: usb-audio: Move txfr_quirk handling to quirk_flags ALSA: usb-audio: Move tx_length quirk handling to quirk_flags ALSA: usb-audio: Move playback_first flag into quirk_flags ALSA: usb-audio: Move clock setup quirk into quirk_flags ALSA: usb-audio: Move ITF-USB DSD quirk handling into quirk_flags ALSA: usb-audio: Move control message delay quirk into quirk_flags ALSA: usb-audio: Move interface setup delay into quirk_flags ALSA: usb-audio: Move rate validation quirk into quirk_flags ALSA: usb-audio: Move autosuspend quirk into quirk_flags ALSA: usb-audio: Move ignore_ctl_error check into quirk_flags ALSA: usb-audio: Move generic DSD raw detection into quirk_flags ALSA: usb-audio: Add quirk_flags module option ALSA: doc: Add the description of quirk_flags option for snd-usb-audio
Documentation/sound/alsa-configuration.rst | 26 +- sound/usb/card.c | 42 ++- sound/usb/clock.c | 15 +- sound/usb/endpoint.c | 14 +- sound/usb/format.c | 6 +- sound/usb/implicit.c | 6 +- sound/usb/mixer.c | 6 +- sound/usb/mixer.h | 3 +- sound/usb/mixer_maps.c | 22 -- sound/usb/quirks-table.h | 70 +--- sound/usb/quirks.c | 359 +++++++++++---------- sound/usb/quirks.h | 5 +- sound/usb/stream.c | 4 +- sound/usb/usbaudio.h | 65 +++- 14 files changed, 341 insertions(+), 302 deletions(-)
As more and more device-specific workarounds came up and gathered in various places, it becomes harder to manage. Now it's time to clean up and collect workarounds more consistently and make them more easily applicable.
This patch is the first step for that: a new field quirk_flags is introduced in snd_usb_audio struct to contain the bit flags for various device-specific quirks. Those are separate one from the quirks in quirks-table.h; the quirks-table.h entries are for more intrusive stuff that needs the descriptor override, while the new quirk_flags is for easier ones that are tied with the vendor:product IDs.
In this patch, as the first example, we convert the list of devices and vendors to ignore GET_SAMPLE_RATE, formerly defined in snb_usb_get_sample_rate_quirk().
Signed-off-by: Takashi Iwai tiwai@suse.de --- sound/usb/card.c | 3 +- sound/usb/clock.c | 2 +- sound/usb/quirks.c | 98 ++++++++++++++++++++++++++++++-------------- sound/usb/quirks.h | 4 +- sound/usb/usbaudio.h | 11 +++++ 5 files changed, 84 insertions(+), 34 deletions(-)
diff --git a/sound/usb/card.c b/sound/usb/card.c index a1f8c3a026f5..8fee90b9776e 100644 --- a/sound/usb/card.c +++ b/sound/usb/card.c @@ -610,6 +610,8 @@ static int snd_usb_audio_create(struct usb_interface *intf, INIT_LIST_HEAD(&chip->midi_list); INIT_LIST_HEAD(&chip->mixer_list);
+ snd_usb_init_quirk_flags(chip); + card->private_free = snd_usb_audio_free;
strcpy(card->driver, "USB-Audio"); @@ -789,7 +791,6 @@ static int usb_audio_probe(struct usb_interface *intf, if (!chip->ctrl_intf) chip->ctrl_intf = alts;
- chip->txfr_quirk = 0; err = 1; /* continue */ if (quirk && quirk->ifnum != QUIRK_NO_INTERFACE) { /* need some special handlings */ diff --git a/sound/usb/clock.c b/sound/usb/clock.c index 14456f61539e..90b03ae03574 100644 --- a/sound/usb/clock.c +++ b/sound/usb/clock.c @@ -426,7 +426,7 @@ static int set_sample_rate_v1(struct snd_usb_audio *chip,
/* Don't check the sample rate for devices which we know don't * support reading */ - if (snd_usb_get_sample_rate_quirk(chip)) + if (chip->quirk_flags & QUIRK_FLAG_GET_SAMPLE_RATE) return 0; /* the firmware is likely buggy, don't repeat to fail too many times */ if (chip->sample_rate_read_error > 2) diff --git a/sound/usb/quirks.c b/sound/usb/quirks.c index 326d1b0ea5e6..9c3d234c8b32 100644 --- a/sound/usb/quirks.c +++ b/sound/usb/quirks.c @@ -1518,36 +1518,6 @@ void snd_usb_set_format_quirk(struct snd_usb_substream *subs, } }
-bool snd_usb_get_sample_rate_quirk(struct snd_usb_audio *chip) -{ - /* devices which do not support reading the sample rate. */ - switch (chip->usb_id) { - case USB_ID(0x041e, 0x4080): /* Creative Live Cam VF0610 */ - case USB_ID(0x04d8, 0xfeea): /* Benchmark DAC1 Pre */ - case USB_ID(0x0556, 0x0014): /* Phoenix Audio TMX320VC */ - case USB_ID(0x05a3, 0x9420): /* ELP HD USB Camera */ - case USB_ID(0x05a7, 0x1020): /* Bose Companion 5 */ - case USB_ID(0x074d, 0x3553): /* Outlaw RR2150 (Micronas UAC3553B) */ - case USB_ID(0x1395, 0x740a): /* Sennheiser DECT */ - case USB_ID(0x1901, 0x0191): /* GE B850V3 CP2114 audio interface */ - case USB_ID(0x21b4, 0x0081): /* AudioQuest DragonFly */ - case USB_ID(0x2912, 0x30c8): /* Audioengine D1 */ - case USB_ID(0x413c, 0xa506): /* Dell AE515 sound bar */ - case USB_ID(0x046d, 0x084c): /* Logitech ConferenceCam Connect */ - return true; - } - - /* devices of these vendors don't support reading rate, either */ - switch (USB_ID_VENDOR(chip->usb_id)) { - case 0x045e: /* MS Lifecam */ - case 0x047f: /* Plantronics */ - case 0x1de7: /* Phoenix Audio */ - return true; - } - - return false; -} - /* ITF-USB DSD based DACs need a vendor cmd to switch * between PCM and native DSD mode */ @@ -1916,3 +1886,71 @@ bool snd_usb_registration_quirk(struct snd_usb_audio *chip, int iface) /* Register as normal */ return false; } + +/* + * driver behavior quirk flags + */ +struct usb_audio_quirk_flags_table { + u32 id; + u32 flags; +}; + +#define DEVICE_FLG(vid, pid, _flags) \ + { .id = USB_ID(vid, pid), .flags = (_flags) } +#define VENDOR_FLG(vid, _flags) DEVICE_FLG(vid, 0, _flags) + +static const struct usb_audio_quirk_flags_table quirk_flags_table[] = { + /* Device matches */ + DEVICE_FLG(0x041e, 0x4080, /* Creative Live Cam VF0610 */ + QUIRK_FLAG_GET_SAMPLE_RATE), + DEVICE_FLG(0x046d, 0x084c, /* Logitech ConferenceCam Connect */ + QUIRK_FLAG_GET_SAMPLE_RATE), + DEVICE_FLG(0x04d8, 0xfeea, /* Benchmark DAC1 Pre */ + QUIRK_FLAG_GET_SAMPLE_RATE), + DEVICE_FLG(0x0556, 0x0014, /* Phoenix Audio TMX320VC */ + QUIRK_FLAG_GET_SAMPLE_RATE), + DEVICE_FLG(0x05a3, 0x9420, /* ELP HD USB Camera */ + QUIRK_FLAG_GET_SAMPLE_RATE), + DEVICE_FLG(0x05a7, 0x1020, /* Bose Companion 5 */ + QUIRK_FLAG_GET_SAMPLE_RATE), + DEVICE_FLG(0x074d, 0x3553, /* Outlaw RR2150 (Micronas UAC3553B) */ + QUIRK_FLAG_GET_SAMPLE_RATE), + DEVICE_FLG(0x1395, 0x740a, /* Sennheiser DECT */ + QUIRK_FLAG_GET_SAMPLE_RATE), + DEVICE_FLG(0x1901, 0x0191, /* GE B850V3 CP2114 audio interface */ + QUIRK_FLAG_GET_SAMPLE_RATE), + DEVICE_FLG(0x21b4, 0x0081, /* AudioQuest DragonFly */ + QUIRK_FLAG_GET_SAMPLE_RATE), + DEVICE_FLG(0x2912, 0x30c8, /* Audioengine D1 */ + QUIRK_FLAG_GET_SAMPLE_RATE), + DEVICE_FLG(0x413c, 0xa506, /* Dell AE515 sound bar */ + QUIRK_FLAG_GET_SAMPLE_RATE), + + /* Vendor matches */ + VENDOR_FLG(0x045e, /* MS Lifecam */ + QUIRK_FLAG_GET_SAMPLE_RATE), + VENDOR_FLG(0x047f, /* Plantronics */ + QUIRK_FLAG_GET_SAMPLE_RATE), + VENDOR_FLG(0x1de7, /* Phoenix Audio */ + QUIRK_FLAG_GET_SAMPLE_RATE), + + {} /* terminator */ +}; + +void snd_usb_init_quirk_flags(struct snd_usb_audio *chip) +{ + const struct usb_audio_quirk_flags_table *p; + + for (p = quirk_flags_table; p->id; p++) { + if (chip->usb_id == p->id || + (!USB_ID_PRODUCT(p->id) && + USB_ID_VENDOR(chip->usb_id) == USB_ID_VENDOR(p->id))) { + usb_audio_dbg(chip, + "Set quirk_flags 0x%x for device %04x:%04x\n", + p->flags, USB_ID_VENDOR(chip->usb_id), + USB_ID_PRODUCT(chip->usb_id)); + chip->quirk_flags |= p->flags; + return; + } + } +} diff --git a/sound/usb/quirks.h b/sound/usb/quirks.h index 67a02303c820..0a49e074ae6a 100644 --- a/sound/usb/quirks.h +++ b/sound/usb/quirks.h @@ -28,8 +28,6 @@ int snd_usb_apply_boot_quirk_once(struct usb_device *dev, void snd_usb_set_format_quirk(struct snd_usb_substream *subs, const struct audioformat *fmt);
-bool snd_usb_get_sample_rate_quirk(struct snd_usb_audio *chip); - int snd_usb_is_big_endian_format(struct snd_usb_audio *chip, const struct audioformat *fp);
@@ -53,4 +51,6 @@ void snd_usb_audioformat_attributes_quirk(struct snd_usb_audio *chip,
bool snd_usb_registration_quirk(struct snd_usb_audio *chip, int iface);
+void snd_usb_init_quirk_flags(struct snd_usb_audio *chip); + #endif /* __USBAUDIO_QUIRKS_H */ diff --git a/sound/usb/usbaudio.h b/sound/usb/usbaudio.h index 538831cbd925..37195ac26ac9 100644 --- a/sound/usb/usbaudio.h +++ b/sound/usb/usbaudio.h @@ -34,6 +34,7 @@ struct snd_usb_audio { atomic_t shutdown; atomic_t usage_count; wait_queue_head_t shutdown_wait; + unsigned int quirk_flags; unsigned int txfr_quirk:1; /* Subframe boundaries on transfers */ unsigned int tx_length_quirk:1; /* Put length specifier in transfers */ unsigned int need_delayed_register:1; /* warn for delayed registration */ @@ -129,4 +130,14 @@ void snd_usb_unlock_shutdown(struct snd_usb_audio *chip); extern bool snd_usb_use_vmalloc; extern bool snd_usb_skip_validation;
+/* + * Driver behavior quirk flags, stored in chip->quirk_flags + * + * QUIRK_FLAG_GET_SAMPLE_RATE: + * Skip reading sample rate for devices, as some devices behave inconsistently + * or return error + */ + +#define QUIRK_FLAG_GET_SAMPLE_RATE (1U << 0) + #endif /* __USBAUDIO_H */
The devices that can have media-controller API entries are currently specified via tables in quirks-table.h, as a part of descriptor override. This can fit better to the new quirk_flags, as we just need a matching with the given ID and create the MC entries accordingly.
Signed-off-by: Takashi Iwai tiwai@suse.de --- sound/usb/card.c | 2 +- sound/usb/quirks-table.h | 1 - sound/usb/quirks.c | 34 ++++++++++++++++++++++++++++++++++ sound/usb/usbaudio.h | 4 +++- 4 files changed, 38 insertions(+), 3 deletions(-)
diff --git a/sound/usb/card.c b/sound/usb/card.c index 8fee90b9776e..5f5095890a29 100644 --- a/sound/usb/card.c +++ b/sound/usb/card.c @@ -826,7 +826,7 @@ static int usb_audio_probe(struct usb_interface *intf, goto __error; }
- if (quirk && quirk->shares_media_device) { + if (chip->quirk_flags & QUIRK_FLAG_SHARE_MEDIA_DEVICE) { /* don't want to fail when snd_media_device_create() fails */ snd_media_device_create(chip, intf); } diff --git a/sound/usb/quirks-table.h b/sound/usb/quirks-table.h index 19bb499c17da..d644b31c4c7f 100644 --- a/sound/usb/quirks-table.h +++ b/sound/usb/quirks-table.h @@ -2816,7 +2816,6 @@ YAMAHA_DEVICE(0x7010, "UB99"), .product_name = pname, \ .ifnum = QUIRK_ANY_INTERFACE, \ .type = QUIRK_AUDIO_ALIGN_TRANSFER, \ - .shares_media_device = 1, \ } \ }
diff --git a/sound/usb/quirks.c b/sound/usb/quirks.c index 9c3d234c8b32..798aec4298f4 100644 --- a/sound/usb/quirks.c +++ b/sound/usb/quirks.c @@ -1913,12 +1913,46 @@ static const struct usb_audio_quirk_flags_table quirk_flags_table[] = { QUIRK_FLAG_GET_SAMPLE_RATE), DEVICE_FLG(0x05a7, 0x1020, /* Bose Companion 5 */ QUIRK_FLAG_GET_SAMPLE_RATE), + DEVICE_FLG(0x05e1, 0x0480, /* Hauppauge Woodbury */ + QUIRK_FLAG_SHARE_MEDIA_DEVICE), DEVICE_FLG(0x074d, 0x3553, /* Outlaw RR2150 (Micronas UAC3553B) */ QUIRK_FLAG_GET_SAMPLE_RATE), + DEVICE_FLG(0x0fd9, 0x0008, /* Hauppauge HVR-950Q */ + QUIRK_FLAG_SHARE_MEDIA_DEVICE), DEVICE_FLG(0x1395, 0x740a, /* Sennheiser DECT */ QUIRK_FLAG_GET_SAMPLE_RATE), DEVICE_FLG(0x1901, 0x0191, /* GE B850V3 CP2114 audio interface */ QUIRK_FLAG_GET_SAMPLE_RATE), + DEVICE_FLG(0x2040, 0x7200, /* Hauppauge HVR-950Q */ + QUIRK_FLAG_SHARE_MEDIA_DEVICE), + DEVICE_FLG(0x2040, 0x7201, /* Hauppauge HVR-950Q-MXL */ + QUIRK_FLAG_SHARE_MEDIA_DEVICE), + DEVICE_FLG(0x2040, 0x7210, /* Hauppauge HVR-950Q */ + QUIRK_FLAG_SHARE_MEDIA_DEVICE), + DEVICE_FLG(0x2040, 0x7211, /* Hauppauge HVR-950Q-MXL */ + QUIRK_FLAG_SHARE_MEDIA_DEVICE), + DEVICE_FLG(0x2040, 0x7213, /* Hauppauge HVR-950Q */ + QUIRK_FLAG_SHARE_MEDIA_DEVICE), + DEVICE_FLG(0x2040, 0x7217, /* Hauppauge HVR-950Q */ + QUIRK_FLAG_SHARE_MEDIA_DEVICE), + DEVICE_FLG(0x2040, 0x721b, /* Hauppauge HVR-950Q */ + QUIRK_FLAG_SHARE_MEDIA_DEVICE), + DEVICE_FLG(0x2040, 0x721e, /* Hauppauge HVR-950Q */ + QUIRK_FLAG_SHARE_MEDIA_DEVICE), + DEVICE_FLG(0x2040, 0x721f, /* Hauppauge HVR-950Q */ + QUIRK_FLAG_SHARE_MEDIA_DEVICE), + DEVICE_FLG(0x2040, 0x7240, /* Hauppauge HVR-850 */ + QUIRK_FLAG_SHARE_MEDIA_DEVICE), + DEVICE_FLG(0x2040, 0x7260, /* Hauppauge HVR-950Q */ + QUIRK_FLAG_SHARE_MEDIA_DEVICE), + DEVICE_FLG(0x2040, 0x7270, /* Hauppauge HVR-950Q */ + QUIRK_FLAG_SHARE_MEDIA_DEVICE), + DEVICE_FLG(0x2040, 0x7280, /* Hauppauge HVR-950Q */ + QUIRK_FLAG_SHARE_MEDIA_DEVICE), + DEVICE_FLG(0x2040, 0x7281, /* Hauppauge HVR-950Q-MXL */ + QUIRK_FLAG_SHARE_MEDIA_DEVICE), + DEVICE_FLG(0x2040, 0x8200, /* Hauppauge Woodbury */ + QUIRK_FLAG_SHARE_MEDIA_DEVICE), DEVICE_FLG(0x21b4, 0x0081, /* AudioQuest DragonFly */ QUIRK_FLAG_GET_SAMPLE_RATE), DEVICE_FLG(0x2912, 0x30c8, /* Audioengine D1 */ diff --git a/sound/usb/usbaudio.h b/sound/usb/usbaudio.h index 37195ac26ac9..ece244637798 100644 --- a/sound/usb/usbaudio.h +++ b/sound/usb/usbaudio.h @@ -116,7 +116,6 @@ struct snd_usb_audio_quirk { const char *product_name; int16_t ifnum; uint16_t type; - bool shares_media_device; const void *data; };
@@ -136,8 +135,11 @@ extern bool snd_usb_skip_validation; * QUIRK_FLAG_GET_SAMPLE_RATE: * Skip reading sample rate for devices, as some devices behave inconsistently * or return error + * QUIRK_FLAG_SHARE_MEDIA_DEVICE: + * Create Media Controller API entries */
#define QUIRK_FLAG_GET_SAMPLE_RATE (1U << 0) +#define QUIRK_FLAG_SHARE_MEDIA_DEVICE (1U << 1)
#endif /* __USBAUDIO_H */
The txfr_quirk field was meant for aligning the transfer, and it's set for certain devices in quirks-table.h. Now we can move that stuff also to the new quirk_flags gracefully, and reduce the quirks-table.h entries (that are exposed to module device table).
As the quirks-table.h entries are also with the name string override, provide the corresponding entries to the usb_audio_names[] table, too.
Signed-off-by: Takashi Iwai tiwai@suse.de --- sound/usb/card.c | 21 ++++++++++++++++ sound/usb/quirks-table.h | 52 +--------------------------------------- sound/usb/quirks.c | 52 ++++++++++++++++------------------------ sound/usb/stream.c | 2 +- sound/usb/usbaudio.h | 6 +++-- 5 files changed, 48 insertions(+), 85 deletions(-)
diff --git a/sound/usb/card.c b/sound/usb/card.c index 5f5095890a29..8c32a784f1e4 100644 --- a/sound/usb/card.c +++ b/sound/usb/card.c @@ -378,6 +378,9 @@ static const struct usb_audio_device_name usb_audio_names[] = {
DEVICE_NAME(0x046d, 0x0990, "Logitech, Inc.", "QuickCam Pro 9000"),
+ DEVICE_NAME(0x05e1, 0x0408, "Syntek", "STK1160"), + DEVICE_NAME(0x05e1, 0x0480, "Hauppauge", "Woodbury"), + /* ASUS ROG Strix */ PROFILE_NAME(0x0b05, 0x1917, "Realtek", "ALC1220-VB-DT", "Realtek-ALC1220-VB-Desktop"), @@ -406,6 +409,8 @@ static const struct usb_audio_device_name usb_audio_names[] = { PROFILE_NAME(0x0db0, 0x543d, "Realtek", "ALC1220-VB-DT", "Realtek-ALC1220-VB-Desktop"),
+ DEVICE_NAME(0x0fd9, 0x0008, "Hauppauge", "HVR-950Q"), + /* Stanton/N2IT Final Scratch v1 device ('Scratchamp') */ DEVICE_NAME(0x103d, 0x0100, "Stanton", "ScratchAmp"), DEVICE_NAME(0x103d, 0x0101, "Stanton", "ScratchAmp"), @@ -424,6 +429,22 @@ static const struct usb_audio_device_name usb_audio_names[] = { PROFILE_NAME(0x26ce, 0x0a01, "Realtek", "ALC1220-VB-DT", "Realtek-ALC1220-VB-Desktop"),
+ DEVICE_NAME(0x2040, 0x7200, "Hauppauge", "HVR-950Q"), + DEVICE_NAME(0x2040, 0x7201, "Hauppauge", "HVR-950Q-MXL"), + DEVICE_NAME(0x2040, 0x7210, "Hauppauge", "HVR-950Q"), + DEVICE_NAME(0x2040, 0x7211, "Hauppauge", "HVR-950Q-MXL"), + DEVICE_NAME(0x2040, 0x7213, "Hauppauge", "HVR-950Q"), + DEVICE_NAME(0x2040, 0x7217, "Hauppauge", "HVR-950Q"), + DEVICE_NAME(0x2040, 0x721b, "Hauppauge", "HVR-950Q"), + DEVICE_NAME(0x2040, 0x721e, "Hauppauge", "HVR-950Q"), + DEVICE_NAME(0x2040, 0x721f, "Hauppauge", "HVR-950Q"), + DEVICE_NAME(0x2040, 0x7240, "Hauppauge", "HVR-850"), + DEVICE_NAME(0x2040, 0x7260, "Hauppauge", "HVR-950Q"), + DEVICE_NAME(0x2040, 0x7270, "Hauppauge", "HVR-950Q"), + DEVICE_NAME(0x2040, 0x7280, "Hauppauge", "HVR-950Q"), + DEVICE_NAME(0x2040, 0x7281, "Hauppauge", "HVR-950Q-MXL"), + DEVICE_NAME(0x2040, 0x8200, "Hauppauge", "Woodbury"), + { } /* terminator */ };
diff --git a/sound/usb/quirks-table.h b/sound/usb/quirks-table.h index d644b31c4c7f..b5e82363cf47 100644 --- a/sound/usb/quirks-table.h +++ b/sound/usb/quirks-table.h @@ -2802,52 +2802,6 @@ YAMAHA_DEVICE(0x7010, "UB99"), } },
-/* - * Auvitek au0828 devices with audio interface. - * This should be kept in sync with drivers/media/usb/au0828/au0828-cards.c - * Please notice that some drivers are DVB only, and don't need to be - * here. That's the case, for example, of DVICO_FUSIONHDTV7. - */ - -#define AU0828_DEVICE(vid, pid, vname, pname) { \ - USB_AUDIO_DEVICE(vid, pid), \ - .driver_info = (unsigned long) &(const struct snd_usb_audio_quirk) { \ - .vendor_name = vname, \ - .product_name = pname, \ - .ifnum = QUIRK_ANY_INTERFACE, \ - .type = QUIRK_AUDIO_ALIGN_TRANSFER, \ - } \ -} - -AU0828_DEVICE(0x2040, 0x7200, "Hauppauge", "HVR-950Q"), -AU0828_DEVICE(0x2040, 0x7240, "Hauppauge", "HVR-850"), -AU0828_DEVICE(0x2040, 0x7210, "Hauppauge", "HVR-950Q"), -AU0828_DEVICE(0x2040, 0x7217, "Hauppauge", "HVR-950Q"), -AU0828_DEVICE(0x2040, 0x721b, "Hauppauge", "HVR-950Q"), -AU0828_DEVICE(0x2040, 0x721e, "Hauppauge", "HVR-950Q"), -AU0828_DEVICE(0x2040, 0x721f, "Hauppauge", "HVR-950Q"), -AU0828_DEVICE(0x2040, 0x7280, "Hauppauge", "HVR-950Q"), -AU0828_DEVICE(0x0fd9, 0x0008, "Hauppauge", "HVR-950Q"), -AU0828_DEVICE(0x2040, 0x7201, "Hauppauge", "HVR-950Q-MXL"), -AU0828_DEVICE(0x2040, 0x7211, "Hauppauge", "HVR-950Q-MXL"), -AU0828_DEVICE(0x2040, 0x7281, "Hauppauge", "HVR-950Q-MXL"), -AU0828_DEVICE(0x05e1, 0x0480, "Hauppauge", "Woodbury"), -AU0828_DEVICE(0x2040, 0x8200, "Hauppauge", "Woodbury"), -AU0828_DEVICE(0x2040, 0x7260, "Hauppauge", "HVR-950Q"), -AU0828_DEVICE(0x2040, 0x7213, "Hauppauge", "HVR-950Q"), -AU0828_DEVICE(0x2040, 0x7270, "Hauppauge", "HVR-950Q"), - -/* Syntek STK1160 */ -{ - USB_AUDIO_DEVICE(0x05e1, 0x0408), - .driver_info = (unsigned long) &(const struct snd_usb_audio_quirk) { - .vendor_name = "Syntek", - .product_name = "STK1160", - .ifnum = QUIRK_ANY_INTERFACE, - .type = QUIRK_AUDIO_ALIGN_TRANSFER - } -}, - /* Digidesign Mbox */ { /* Thanks to Clemens Ladisch clemens@ladisch.de */ @@ -3810,7 +3764,7 @@ AU0828_DEVICE(0x2040, 0x7270, "Hauppauge", "HVR-950Q"), * MacroSilicon MS2109 based HDMI capture cards * * These claim 96kHz 1ch in the descriptors, but are actually 48kHz 2ch. - * They also need QUIRK_AUDIO_ALIGN_TRANSFER, which makes one wonder if + * They also need QUIRK_FLAG_ALIGN_TRANSFER, which makes one wonder if * they pretend to be 96kHz mono as a workaround for stereo being broken * by that... * @@ -3825,10 +3779,6 @@ AU0828_DEVICE(0x2040, 0x7270, "Hauppauge", "HVR-950Q"), .ifnum = QUIRK_ANY_INTERFACE, .type = QUIRK_COMPOSITE, .data = &(const struct snd_usb_audio_quirk[]) { - { - .ifnum = 2, - .type = QUIRK_AUDIO_ALIGN_TRANSFER, - }, { .ifnum = 2, .type = QUIRK_AUDIO_STANDARD_MIXER, diff --git a/sound/usb/quirks.c b/sound/usb/quirks.c index 798aec4298f4..5dce068f613a 100644 --- a/sound/usb/quirks.c +++ b/sound/usb/quirks.c @@ -75,19 +75,6 @@ static int ignore_interface_quirk(struct snd_usb_audio *chip, }
-/* - * Allow alignment on audio sub-slot (channel samples) rather than - * on audio slots (audio frames) - */ -static int create_align_transfer_quirk(struct snd_usb_audio *chip, - struct usb_interface *iface, - struct usb_driver *driver, - const struct snd_usb_audio_quirk *quirk) -{ - chip->txfr_quirk = 1; - return 1; /* Continue with creating streams and mixer */ -} - static int create_any_midi_quirk(struct snd_usb_audio *chip, struct usb_interface *intf, struct usb_driver *driver, @@ -595,7 +582,6 @@ int snd_usb_create_quirk(struct snd_usb_audio *chip, [QUIRK_AUDIO_STANDARD_INTERFACE] = create_standard_audio_quirk, [QUIRK_AUDIO_FIXED_ENDPOINT] = create_fixed_stream_quirk, [QUIRK_AUDIO_EDIROL_UAXX] = create_uaxx_quirk, - [QUIRK_AUDIO_ALIGN_TRANSFER] = create_align_transfer_quirk, [QUIRK_AUDIO_STANDARD_MIXER] = create_standard_mixer_quirk, [QUIRK_SETUP_DISABLE_AUTOSUSPEND] = setup_disable_autosuspend, }; @@ -1913,52 +1899,56 @@ static const struct usb_audio_quirk_flags_table quirk_flags_table[] = { QUIRK_FLAG_GET_SAMPLE_RATE), DEVICE_FLG(0x05a7, 0x1020, /* Bose Companion 5 */ QUIRK_FLAG_GET_SAMPLE_RATE), + DEVICE_FLG(0x05e1, 0x0408, /* Syntek STK1160 */ + QUIRK_FLAG_ALIGN_TRANSFER), DEVICE_FLG(0x05e1, 0x0480, /* Hauppauge Woodbury */ - QUIRK_FLAG_SHARE_MEDIA_DEVICE), + QUIRK_FLAG_SHARE_MEDIA_DEVICE | QUIRK_FLAG_ALIGN_TRANSFER), DEVICE_FLG(0x074d, 0x3553, /* Outlaw RR2150 (Micronas UAC3553B) */ QUIRK_FLAG_GET_SAMPLE_RATE), DEVICE_FLG(0x0fd9, 0x0008, /* Hauppauge HVR-950Q */ - QUIRK_FLAG_SHARE_MEDIA_DEVICE), + QUIRK_FLAG_SHARE_MEDIA_DEVICE | QUIRK_FLAG_ALIGN_TRANSFER), DEVICE_FLG(0x1395, 0x740a, /* Sennheiser DECT */ QUIRK_FLAG_GET_SAMPLE_RATE), DEVICE_FLG(0x1901, 0x0191, /* GE B850V3 CP2114 audio interface */ QUIRK_FLAG_GET_SAMPLE_RATE), DEVICE_FLG(0x2040, 0x7200, /* Hauppauge HVR-950Q */ - QUIRK_FLAG_SHARE_MEDIA_DEVICE), + QUIRK_FLAG_SHARE_MEDIA_DEVICE | QUIRK_FLAG_ALIGN_TRANSFER), DEVICE_FLG(0x2040, 0x7201, /* Hauppauge HVR-950Q-MXL */ - QUIRK_FLAG_SHARE_MEDIA_DEVICE), + QUIRK_FLAG_SHARE_MEDIA_DEVICE | QUIRK_FLAG_ALIGN_TRANSFER), DEVICE_FLG(0x2040, 0x7210, /* Hauppauge HVR-950Q */ - QUIRK_FLAG_SHARE_MEDIA_DEVICE), + QUIRK_FLAG_SHARE_MEDIA_DEVICE | QUIRK_FLAG_ALIGN_TRANSFER), DEVICE_FLG(0x2040, 0x7211, /* Hauppauge HVR-950Q-MXL */ - QUIRK_FLAG_SHARE_MEDIA_DEVICE), + QUIRK_FLAG_SHARE_MEDIA_DEVICE | QUIRK_FLAG_ALIGN_TRANSFER), DEVICE_FLG(0x2040, 0x7213, /* Hauppauge HVR-950Q */ - QUIRK_FLAG_SHARE_MEDIA_DEVICE), + QUIRK_FLAG_SHARE_MEDIA_DEVICE | QUIRK_FLAG_ALIGN_TRANSFER), DEVICE_FLG(0x2040, 0x7217, /* Hauppauge HVR-950Q */ - QUIRK_FLAG_SHARE_MEDIA_DEVICE), + QUIRK_FLAG_SHARE_MEDIA_DEVICE | QUIRK_FLAG_ALIGN_TRANSFER), DEVICE_FLG(0x2040, 0x721b, /* Hauppauge HVR-950Q */ - QUIRK_FLAG_SHARE_MEDIA_DEVICE), + QUIRK_FLAG_SHARE_MEDIA_DEVICE | QUIRK_FLAG_ALIGN_TRANSFER), DEVICE_FLG(0x2040, 0x721e, /* Hauppauge HVR-950Q */ - QUIRK_FLAG_SHARE_MEDIA_DEVICE), + QUIRK_FLAG_SHARE_MEDIA_DEVICE | QUIRK_FLAG_ALIGN_TRANSFER), DEVICE_FLG(0x2040, 0x721f, /* Hauppauge HVR-950Q */ - QUIRK_FLAG_SHARE_MEDIA_DEVICE), + QUIRK_FLAG_SHARE_MEDIA_DEVICE | QUIRK_FLAG_ALIGN_TRANSFER), DEVICE_FLG(0x2040, 0x7240, /* Hauppauge HVR-850 */ - QUIRK_FLAG_SHARE_MEDIA_DEVICE), + QUIRK_FLAG_SHARE_MEDIA_DEVICE | QUIRK_FLAG_ALIGN_TRANSFER), DEVICE_FLG(0x2040, 0x7260, /* Hauppauge HVR-950Q */ - QUIRK_FLAG_SHARE_MEDIA_DEVICE), + QUIRK_FLAG_SHARE_MEDIA_DEVICE | QUIRK_FLAG_ALIGN_TRANSFER), DEVICE_FLG(0x2040, 0x7270, /* Hauppauge HVR-950Q */ - QUIRK_FLAG_SHARE_MEDIA_DEVICE), + QUIRK_FLAG_SHARE_MEDIA_DEVICE | QUIRK_FLAG_ALIGN_TRANSFER), DEVICE_FLG(0x2040, 0x7280, /* Hauppauge HVR-950Q */ - QUIRK_FLAG_SHARE_MEDIA_DEVICE), + QUIRK_FLAG_SHARE_MEDIA_DEVICE | QUIRK_FLAG_ALIGN_TRANSFER), DEVICE_FLG(0x2040, 0x7281, /* Hauppauge HVR-950Q-MXL */ - QUIRK_FLAG_SHARE_MEDIA_DEVICE), + QUIRK_FLAG_SHARE_MEDIA_DEVICE | QUIRK_FLAG_ALIGN_TRANSFER), DEVICE_FLG(0x2040, 0x8200, /* Hauppauge Woodbury */ - QUIRK_FLAG_SHARE_MEDIA_DEVICE), + QUIRK_FLAG_SHARE_MEDIA_DEVICE | QUIRK_FLAG_ALIGN_TRANSFER), DEVICE_FLG(0x21b4, 0x0081, /* AudioQuest DragonFly */ QUIRK_FLAG_GET_SAMPLE_RATE), DEVICE_FLG(0x2912, 0x30c8, /* Audioengine D1 */ QUIRK_FLAG_GET_SAMPLE_RATE), DEVICE_FLG(0x413c, 0xa506, /* Dell AE515 sound bar */ QUIRK_FLAG_GET_SAMPLE_RATE), + DEVICE_FLG(0x534d, 0x2109, /* MacroSilicon MS2109 */ + QUIRK_FLAG_ALIGN_TRANSFER),
/* Vendor matches */ VENDOR_FLG(0x045e, /* MS Lifecam */ diff --git a/sound/usb/stream.c b/sound/usb/stream.c index ee9aa1dcf0d8..541ab19101eb 100644 --- a/sound/usb/stream.c +++ b/sound/usb/stream.c @@ -89,7 +89,7 @@ static void snd_usb_init_substream(struct snd_usb_stream *as, subs->stream = as; subs->direction = stream; subs->dev = as->chip->dev; - subs->txfr_quirk = as->chip->txfr_quirk; + subs->txfr_quirk = !!(as->chip->quirk_flags & QUIRK_FLAG_ALIGN_TRANSFER); subs->tx_length_quirk = as->chip->tx_length_quirk; subs->speed = snd_usb_get_speed(subs->dev); subs->pkt_offset_adj = 0; diff --git a/sound/usb/usbaudio.h b/sound/usb/usbaudio.h index ece244637798..170e96865061 100644 --- a/sound/usb/usbaudio.h +++ b/sound/usb/usbaudio.h @@ -35,7 +35,6 @@ struct snd_usb_audio { atomic_t usage_count; wait_queue_head_t shutdown_wait; unsigned int quirk_flags; - unsigned int txfr_quirk:1; /* Subframe boundaries on transfers */ unsigned int tx_length_quirk:1; /* Put length specifier in transfers */ unsigned int need_delayed_register:1; /* warn for delayed registration */ unsigned int playback_first:1; /* for implicit fb: don't wait for the first capture URBs */ @@ -103,7 +102,6 @@ enum quirk_type { QUIRK_AUDIO_STANDARD_INTERFACE, QUIRK_AUDIO_FIXED_ENDPOINT, QUIRK_AUDIO_EDIROL_UAXX, - QUIRK_AUDIO_ALIGN_TRANSFER, QUIRK_AUDIO_STANDARD_MIXER, QUIRK_SETUP_FMT_AFTER_RESUME, QUIRK_SETUP_DISABLE_AUTOSUSPEND, @@ -137,9 +135,13 @@ extern bool snd_usb_skip_validation; * or return error * QUIRK_FLAG_SHARE_MEDIA_DEVICE: * Create Media Controller API entries + * QUIRK_FLAG_ALIGN_TRANSFER: + * Allow alignment on audio sub-slot (channel samples) rather than on audio + * slots (audio frames) */
#define QUIRK_FLAG_GET_SAMPLE_RATE (1U << 0) #define QUIRK_FLAG_SHARE_MEDIA_DEVICE (1U << 1) +#define QUIRK_FLAG_ALIGN_TRANSFER (1U << 2)
#endif /* __USBAUDIO_H */
There is another quirk for the transfer, and that's currently specific to Zoom R16/24, handled in create_standard_audio_quirk(). Let's move this also to the new quirk_flags.
Signed-off-by: Takashi Iwai tiwai@suse.de --- sound/usb/endpoint.c | 9 +++++++-- sound/usb/quirks.c | 5 ++--- sound/usb/stream.c | 2 +- sound/usb/usbaudio.h | 4 +++- 4 files changed, 13 insertions(+), 7 deletions(-)
diff --git a/sound/usb/endpoint.c b/sound/usb/endpoint.c index 4f856771216b..16c36e43c16f 100644 --- a/sound/usb/endpoint.c +++ b/sound/usb/endpoint.c @@ -240,6 +240,11 @@ static void retire_inbound_urb(struct snd_usb_endpoint *ep, call_retire_callback(ep, urb); }
+static inline bool has_tx_length_quirk(struct snd_usb_audio *chip) +{ + return chip->quirk_flags & QUIRK_FLAG_TX_LENGTH; +} + static void prepare_silent_urb(struct snd_usb_endpoint *ep, struct snd_urb_ctx *ctx) { @@ -250,7 +255,7 @@ static void prepare_silent_urb(struct snd_usb_endpoint *ep, int i;
/* For tx_length_quirk, put packet length at start of packet */ - if (ep->chip->tx_length_quirk) + if (has_tx_length_quirk(ep->chip)) extra = sizeof(packet_length);
for (i = 0; i < ctx->packets; ++i) { @@ -952,7 +957,7 @@ static int data_ep_set_params(struct snd_usb_endpoint *ep) unsigned int max_urbs, i; const struct audioformat *fmt = ep->cur_audiofmt; int frame_bits = ep->cur_frame_bytes * 8; - int tx_length_quirk = (chip->tx_length_quirk && + int tx_length_quirk = (has_tx_length_quirk(chip) && usb_pipeout(ep->pipe));
usb_audio_dbg(chip, "Setting params for data EP 0x%x, pipe 0x%x\n", diff --git a/sound/usb/quirks.c b/sound/usb/quirks.c index 5dce068f613a..9f295cb8c3c5 100644 --- a/sound/usb/quirks.c +++ b/sound/usb/quirks.c @@ -95,9 +95,6 @@ static int create_standard_audio_quirk(struct snd_usb_audio *chip, struct usb_interface_descriptor *altsd; int err;
- if (chip->usb_id == USB_ID(0x1686, 0x00dd)) /* Zoom R16/24 */ - chip->tx_length_quirk = 1; - alts = &iface->altsetting[0]; altsd = get_iface_desc(alts); err = snd_usb_parse_audio_interface(chip, altsd->bInterfaceNumber); @@ -1909,6 +1906,8 @@ static const struct usb_audio_quirk_flags_table quirk_flags_table[] = { QUIRK_FLAG_SHARE_MEDIA_DEVICE | QUIRK_FLAG_ALIGN_TRANSFER), DEVICE_FLG(0x1395, 0x740a, /* Sennheiser DECT */ QUIRK_FLAG_GET_SAMPLE_RATE), + DEVICE_FLG(0x1686, 0x00dd, /* Zoom R16/24 */ + QUIRK_FLAG_TX_LENGTH), DEVICE_FLG(0x1901, 0x0191, /* GE B850V3 CP2114 audio interface */ QUIRK_FLAG_GET_SAMPLE_RATE), DEVICE_FLG(0x2040, 0x7200, /* Hauppauge HVR-950Q */ diff --git a/sound/usb/stream.c b/sound/usb/stream.c index 541ab19101eb..ceb93d798182 100644 --- a/sound/usb/stream.c +++ b/sound/usb/stream.c @@ -90,7 +90,7 @@ static void snd_usb_init_substream(struct snd_usb_stream *as, subs->direction = stream; subs->dev = as->chip->dev; subs->txfr_quirk = !!(as->chip->quirk_flags & QUIRK_FLAG_ALIGN_TRANSFER); - subs->tx_length_quirk = as->chip->tx_length_quirk; + subs->tx_length_quirk = !!(as->chip->quirk_flags & QUIRK_FLAG_TX_LENGTH); subs->speed = snd_usb_get_speed(subs->dev); subs->pkt_offset_adj = 0; subs->stream_offset_adj = 0; diff --git a/sound/usb/usbaudio.h b/sound/usb/usbaudio.h index 170e96865061..4003ca99d4ac 100644 --- a/sound/usb/usbaudio.h +++ b/sound/usb/usbaudio.h @@ -35,7 +35,6 @@ struct snd_usb_audio { atomic_t usage_count; wait_queue_head_t shutdown_wait; unsigned int quirk_flags; - unsigned int tx_length_quirk:1; /* Put length specifier in transfers */ unsigned int need_delayed_register:1; /* warn for delayed registration */ unsigned int playback_first:1; /* for implicit fb: don't wait for the first capture URBs */ int num_interfaces; @@ -138,10 +137,13 @@ extern bool snd_usb_skip_validation; * QUIRK_FLAG_ALIGN_TRANSFER: * Allow alignment on audio sub-slot (channel samples) rather than on audio * slots (audio frames) + * QUIRK_TX_LENGTH: + * Add length specifier to transfers */
#define QUIRK_FLAG_GET_SAMPLE_RATE (1U << 0) #define QUIRK_FLAG_SHARE_MEDIA_DEVICE (1U << 1) #define QUIRK_FLAG_ALIGN_TRANSFER (1U << 2) +#define QUIRK_FLAG_TX_LENGTH (1U << 3)
#endif /* __USBAUDIO_H */
The snd_usb_audio.playback_first flag is used by the implicit feedback mode handling, and this can be also moved to quirk_flags.
Signed-off-by: Takashi Iwai tiwai@suse.de --- sound/usb/endpoint.c | 2 +- sound/usb/implicit.c | 6 +++--- sound/usb/usbaudio.h | 4 +++- 3 files changed, 7 insertions(+), 5 deletions(-)
diff --git a/sound/usb/endpoint.c b/sound/usb/endpoint.c index 16c36e43c16f..6016e97faf69 100644 --- a/sound/usb/endpoint.c +++ b/sound/usb/endpoint.c @@ -1382,7 +1382,7 @@ int snd_usb_endpoint_start(struct snd_usb_endpoint *ep) goto __error;
if (snd_usb_endpoint_implicit_feedback_sink(ep) && - !ep->chip->playback_first) { + !(ep->chip->quirk_flags & QUIRK_FLAG_PLAYBACK_FIRST)) { for (i = 0; i < ep->nurbs; i++) { struct snd_urb_ctx *ctx = ep->urb + i; list_add_tail(&ctx->ready_list, &ep->ready_playback_urbs); diff --git a/sound/usb/implicit.c b/sound/usb/implicit.c index 590a0dbba7a2..23767a14d126 100644 --- a/sound/usb/implicit.c +++ b/sound/usb/implicit.c @@ -171,7 +171,7 @@ static int add_roland_implicit_fb(struct snd_usb_audio *chip, if (!usb_endpoint_is_isoc_in(epd) || (epd->bmAttributes & USB_ENDPOINT_SYNCTYPE) != USB_ENDPOINT_SYNC_ASYNC) return 0; - chip->playback_first = 1; + chip->quirk_flags |= QUIRK_FLAG_PLAYBACK_FIRST; return add_implicit_fb_sync_ep(chip, fmt, epd->bEndpointAddress, 0, alts->desc.bInterfaceNumber, alts); } @@ -320,7 +320,7 @@ static int audioformat_implicit_fb_quirk(struct snd_usb_audio *chip, case IMPLICIT_FB_FIXED: return 0; /* no quirk */ case IMPLICIT_FB_BOTH: - chip->playback_first = 1; + chip->quirk_flags |= QUIRK_FLAG_PLAYBACK_FIRST; return add_generic_implicit_fb(chip, fmt, alts); } } @@ -344,7 +344,7 @@ static int audioformat_implicit_fb_quirk(struct snd_usb_audio *chip,
/* Pioneer devices with vendor spec class */ if (is_pioneer_implicit_fb(chip, alts)) { - chip->playback_first = 1; + chip->quirk_flags |= QUIRK_FLAG_PLAYBACK_FIRST; return add_implicit_fb_sync_ep(chip, fmt, get_endpoint(alts, 1)->bEndpointAddress, 1, alts->desc.bInterfaceNumber, diff --git a/sound/usb/usbaudio.h b/sound/usb/usbaudio.h index 4003ca99d4ac..8de2b6c51dad 100644 --- a/sound/usb/usbaudio.h +++ b/sound/usb/usbaudio.h @@ -36,7 +36,6 @@ struct snd_usb_audio { wait_queue_head_t shutdown_wait; unsigned int quirk_flags; unsigned int need_delayed_register:1; /* warn for delayed registration */ - unsigned int playback_first:1; /* for implicit fb: don't wait for the first capture URBs */ int num_interfaces; int num_suspended_intf; int sample_rate_read_error; @@ -139,11 +138,14 @@ extern bool snd_usb_skip_validation; * slots (audio frames) * QUIRK_TX_LENGTH: * Add length specifier to transfers + * QUIRK_FLAG_PLAYBACK_FIRST: + * Start playback stream at first even in implement feedback mode */
#define QUIRK_FLAG_GET_SAMPLE_RATE (1U << 0) #define QUIRK_FLAG_SHARE_MEDIA_DEVICE (1U << 1) #define QUIRK_FLAG_ALIGN_TRANSFER (1U << 2) #define QUIRK_FLAG_TX_LENGTH (1U << 3) +#define QUIRK_FLAG_PLAYBACK_FIRST (1U << 4)
#endif /* __USBAUDIO_H */
There are a couple of device-specific quirks in the clock setup code, and those can be moved gracefully to quirk_flags, too.
Signed-off-by: Takashi Iwai tiwai@suse.de --- sound/usb/clock.c | 13 ++++--------- sound/usb/quirks.c | 4 ++++ sound/usb/usbaudio.h | 6 ++++++ 3 files changed, 14 insertions(+), 9 deletions(-)
diff --git a/sound/usb/clock.c b/sound/usb/clock.c index 90b03ae03574..81d5ce07d548 100644 --- a/sound/usb/clock.c +++ b/sound/usb/clock.c @@ -324,11 +324,8 @@ static int __uac_clock_find_source(struct snd_usb_audio *chip, sources[ret - 1], visited, validate); if (ret > 0) { - /* - * For Samsung USBC Headset (AKG), setting clock selector again - * will result in incorrect default clock setting problems - */ - if (chip->usb_id == USB_ID(0x04e8, 0xa051)) + /* Skip setting clock selector again for some devices */ + if (chip->quirk_flags & QUIRK_FLAG_SKIP_CLOCK_SELECTOR) return ret; err = uac_clock_selector_set_val(chip, entity_id, cur); if (err < 0) @@ -541,10 +538,8 @@ static int set_sample_rate_v2v3(struct snd_usb_audio *chip, */ clock = snd_usb_clock_find_source(chip, fmt, false);
- /* Denon DN-X1600 hardcoded - * Sample rate seems to be set on the hardware itself - */ - if (chip->usb_id == USB_ID(0x154e, 0x500e)) + /* Hardcoded sample rates */ + if (chip->quirk_flags & QUIRK_FLAG_IGNORE_CLOCK_SOURCE) return 0;
if (clock < 0) diff --git a/sound/usb/quirks.c b/sound/usb/quirks.c index 9f295cb8c3c5..a9d8bde416ce 100644 --- a/sound/usb/quirks.c +++ b/sound/usb/quirks.c @@ -1890,6 +1890,8 @@ static const struct usb_audio_quirk_flags_table quirk_flags_table[] = { QUIRK_FLAG_GET_SAMPLE_RATE), DEVICE_FLG(0x04d8, 0xfeea, /* Benchmark DAC1 Pre */ QUIRK_FLAG_GET_SAMPLE_RATE), + DEVICE_FLG(0x04e8, 0xa051, /* Samsung USBC Headset (AKG) */ + QUIRK_FLAG_SKIP_CLOCK_SELECTOR), DEVICE_FLG(0x0556, 0x0014, /* Phoenix Audio TMX320VC */ QUIRK_FLAG_GET_SAMPLE_RATE), DEVICE_FLG(0x05a3, 0x9420, /* ELP HD USB Camera */ @@ -1906,6 +1908,8 @@ static const struct usb_audio_quirk_flags_table quirk_flags_table[] = { QUIRK_FLAG_SHARE_MEDIA_DEVICE | QUIRK_FLAG_ALIGN_TRANSFER), DEVICE_FLG(0x1395, 0x740a, /* Sennheiser DECT */ QUIRK_FLAG_GET_SAMPLE_RATE), + DEVICE_FLG(0x154e, 0x500e, /* Denon DN-X1600 */ + QUIRK_FLAG_IGNORE_CLOCK_SOURCE), DEVICE_FLG(0x1686, 0x00dd, /* Zoom R16/24 */ QUIRK_FLAG_TX_LENGTH), DEVICE_FLG(0x1901, 0x0191, /* GE B850V3 CP2114 audio interface */ diff --git a/sound/usb/usbaudio.h b/sound/usb/usbaudio.h index 8de2b6c51dad..82073ebeac5b 100644 --- a/sound/usb/usbaudio.h +++ b/sound/usb/usbaudio.h @@ -140,6 +140,10 @@ extern bool snd_usb_skip_validation; * Add length specifier to transfers * QUIRK_FLAG_PLAYBACK_FIRST: * Start playback stream at first even in implement feedback mode + * QUIRK_FLAG_SKIP_CLOCK_SELECTOR: + * Skip clock selector setup; the device may reset to invalid state + * QUIRK_FLAG_IGNORE_CLOCK_SOURCE: + * Ignore errors from clock source search; i.e. hardcoded clock */
#define QUIRK_FLAG_GET_SAMPLE_RATE (1U << 0) @@ -147,5 +151,7 @@ extern bool snd_usb_skip_validation; #define QUIRK_FLAG_ALIGN_TRANSFER (1U << 2) #define QUIRK_FLAG_TX_LENGTH (1U << 3) #define QUIRK_FLAG_PLAYBACK_FIRST (1U << 4) +#define QUIRK_FLAG_SKIP_CLOCK_SELECTOR (1U << 5) +#define QUIRK_FLAG_IGNORE_CLOCK_SOURCE (1U << 6)
#endif /* __USBAUDIO_H */
The devices with ITF-USB DSD type are listed in another function, and this can be integrated into the quirk_flags easily.
Signed-off-by: Takashi Iwai tiwai@suse.de --- sound/usb/quirks.c | 41 +++++++++++++++++++---------------------- sound/usb/usbaudio.h | 4 ++++ 2 files changed, 23 insertions(+), 22 deletions(-)
diff --git a/sound/usb/quirks.c b/sound/usb/quirks.c index a9d8bde416ce..a0986e079a66 100644 --- a/sound/usb/quirks.c +++ b/sound/usb/quirks.c @@ -1501,32 +1501,13 @@ void snd_usb_set_format_quirk(struct snd_usb_substream *subs, } }
-/* ITF-USB DSD based DACs need a vendor cmd to switch - * between PCM and native DSD mode - */ -static bool is_itf_usb_dsd_dac(unsigned int id) -{ - switch (id) { - case USB_ID(0x154e, 0x1002): /* Denon DCD-1500RE */ - case USB_ID(0x154e, 0x1003): /* Denon DA-300USB */ - case USB_ID(0x154e, 0x3005): /* Marantz HD-DAC1 */ - case USB_ID(0x154e, 0x3006): /* Marantz SA-14S1 */ - case USB_ID(0x1852, 0x5065): /* Luxman DA-06 */ - case USB_ID(0x0644, 0x8043): /* TEAC UD-501/UD-501V2/UD-503/NT-503 */ - case USB_ID(0x0644, 0x8044): /* Esoteric D-05X */ - case USB_ID(0x0644, 0x804a): /* TEAC UD-301 */ - return true; - } - return false; -} - int snd_usb_select_mode_quirk(struct snd_usb_audio *chip, const struct audioformat *fmt) { struct usb_device *dev = chip->dev; int err;
- if (is_itf_usb_dsd_dac(chip->usb_id)) { + 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 */ @@ -1633,7 +1614,7 @@ void snd_usb_ctl_msg_quirk(struct usb_device *dev, unsigned int pipe, /* ITF-USB DSD based DACs functionality need a delay * after each class compliant request */ - if (is_itf_usb_dsd_dac(chip->usb_id) + if ((chip->quirk_flags & QUIRK_FLAG_ITF_USB_DSD_DAC) && (requesttype & USB_TYPE_MASK) == USB_TYPE_CLASS) msleep(20);
@@ -1749,7 +1730,7 @@ u64 snd_usb_interface_dsd_format_quirks(struct snd_usb_audio *chip, }
/* ITF-USB DSD based DACs */ - if (is_itf_usb_dsd_dac(chip->usb_id)) { + 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 @@ -1902,16 +1883,32 @@ static const struct usb_audio_quirk_flags_table quirk_flags_table[] = { QUIRK_FLAG_ALIGN_TRANSFER), DEVICE_FLG(0x05e1, 0x0480, /* Hauppauge Woodbury */ QUIRK_FLAG_SHARE_MEDIA_DEVICE | QUIRK_FLAG_ALIGN_TRANSFER), + DEVICE_FLG(0x0644, 0x8043, /* TEAC UD-501/UD-501V2/UD-503/NT-503 */ + QUIRK_FLAG_ITF_USB_DSD_DAC), + DEVICE_FLG(0x0644, 0x8044, /* Esoteric D-05X */ + QUIRK_FLAG_ITF_USB_DSD_DAC), + DEVICE_FLG(0x0644, 0x804a, /* TEAC UD-301 */ + QUIRK_FLAG_ITF_USB_DSD_DAC), DEVICE_FLG(0x074d, 0x3553, /* Outlaw RR2150 (Micronas UAC3553B) */ QUIRK_FLAG_GET_SAMPLE_RATE), DEVICE_FLG(0x0fd9, 0x0008, /* Hauppauge HVR-950Q */ QUIRK_FLAG_SHARE_MEDIA_DEVICE | QUIRK_FLAG_ALIGN_TRANSFER), DEVICE_FLG(0x1395, 0x740a, /* Sennheiser DECT */ QUIRK_FLAG_GET_SAMPLE_RATE), + DEVICE_FLG(0x154e, 0x1002, /* Denon DCD-1500RE */ + QUIRK_FLAG_ITF_USB_DSD_DAC), + DEVICE_FLG(0x154e, 0x1003, /* Denon DA-300USB */ + QUIRK_FLAG_ITF_USB_DSD_DAC), + DEVICE_FLG(0x154e, 0x3005, /* Marantz HD-DAC1 */ + QUIRK_FLAG_ITF_USB_DSD_DAC), + DEVICE_FLG(0x154e, 0x3006, /* Marantz SA-14S1 */ + QUIRK_FLAG_ITF_USB_DSD_DAC), DEVICE_FLG(0x154e, 0x500e, /* Denon DN-X1600 */ QUIRK_FLAG_IGNORE_CLOCK_SOURCE), DEVICE_FLG(0x1686, 0x00dd, /* Zoom R16/24 */ QUIRK_FLAG_TX_LENGTH), + DEVICE_FLG(0x1852, 0x5065, /* Luxman DA-06 */ + QUIRK_FLAG_ITF_USB_DSD_DAC), DEVICE_FLG(0x1901, 0x0191, /* GE B850V3 CP2114 audio interface */ QUIRK_FLAG_GET_SAMPLE_RATE), DEVICE_FLG(0x2040, 0x7200, /* Hauppauge HVR-950Q */ diff --git a/sound/usb/usbaudio.h b/sound/usb/usbaudio.h index 82073ebeac5b..7b41a95eadee 100644 --- a/sound/usb/usbaudio.h +++ b/sound/usb/usbaudio.h @@ -144,6 +144,9 @@ extern bool snd_usb_skip_validation; * Skip clock selector setup; the device may reset to invalid state * QUIRK_FLAG_IGNORE_CLOCK_SOURCE: * Ignore errors from clock source search; i.e. hardcoded clock + * QUIRK_FLAG_ITF_USB_DSD_DAC: + * Indicates the device is for ITF-USB DSD based DACs that need a vendor cmd + * to switch between PCM and native DSD mode */
#define QUIRK_FLAG_GET_SAMPLE_RATE (1U << 0) @@ -153,5 +156,6 @@ extern bool snd_usb_skip_validation; #define QUIRK_FLAG_PLAYBACK_FIRST (1U << 4) #define QUIRK_FLAG_SKIP_CLOCK_SELECTOR (1U << 5) #define QUIRK_FLAG_IGNORE_CLOCK_SOURCE (1U << 6) +#define QUIRK_FLAG_ITF_USB_DSD_DAC (1U << 7)
#endif /* __USBAUDIO_H */
We apply some delay for the control messages on certain devices as a workaround, and this can be moved into the quirk_flags as well. Currently there are three different delay periods (1ms, 5ms and 20ms), so three different quirk bits are assigned for them.
Signed-off-by: Takashi Iwai tiwai@suse.de --- sound/usb/quirks.c | 85 ++++++++++++++------------------------------ sound/usb/usbaudio.h | 9 +++++ 2 files changed, 35 insertions(+), 59 deletions(-)
diff --git a/sound/usb/quirks.c b/sound/usb/quirks.c index a0986e079a66..a6b78cbf5089 100644 --- a/sound/usb/quirks.c +++ b/sound/usb/quirks.c @@ -1593,57 +1593,14 @@ void snd_usb_ctl_msg_quirk(struct usb_device *dev, unsigned int pipe, { struct snd_usb_audio *chip = dev_get_drvdata(&dev->dev);
- if (!chip) + if (!chip || (requesttype & USB_TYPE_MASK) != USB_TYPE_CLASS) return; - /* - * "Playback Design" products need a 20ms delay after each - * class compliant request - */ - if (USB_ID_VENDOR(chip->usb_id) == 0x23ba && - (requesttype & USB_TYPE_MASK) == USB_TYPE_CLASS) - msleep(20);
- /* - * "TEAC Corp." products need a 20ms delay after each - * class compliant request - */ - if (USB_ID_VENDOR(chip->usb_id) == 0x0644 && - (requesttype & USB_TYPE_MASK) == USB_TYPE_CLASS) + if (chip->quirk_flags & QUIRK_FLAG_CTL_MSG_DELAY) msleep(20); - - /* ITF-USB DSD based DACs functionality need a delay - * after each class compliant request - */ - if ((chip->quirk_flags & QUIRK_FLAG_ITF_USB_DSD_DAC) - && (requesttype & USB_TYPE_MASK) == USB_TYPE_CLASS) - msleep(20); - - /* - * Plantronics headsets (C320, C320-M, etc) need a delay to avoid - * random microhpone failures. - */ - if (USB_ID_VENDOR(chip->usb_id) == 0x047f && - (requesttype & USB_TYPE_MASK) == USB_TYPE_CLASS) - msleep(20); - - /* Zoom R16/24, many Logitech(at least H650e/H570e/BCC950), - * Jabra 550a, Kingston HyperX needs a tiny delay here, - * otherwise requests like get/set frequency return - * as failed despite actually succeeding. - */ - if ((chip->usb_id == USB_ID(0x1686, 0x00dd) || - USB_ID_VENDOR(chip->usb_id) == 0x046d || /* Logitech */ - chip->usb_id == USB_ID(0x0b0e, 0x0349) || - chip->usb_id == USB_ID(0x0951, 0x16ad)) && - (requesttype & USB_TYPE_MASK) == USB_TYPE_CLASS) + else if (chip->quirk_flags & QUIRK_FLAG_CTL_MSG_DELAY_1M) usleep_range(1000, 2000); - - /* - * Samsung USBC Headset (AKG) need a tiny delay after each - * class compliant request. (Model number: AAM625R or AAM627R) - */ - if (chip->usb_id == USB_ID(0x04e8, 0xa051) && - (requesttype & USB_TYPE_MASK) == USB_TYPE_CLASS) + else if (chip->quirk_flags & QUIRK_FLAG_CTL_MSG_DELAY_5M) usleep_range(5000, 6000); }
@@ -1868,11 +1825,11 @@ static const struct usb_audio_quirk_flags_table quirk_flags_table[] = { DEVICE_FLG(0x041e, 0x4080, /* Creative Live Cam VF0610 */ QUIRK_FLAG_GET_SAMPLE_RATE), DEVICE_FLG(0x046d, 0x084c, /* Logitech ConferenceCam Connect */ - QUIRK_FLAG_GET_SAMPLE_RATE), + QUIRK_FLAG_GET_SAMPLE_RATE | QUIRK_FLAG_CTL_MSG_DELAY_1M), DEVICE_FLG(0x04d8, 0xfeea, /* Benchmark DAC1 Pre */ QUIRK_FLAG_GET_SAMPLE_RATE), DEVICE_FLG(0x04e8, 0xa051, /* Samsung USBC Headset (AKG) */ - QUIRK_FLAG_SKIP_CLOCK_SELECTOR), + QUIRK_FLAG_SKIP_CLOCK_SELECTOR | QUIRK_FLAG_CTL_MSG_DELAY_5M), DEVICE_FLG(0x0556, 0x0014, /* Phoenix Audio TMX320VC */ QUIRK_FLAG_GET_SAMPLE_RATE), DEVICE_FLG(0x05a3, 0x9420, /* ELP HD USB Camera */ @@ -1884,31 +1841,35 @@ static const struct usb_audio_quirk_flags_table quirk_flags_table[] = { DEVICE_FLG(0x05e1, 0x0480, /* Hauppauge Woodbury */ QUIRK_FLAG_SHARE_MEDIA_DEVICE | QUIRK_FLAG_ALIGN_TRANSFER), DEVICE_FLG(0x0644, 0x8043, /* TEAC UD-501/UD-501V2/UD-503/NT-503 */ - QUIRK_FLAG_ITF_USB_DSD_DAC), + QUIRK_FLAG_ITF_USB_DSD_DAC | QUIRK_FLAG_CTL_MSG_DELAY), DEVICE_FLG(0x0644, 0x8044, /* Esoteric D-05X */ - QUIRK_FLAG_ITF_USB_DSD_DAC), + QUIRK_FLAG_ITF_USB_DSD_DAC | QUIRK_FLAG_CTL_MSG_DELAY), DEVICE_FLG(0x0644, 0x804a, /* TEAC UD-301 */ - QUIRK_FLAG_ITF_USB_DSD_DAC), + QUIRK_FLAG_ITF_USB_DSD_DAC | QUIRK_FLAG_CTL_MSG_DELAY), DEVICE_FLG(0x074d, 0x3553, /* Outlaw RR2150 (Micronas UAC3553B) */ QUIRK_FLAG_GET_SAMPLE_RATE), + DEVICE_FLG(0x0951, 0x16ad, /* Kingston HyperX */ + QUIRK_FLAG_CTL_MSG_DELAY_1M), + DEVICE_FLG(0x0b0e, 0x0349, /* Jabra 550a */ + QUIRK_FLAG_CTL_MSG_DELAY_1M), DEVICE_FLG(0x0fd9, 0x0008, /* Hauppauge HVR-950Q */ QUIRK_FLAG_SHARE_MEDIA_DEVICE | QUIRK_FLAG_ALIGN_TRANSFER), DEVICE_FLG(0x1395, 0x740a, /* Sennheiser DECT */ QUIRK_FLAG_GET_SAMPLE_RATE), DEVICE_FLG(0x154e, 0x1002, /* Denon DCD-1500RE */ - QUIRK_FLAG_ITF_USB_DSD_DAC), + QUIRK_FLAG_ITF_USB_DSD_DAC | QUIRK_FLAG_CTL_MSG_DELAY), DEVICE_FLG(0x154e, 0x1003, /* Denon DA-300USB */ - QUIRK_FLAG_ITF_USB_DSD_DAC), + QUIRK_FLAG_ITF_USB_DSD_DAC | QUIRK_FLAG_CTL_MSG_DELAY), DEVICE_FLG(0x154e, 0x3005, /* Marantz HD-DAC1 */ - QUIRK_FLAG_ITF_USB_DSD_DAC), + QUIRK_FLAG_ITF_USB_DSD_DAC | QUIRK_FLAG_CTL_MSG_DELAY), DEVICE_FLG(0x154e, 0x3006, /* Marantz SA-14S1 */ - QUIRK_FLAG_ITF_USB_DSD_DAC), + QUIRK_FLAG_ITF_USB_DSD_DAC | QUIRK_FLAG_CTL_MSG_DELAY), DEVICE_FLG(0x154e, 0x500e, /* Denon DN-X1600 */ QUIRK_FLAG_IGNORE_CLOCK_SOURCE), DEVICE_FLG(0x1686, 0x00dd, /* Zoom R16/24 */ - QUIRK_FLAG_TX_LENGTH), + QUIRK_FLAG_TX_LENGTH | QUIRK_FLAG_CTL_MSG_DELAY_1M), DEVICE_FLG(0x1852, 0x5065, /* Luxman DA-06 */ - QUIRK_FLAG_ITF_USB_DSD_DAC), + QUIRK_FLAG_ITF_USB_DSD_DAC | QUIRK_FLAG_CTL_MSG_DELAY), DEVICE_FLG(0x1901, 0x0191, /* GE B850V3 CP2114 audio interface */ QUIRK_FLAG_GET_SAMPLE_RATE), DEVICE_FLG(0x2040, 0x7200, /* Hauppauge HVR-950Q */ @@ -1953,10 +1914,16 @@ static const struct usb_audio_quirk_flags_table quirk_flags_table[] = { /* Vendor matches */ VENDOR_FLG(0x045e, /* MS Lifecam */ QUIRK_FLAG_GET_SAMPLE_RATE), + VENDOR_FLG(0x046d, /* Logitech */ + QUIRK_FLAG_CTL_MSG_DELAY_1M), VENDOR_FLG(0x047f, /* Plantronics */ - QUIRK_FLAG_GET_SAMPLE_RATE), + QUIRK_FLAG_GET_SAMPLE_RATE | QUIRK_FLAG_CTL_MSG_DELAY), + VENDOR_FLG(0x0644, /* TEAC Corp. */ + QUIRK_FLAG_CTL_MSG_DELAY), VENDOR_FLG(0x1de7, /* Phoenix Audio */ QUIRK_FLAG_GET_SAMPLE_RATE), + VENDOR_FLG(0x23ba, /* Playback Design */ + QUIRK_FLAG_CTL_MSG_DELAY),
{} /* terminator */ }; diff --git a/sound/usb/usbaudio.h b/sound/usb/usbaudio.h index 7b41a95eadee..69fa81150f36 100644 --- a/sound/usb/usbaudio.h +++ b/sound/usb/usbaudio.h @@ -147,6 +147,12 @@ extern bool snd_usb_skip_validation; * QUIRK_FLAG_ITF_USB_DSD_DAC: * Indicates the device is for ITF-USB DSD based DACs that need a vendor cmd * to switch between PCM and native DSD mode + * QUIRK_FLAG_CTL_MSG_DELAY: + * Add a delay of 20ms at each control message handling + * QUIRK_FLAG_CTL_MSG_DELAY_1M: + * Add a delay of 1-2ms at each control message handling + * QUIRK_FLAG_CTL_MSG_DELAY_5M: + * Add a delay of 5-6ms at each control message handling */
#define QUIRK_FLAG_GET_SAMPLE_RATE (1U << 0) @@ -157,5 +163,8 @@ extern bool snd_usb_skip_validation; #define QUIRK_FLAG_SKIP_CLOCK_SELECTOR (1U << 5) #define QUIRK_FLAG_IGNORE_CLOCK_SOURCE (1U << 6) #define QUIRK_FLAG_ITF_USB_DSD_DAC (1U << 7) +#define QUIRK_FLAG_CTL_MSG_DELAY (1U << 8) +#define QUIRK_FLAG_CTL_MSG_DELAY_1M (1U << 9) +#define QUIRK_FLAG_CTL_MSG_DELAY_5M (1U << 10)
#endif /* __USBAUDIO_H */
Yet another delay is applied at switching the interface. This can be moved to quirk_flags, too.
Signed-off-by: Takashi Iwai tiwai@suse.de --- sound/usb/endpoint.c | 3 ++- sound/usb/quirks.c | 29 ++++++++--------------------- sound/usb/quirks.h | 1 - sound/usb/usbaudio.h | 3 +++ 4 files changed, 13 insertions(+), 23 deletions(-)
diff --git a/sound/usb/endpoint.c b/sound/usb/endpoint.c index 6016e97faf69..d33685874a6b 100644 --- a/sound/usb/endpoint.c +++ b/sound/usb/endpoint.c @@ -808,7 +808,8 @@ static int endpoint_set_interface(struct snd_usb_audio *chip, return err; }
- snd_usb_set_interface_quirk(chip); + if (chip->quirk_flags & QUIRK_FLAG_IFACE_DELAY) + msleep(50); return 0; }
diff --git a/sound/usb/quirks.c b/sound/usb/quirks.c index a6b78cbf5089..f47078209bcc 100644 --- a/sound/usb/quirks.c +++ b/sound/usb/quirks.c @@ -1570,22 +1570,6 @@ void snd_usb_endpoint_start_quirk(struct snd_usb_endpoint *ep) ep->tenor_fb_quirk = 1; }
-void snd_usb_set_interface_quirk(struct snd_usb_audio *chip) -{ - if (!chip) - return; - /* - * "Playback Design" products need a 50ms delay after setting the - * USB interface. - */ - switch (USB_ID_VENDOR(chip->usb_id)) { - case 0x23ba: /* Playback Design */ - case 0x0644: /* TEAC Corp. */ - msleep(50); - break; - } -} - /* quirk applied after snd_usb_ctl_msg(); not applied during boot quirks */ void snd_usb_ctl_msg_quirk(struct usb_device *dev, unsigned int pipe, __u8 request, __u8 requesttype, __u16 value, @@ -1841,11 +1825,14 @@ static const struct usb_audio_quirk_flags_table quirk_flags_table[] = { DEVICE_FLG(0x05e1, 0x0480, /* Hauppauge Woodbury */ QUIRK_FLAG_SHARE_MEDIA_DEVICE | QUIRK_FLAG_ALIGN_TRANSFER), DEVICE_FLG(0x0644, 0x8043, /* TEAC UD-501/UD-501V2/UD-503/NT-503 */ - QUIRK_FLAG_ITF_USB_DSD_DAC | QUIRK_FLAG_CTL_MSG_DELAY), + QUIRK_FLAG_ITF_USB_DSD_DAC | QUIRK_FLAG_CTL_MSG_DELAY | + QUIRK_FLAG_IFACE_DELAY), DEVICE_FLG(0x0644, 0x8044, /* Esoteric D-05X */ - QUIRK_FLAG_ITF_USB_DSD_DAC | QUIRK_FLAG_CTL_MSG_DELAY), + QUIRK_FLAG_ITF_USB_DSD_DAC | QUIRK_FLAG_CTL_MSG_DELAY | + QUIRK_FLAG_IFACE_DELAY), DEVICE_FLG(0x0644, 0x804a, /* TEAC UD-301 */ - QUIRK_FLAG_ITF_USB_DSD_DAC | QUIRK_FLAG_CTL_MSG_DELAY), + QUIRK_FLAG_ITF_USB_DSD_DAC | QUIRK_FLAG_CTL_MSG_DELAY | + QUIRK_FLAG_IFACE_DELAY), DEVICE_FLG(0x074d, 0x3553, /* Outlaw RR2150 (Micronas UAC3553B) */ QUIRK_FLAG_GET_SAMPLE_RATE), DEVICE_FLG(0x0951, 0x16ad, /* Kingston HyperX */ @@ -1919,11 +1906,11 @@ static const struct usb_audio_quirk_flags_table quirk_flags_table[] = { VENDOR_FLG(0x047f, /* Plantronics */ QUIRK_FLAG_GET_SAMPLE_RATE | QUIRK_FLAG_CTL_MSG_DELAY), VENDOR_FLG(0x0644, /* TEAC Corp. */ - QUIRK_FLAG_CTL_MSG_DELAY), + QUIRK_FLAG_CTL_MSG_DELAY | QUIRK_FLAG_IFACE_DELAY), VENDOR_FLG(0x1de7, /* Phoenix Audio */ QUIRK_FLAG_GET_SAMPLE_RATE), VENDOR_FLG(0x23ba, /* Playback Design */ - QUIRK_FLAG_CTL_MSG_DELAY), + QUIRK_FLAG_CTL_MSG_DELAY | QUIRK_FLAG_IFACE_DELAY),
{} /* terminator */ }; diff --git a/sound/usb/quirks.h b/sound/usb/quirks.h index 0a49e074ae6a..31abb7cb01a5 100644 --- a/sound/usb/quirks.h +++ b/sound/usb/quirks.h @@ -33,7 +33,6 @@ int snd_usb_is_big_endian_format(struct snd_usb_audio *chip,
void snd_usb_endpoint_start_quirk(struct snd_usb_endpoint *ep);
-void snd_usb_set_interface_quirk(struct snd_usb_audio *chip); void snd_usb_ctl_msg_quirk(struct usb_device *dev, unsigned int pipe, __u8 request, __u8 requesttype, __u16 value, __u16 index, void *data, __u16 size); diff --git a/sound/usb/usbaudio.h b/sound/usb/usbaudio.h index 69fa81150f36..57b5dcf211d4 100644 --- a/sound/usb/usbaudio.h +++ b/sound/usb/usbaudio.h @@ -153,6 +153,8 @@ extern bool snd_usb_skip_validation; * Add a delay of 1-2ms at each control message handling * QUIRK_FLAG_CTL_MSG_DELAY_5M: * Add a delay of 5-6ms at each control message handling + * QUIRK_FLAG_IFACE_DELAY: + * Add a delay of 50ms at each interface setup */
#define QUIRK_FLAG_GET_SAMPLE_RATE (1U << 0) @@ -166,5 +168,6 @@ extern bool snd_usb_skip_validation; #define QUIRK_FLAG_CTL_MSG_DELAY (1U << 8) #define QUIRK_FLAG_CTL_MSG_DELAY_1M (1U << 9) #define QUIRK_FLAG_CTL_MSG_DELAY_5M (1U << 10) +#define QUIRK_FLAG_IFACE_DELAY (1U << 11)
#endif /* __USBAUDIO_H */
The rate validation at the device probe is applied only to the specific devices (currently only for MOTU devices), and this check can be moved to quirk_flags gracefully, too.
Signed-off-by: Takashi Iwai tiwai@suse.de --- sound/usb/format.c | 6 +----- sound/usb/quirks.c | 2 ++ sound/usb/usbaudio.h | 3 +++ 3 files changed, 6 insertions(+), 5 deletions(-)
diff --git a/sound/usb/format.c b/sound/usb/format.c index eb216fef4ba7..50efccbffb8a 100644 --- a/sound/usb/format.c +++ b/sound/usb/format.c @@ -472,12 +472,8 @@ static int validate_sample_rate_table_v2v3(struct snd_usb_audio *chip, * behavior afterwards by some unknown reason. Do this only for the * known devices. */ - switch (USB_ID_VENDOR(chip->usb_id)) { - case 0x07fd: /* MOTU */ - break; - default: + if (!(chip->quirk_flags & QUIRK_FLAG_VALIDATE_RATES)) return 0; /* don't perform the validation as default */ - }
table = kcalloc(fp->nr_rates, sizeof(*table), GFP_KERNEL); if (!table) diff --git a/sound/usb/quirks.c b/sound/usb/quirks.c index f47078209bcc..dc667b8c92f2 100644 --- a/sound/usb/quirks.c +++ b/sound/usb/quirks.c @@ -1907,6 +1907,8 @@ static const struct usb_audio_quirk_flags_table quirk_flags_table[] = { QUIRK_FLAG_GET_SAMPLE_RATE | QUIRK_FLAG_CTL_MSG_DELAY), VENDOR_FLG(0x0644, /* TEAC Corp. */ QUIRK_FLAG_CTL_MSG_DELAY | QUIRK_FLAG_IFACE_DELAY), + VENDOR_FLG(0x07fd, /* MOTU */ + QUIRK_FLAG_VALIDATE_RATES), VENDOR_FLG(0x1de7, /* Phoenix Audio */ QUIRK_FLAG_GET_SAMPLE_RATE), VENDOR_FLG(0x23ba, /* Playback Design */ diff --git a/sound/usb/usbaudio.h b/sound/usb/usbaudio.h index 57b5dcf211d4..ea0e3deb2a23 100644 --- a/sound/usb/usbaudio.h +++ b/sound/usb/usbaudio.h @@ -155,6 +155,8 @@ extern bool snd_usb_skip_validation; * Add a delay of 5-6ms at each control message handling * QUIRK_FLAG_IFACE_DELAY: * Add a delay of 50ms at each interface setup + * QUIRK_FLAG_VALIDATE_RATES: + * Perform sample rate validations at probe */
#define QUIRK_FLAG_GET_SAMPLE_RATE (1U << 0) @@ -169,5 +171,6 @@ extern bool snd_usb_skip_validation; #define QUIRK_FLAG_CTL_MSG_DELAY_1M (1U << 9) #define QUIRK_FLAG_CTL_MSG_DELAY_5M (1U << 10) #define QUIRK_FLAG_IFACE_DELAY (1U << 11) +#define QUIRK_FLAG_VALIDATE_RATES (1U << 12)
#endif /* __USBAUDIO_H */
The auto-suspend suppression workaround for Lenovo machines are handled in quirks-table.h. Now it's more easier to handle with quirk_flags.
Signed-off-by: Takashi Iwai tiwai@suse.de --- sound/usb/card.c | 5 ++++- sound/usb/quirks-table.h | 17 ----------------- sound/usb/quirks.c | 14 ++++---------- sound/usb/usbaudio.h | 5 +++-- 4 files changed, 11 insertions(+), 30 deletions(-)
diff --git a/sound/usb/card.c b/sound/usb/card.c index 8c32a784f1e4..d66a3788111c 100644 --- a/sound/usb/card.c +++ b/sound/usb/card.c @@ -804,6 +804,9 @@ static int usb_audio_probe(struct usb_interface *intf,
dev_set_drvdata(&dev->dev, chip);
+ if (chip->quirk_flags & QUIRK_FLAG_DISABLE_AUTOSUSPEND) + usb_disable_autosuspend(interface_to_usbdev(intf)); + /* * For devices with more than one control interface, we assume the * first contains the audio controls. We might need a more specific @@ -929,7 +932,7 @@ static void usb_audio_disconnect(struct usb_interface *intf) } }
- if (chip->quirk_type == QUIRK_SETUP_DISABLE_AUTOSUSPEND) + if (chip->quirk_flags & QUIRK_FLAG_DISABLE_AUTOSUSPEND) usb_enable_autosuspend(interface_to_usbdev(intf));
chip->num_interfaces--; diff --git a/sound/usb/quirks-table.h b/sound/usb/quirks-table.h index b5e82363cf47..e03043f7dad3 100644 --- a/sound/usb/quirks-table.h +++ b/sound/usb/quirks-table.h @@ -2730,23 +2730,6 @@ YAMAHA_DEVICE(0x7010, "UB99"), } },
-/* Lenovo ThinkStation P620 Rear Line-in, Line-out and Microphone */ -{ - USB_DEVICE(0x17aa, 0x1046), - .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) { - .ifnum = QUIRK_ANY_INTERFACE, - .type = QUIRK_SETUP_DISABLE_AUTOSUSPEND - } -}, -/* Lenovo ThinkStation P620 Internal Speaker + Front Headset */ -{ - USB_DEVICE(0x17aa, 0x104d), - .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) { - .ifnum = QUIRK_ANY_INTERFACE, - .type = QUIRK_SETUP_DISABLE_AUTOSUSPEND - } -}, - /* Native Instruments MK2 series */ { /* Komplete Audio 6 */ diff --git a/sound/usb/quirks.c b/sound/usb/quirks.c index dc667b8c92f2..1cffb87e5026 100644 --- a/sound/usb/quirks.c +++ b/sound/usb/quirks.c @@ -534,15 +534,6 @@ static int create_standard_mixer_quirk(struct snd_usb_audio *chip, return snd_usb_create_mixer(chip, quirk->ifnum, 0); }
-static int setup_disable_autosuspend(struct snd_usb_audio *chip, - struct usb_interface *iface, - struct usb_driver *driver, - const struct snd_usb_audio_quirk *quirk) -{ - usb_disable_autosuspend(interface_to_usbdev(iface)); - return 1; /* Continue with creating streams and mixer */ -} - /* * audio-interface quirks * @@ -580,7 +571,6 @@ int snd_usb_create_quirk(struct snd_usb_audio *chip, [QUIRK_AUDIO_FIXED_ENDPOINT] = create_fixed_stream_quirk, [QUIRK_AUDIO_EDIROL_UAXX] = create_uaxx_quirk, [QUIRK_AUDIO_STANDARD_MIXER] = create_standard_mixer_quirk, - [QUIRK_SETUP_DISABLE_AUTOSUSPEND] = setup_disable_autosuspend, };
if (quirk->type < QUIRK_TYPE_COUNT) { @@ -1855,6 +1845,10 @@ static const struct usb_audio_quirk_flags_table quirk_flags_table[] = { QUIRK_FLAG_IGNORE_CLOCK_SOURCE), DEVICE_FLG(0x1686, 0x00dd, /* Zoom R16/24 */ QUIRK_FLAG_TX_LENGTH | QUIRK_FLAG_CTL_MSG_DELAY_1M), + DEVICE_FLG(0x17aa, 0x1046, /* Lenovo ThinkStation P620 Rear Line-in, Line-out and Microphone */ + QUIRK_FLAG_DISABLE_AUTOSUSPEND), + DEVICE_FLG(0x17aa, 0x104d, /* Lenovo ThinkStation P620 Internal Speaker + Front Headset */ + QUIRK_FLAG_DISABLE_AUTOSUSPEND), DEVICE_FLG(0x1852, 0x5065, /* Luxman DA-06 */ QUIRK_FLAG_ITF_USB_DSD_DAC | QUIRK_FLAG_CTL_MSG_DELAY), DEVICE_FLG(0x1901, 0x0191, /* GE B850V3 CP2114 audio interface */ diff --git a/sound/usb/usbaudio.h b/sound/usb/usbaudio.h index ea0e3deb2a23..ce31d58f810f 100644 --- a/sound/usb/usbaudio.h +++ b/sound/usb/usbaudio.h @@ -101,8 +101,6 @@ enum quirk_type { QUIRK_AUDIO_FIXED_ENDPOINT, QUIRK_AUDIO_EDIROL_UAXX, QUIRK_AUDIO_STANDARD_MIXER, - QUIRK_SETUP_FMT_AFTER_RESUME, - QUIRK_SETUP_DISABLE_AUTOSUSPEND,
QUIRK_TYPE_COUNT }; @@ -157,6 +155,8 @@ extern bool snd_usb_skip_validation; * Add a delay of 50ms at each interface setup * QUIRK_FLAG_VALIDATE_RATES: * Perform sample rate validations at probe + * QUIRK_FLAG_DISABLE_AUTOSUSPEND: + * Disable runtime PM autosuspend */
#define QUIRK_FLAG_GET_SAMPLE_RATE (1U << 0) @@ -172,5 +172,6 @@ extern bool snd_usb_skip_validation; #define QUIRK_FLAG_CTL_MSG_DELAY_5M (1U << 10) #define QUIRK_FLAG_IFACE_DELAY (1U << 11) #define QUIRK_FLAG_VALIDATE_RATES (1U << 12) +#define QUIRK_FLAG_DISABLE_AUTOSUSPEND (1U << 13)
#endif /* __USBAUDIO_H */
The mixer code has a flag ignore_ctl_error for ignoring the errors returned from the device wrt mixer accesses, and this is set from the entries in mixer_maps.c, as well as ignore_ctl_error module option. Those can be well integrated into the new quirk_flags field, too.
Signed-off-by: Takashi Iwai tiwai@suse.de --- sound/usb/card.c | 5 ++++- sound/usb/mixer.c | 6 ++---- sound/usb/mixer.h | 3 +-- sound/usb/mixer_maps.c | 22 ---------------------- sound/usb/quirks.c | 16 +++++++++++++++- sound/usb/usbaudio.h | 3 +++ 6 files changed, 25 insertions(+), 30 deletions(-)
diff --git a/sound/usb/card.c b/sound/usb/card.c index d66a3788111c..9535df39c02f 100644 --- a/sound/usb/card.c +++ b/sound/usb/card.c @@ -804,6 +804,9 @@ static int usb_audio_probe(struct usb_interface *intf,
dev_set_drvdata(&dev->dev, chip);
+ if (ignore_ctl_error) + chip->quirk_flags |= QUIRK_FLAG_IGNORE_CTL_ERROR; + if (chip->quirk_flags & QUIRK_FLAG_DISABLE_AUTOSUSPEND) usb_disable_autosuspend(interface_to_usbdev(intf));
@@ -828,7 +831,7 @@ static int usb_audio_probe(struct usb_interface *intf, err = snd_usb_create_streams(chip, ifnum); if (err < 0) goto __error; - err = snd_usb_create_mixer(chip, ifnum, ignore_ctl_error); + err = snd_usb_create_mixer(chip, ifnum); if (err < 0) goto __error; } diff --git a/sound/usb/mixer.c b/sound/usb/mixer.c index f4cdaf1ba44a..6cb5f4942ae2 100644 --- a/sound/usb/mixer.c +++ b/sound/usb/mixer.c @@ -3170,7 +3170,6 @@ static int snd_usb_mixer_controls(struct usb_mixer_interface *mixer) state.map = map->map; state.selector_map = map->selector_map; mixer->connector_map = map->connector_map; - mixer->ignore_ctl_error |= map->ignore_ctl_error; break; } } @@ -3495,8 +3494,7 @@ static int snd_usb_mixer_status_create(struct usb_mixer_interface *mixer) return 0; }
-int snd_usb_create_mixer(struct snd_usb_audio *chip, int ctrlif, - int ignore_error) +int snd_usb_create_mixer(struct snd_usb_audio *chip, int ctrlif) { static const struct snd_device_ops dev_ops = { .dev_free = snd_usb_mixer_dev_free @@ -3510,7 +3508,7 @@ int snd_usb_create_mixer(struct snd_usb_audio *chip, int ctrlif, if (!mixer) return -ENOMEM; mixer->chip = chip; - mixer->ignore_ctl_error = ignore_error; + mixer->ignore_ctl_error = !!(chip->quirk_flags & QUIRK_FLAG_IGNORE_CTL_ERROR); mixer->id_elems = kcalloc(MAX_ID_ELEMS, sizeof(*mixer->id_elems), GFP_KERNEL); if (!mixer->id_elems) { diff --git a/sound/usb/mixer.h b/sound/usb/mixer.h index ea41e7a1f7bf..876bbc9a71ad 100644 --- a/sound/usb/mixer.h +++ b/sound/usb/mixer.h @@ -97,8 +97,7 @@ struct usb_mixer_elem_info { void *private_data; };
-int snd_usb_create_mixer(struct snd_usb_audio *chip, int ctrlif, - int ignore_error); +int snd_usb_create_mixer(struct snd_usb_audio *chip, int ctrlif); void snd_usb_mixer_disconnect(struct usb_mixer_interface *mixer);
void snd_usb_mixer_notify_id(struct usb_mixer_interface *mixer, int unitid); diff --git a/sound/usb/mixer_maps.c b/sound/usb/mixer_maps.c index c5794e83fd80..55eea90ee993 100644 --- a/sound/usb/mixer_maps.c +++ b/sound/usb/mixer_maps.c @@ -28,7 +28,6 @@ struct usbmix_ctl_map { const struct usbmix_name_map *map; const struct usbmix_selector_map *selector_map; const struct usbmix_connector_map *connector_map; - int ignore_ctl_error; };
/* @@ -432,7 +431,6 @@ static const struct usbmix_ctl_map usbmix_ctl_maps[] = { { .id = USB_ID(0x041e, 0x3000), .map = extigy_map, - .ignore_ctl_error = 1, }, { .id = USB_ID(0x041e, 0x3010), @@ -452,28 +450,10 @@ static const struct usbmix_ctl_map usbmix_ctl_maps[] = { .map = audigy2nx_map, .selector_map = audigy2nx_selectors, }, - { /* Logitech, Inc. QuickCam Pro for Notebooks */ - .id = USB_ID(0x046d, 0x0991), - .ignore_ctl_error = 1, - }, - { /* Logitech, Inc. QuickCam E 3500 */ - .id = USB_ID(0x046d, 0x09a4), - .ignore_ctl_error = 1, - }, { /* Plantronics GameCom 780 */ .id = USB_ID(0x047f, 0xc010), .map = gamecom780_map, }, - { - /* Hercules DJ Console (Windows Edition) */ - .id = USB_ID(0x06f8, 0xb000), - .ignore_ctl_error = 1, - }, - { - /* Hercules DJ Console (Macintosh Edition) */ - .id = USB_ID(0x06f8, 0xd002), - .ignore_ctl_error = 1, - }, { /* Hercules Gamesurround Muse Pocket LT * (USB 5.1 Channel Audio Adapter) @@ -492,7 +472,6 @@ static const struct usbmix_ctl_map usbmix_ctl_maps[] = { { .id = USB_ID(0x08bb, 0x2702), .map = linex_map, - .ignore_ctl_error = 1, }, { .id = USB_ID(0x0a92, 0x0091), @@ -517,7 +496,6 @@ static const struct usbmix_ctl_map usbmix_ctl_maps[] = { { .id = USB_ID(0x13e5, 0x0001), .map = scratch_live_map, - .ignore_ctl_error = 1, }, { .id = USB_ID(0x200c, 0x1018), diff --git a/sound/usb/quirks.c b/sound/usb/quirks.c index 1cffb87e5026..fce3a341adc8 100644 --- a/sound/usb/quirks.c +++ b/sound/usb/quirks.c @@ -531,7 +531,7 @@ static int create_standard_mixer_quirk(struct snd_usb_audio *chip, if (quirk->ifnum < 0) return 0;
- return snd_usb_create_mixer(chip, quirk->ifnum, 0); + return snd_usb_create_mixer(chip, quirk->ifnum); }
/* @@ -1796,10 +1796,16 @@ struct usb_audio_quirk_flags_table {
static const struct usb_audio_quirk_flags_table quirk_flags_table[] = { /* Device matches */ + DEVICE_FLG(0x041e, 0x3000, /* Creative SB Extigy */ + QUIRK_FLAG_IGNORE_CTL_ERROR), DEVICE_FLG(0x041e, 0x4080, /* Creative Live Cam VF0610 */ QUIRK_FLAG_GET_SAMPLE_RATE), DEVICE_FLG(0x046d, 0x084c, /* Logitech ConferenceCam Connect */ QUIRK_FLAG_GET_SAMPLE_RATE | QUIRK_FLAG_CTL_MSG_DELAY_1M), + DEVICE_FLG(0x046d, 0x0991, /* Logitech QuickCam Pro */ + QUIRK_FLAG_CTL_MSG_DELAY_1M | QUIRK_FLAG_IGNORE_CTL_ERROR), + DEVICE_FLG(0x046d, 0x09a4, /* Logitech QuickCam E 3500 */ + QUIRK_FLAG_CTL_MSG_DELAY_1M | QUIRK_FLAG_IGNORE_CTL_ERROR), DEVICE_FLG(0x04d8, 0xfeea, /* Benchmark DAC1 Pre */ QUIRK_FLAG_GET_SAMPLE_RATE), DEVICE_FLG(0x04e8, 0xa051, /* Samsung USBC Headset (AKG) */ @@ -1823,8 +1829,14 @@ static const struct usb_audio_quirk_flags_table quirk_flags_table[] = { DEVICE_FLG(0x0644, 0x804a, /* TEAC UD-301 */ QUIRK_FLAG_ITF_USB_DSD_DAC | QUIRK_FLAG_CTL_MSG_DELAY | QUIRK_FLAG_IFACE_DELAY), + DEVICE_FLG(0x06f8, 0xb000, /* Hercules DJ Console (Windows Edition) */ + QUIRK_FLAG_IGNORE_CTL_ERROR), + DEVICE_FLG(0x06f8, 0xd002, /* Hercules DJ Console (Macintosh Edition) */ + QUIRK_FLAG_IGNORE_CTL_ERROR), DEVICE_FLG(0x074d, 0x3553, /* Outlaw RR2150 (Micronas UAC3553B) */ QUIRK_FLAG_GET_SAMPLE_RATE), + DEVICE_FLG(0x08bb, 0x2702, /* LineX FM Transmitter */ + QUIRK_FLAG_IGNORE_CTL_ERROR), DEVICE_FLG(0x0951, 0x16ad, /* Kingston HyperX */ QUIRK_FLAG_CTL_MSG_DELAY_1M), DEVICE_FLG(0x0b0e, 0x0349, /* Jabra 550a */ @@ -1833,6 +1845,8 @@ static const struct usb_audio_quirk_flags_table quirk_flags_table[] = { QUIRK_FLAG_SHARE_MEDIA_DEVICE | QUIRK_FLAG_ALIGN_TRANSFER), DEVICE_FLG(0x1395, 0x740a, /* Sennheiser DECT */ QUIRK_FLAG_GET_SAMPLE_RATE), + DEVICE_FLG(0x13e5, 0x0001, /* Serato Phono */ + QUIRK_FLAG_IGNORE_CTL_ERROR), DEVICE_FLG(0x154e, 0x1002, /* Denon DCD-1500RE */ QUIRK_FLAG_ITF_USB_DSD_DAC | QUIRK_FLAG_CTL_MSG_DELAY), DEVICE_FLG(0x154e, 0x1003, /* Denon DA-300USB */ diff --git a/sound/usb/usbaudio.h b/sound/usb/usbaudio.h index ce31d58f810f..a152f5b08c7a 100644 --- a/sound/usb/usbaudio.h +++ b/sound/usb/usbaudio.h @@ -157,6 +157,8 @@ extern bool snd_usb_skip_validation; * Perform sample rate validations at probe * QUIRK_FLAG_DISABLE_AUTOSUSPEND: * Disable runtime PM autosuspend + * QUIRK_FLAG_IGNORE_CTL_ERROR: + * Ignore errors for mixer access */
#define QUIRK_FLAG_GET_SAMPLE_RATE (1U << 0) @@ -173,5 +175,6 @@ extern bool snd_usb_skip_validation; #define QUIRK_FLAG_IFACE_DELAY (1U << 11) #define QUIRK_FLAG_VALIDATE_RATES (1U << 12) #define QUIRK_FLAG_DISABLE_AUTOSUSPEND (1U << 13) +#define QUIRK_FLAG_IGNORE_CTL_ERROR (1U << 14)
#endif /* __USBAUDIO_H */
The generic DSD raw detection is based on the known allow list, and we can integrate it into quirk_flags, too.
Signed-off-by: Takashi Iwai tiwai@suse.de --- sound/usb/quirks.c | 51 +++++++++++++++++++++++--------------------- sound/usb/usbaudio.h | 3 +++ 2 files changed, 30 insertions(+), 24 deletions(-)
diff --git a/sound/usb/quirks.c b/sound/usb/quirks.c index fce3a341adc8..670abc6318f2 100644 --- a/sound/usb/quirks.c +++ b/sound/usb/quirks.c @@ -1673,29 +1673,9 @@ u64 snd_usb_interface_dsd_format_quirks(struct snd_usb_audio *chip, return SNDRV_PCM_FMTBIT_DSD_U32_BE; }
- /* Mostly generic method to detect many DSD-capable implementations - - * from XMOS/Thesycon - */ - switch (USB_ID_VENDOR(chip->usb_id)) { - case 0x152a: /* Thesycon devices */ - case 0x20b1: /* XMOS based devices */ - case 0x22d9: /* Oppo */ - case 0x23ba: /* Playback Designs */ - case 0x25ce: /* Mytek devices */ - case 0x278b: /* Rotel? */ - case 0x292b: /* Gustard/Ess based devices */ - case 0x2972: /* FiiO devices */ - case 0x2ab6: /* T+A devices */ - case 0x3353: /* Khadas devices */ - case 0x3842: /* EVGA */ - case 0xc502: /* HiBy devices */ - if (fp->dsd_raw) - return SNDRV_PCM_FMTBIT_DSD_U32_BE; - break; - default: - break; - - } + /* 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; } @@ -1917,10 +1897,33 @@ static const struct usb_audio_quirk_flags_table quirk_flags_table[] = { QUIRK_FLAG_CTL_MSG_DELAY | QUIRK_FLAG_IFACE_DELAY), VENDOR_FLG(0x07fd, /* MOTU */ QUIRK_FLAG_VALIDATE_RATES), + VENDOR_FLG(0x152a, /* Thesycon devices */ + QUIRK_FLAG_DSD_RAW), VENDOR_FLG(0x1de7, /* Phoenix Audio */ QUIRK_FLAG_GET_SAMPLE_RATE), + VENDOR_FLG(0x20b1, /* XMOS based devices */ + QUIRK_FLAG_DSD_RAW), + VENDOR_FLG(0x22d9, /* Oppo */ + QUIRK_FLAG_DSD_RAW), VENDOR_FLG(0x23ba, /* Playback Design */ - QUIRK_FLAG_CTL_MSG_DELAY | QUIRK_FLAG_IFACE_DELAY), + QUIRK_FLAG_CTL_MSG_DELAY | QUIRK_FLAG_IFACE_DELAY | + QUIRK_FLAG_DSD_RAW), + VENDOR_FLG(0x25ce, /* Mytek devices */ + QUIRK_FLAG_DSD_RAW), + VENDOR_FLG(0x278b, /* Rotel? */ + QUIRK_FLAG_DSD_RAW), + VENDOR_FLG(0x292b, /* Gustard/Ess based devices */ + QUIRK_FLAG_DSD_RAW), + VENDOR_FLG(0x2972, /* FiiO devices */ + QUIRK_FLAG_DSD_RAW), + VENDOR_FLG(0x2ab6, /* T+A devices */ + QUIRK_FLAG_DSD_RAW), + VENDOR_FLG(0x3353, /* Khadas devices */ + QUIRK_FLAG_DSD_RAW), + VENDOR_FLG(0x3842, /* EVGA */ + QUIRK_FLAG_DSD_RAW), + VENDOR_FLG(0xc502, /* HiBy devices */ + QUIRK_FLAG_DSD_RAW),
{} /* terminator */ }; diff --git a/sound/usb/usbaudio.h b/sound/usb/usbaudio.h index a152f5b08c7a..4e93668a2a48 100644 --- a/sound/usb/usbaudio.h +++ b/sound/usb/usbaudio.h @@ -159,6 +159,8 @@ extern bool snd_usb_skip_validation; * Disable runtime PM autosuspend * QUIRK_FLAG_IGNORE_CTL_ERROR: * Ignore errors for mixer access + * QUIRK_FLAG_DSD_RAW: + * Support generic DSD raw U32_BE format */
#define QUIRK_FLAG_GET_SAMPLE_RATE (1U << 0) @@ -176,5 +178,6 @@ extern bool snd_usb_skip_validation; #define QUIRK_FLAG_VALIDATE_RATES (1U << 12) #define QUIRK_FLAG_DISABLE_AUTOSUSPEND (1U << 13) #define QUIRK_FLAG_IGNORE_CTL_ERROR (1U << 14) +#define QUIRK_FLAG_DSD_RAW (1U << 15)
#endif /* __USBAUDIO_H */
This patch adds a new module option, quirk_flags, for allowing user to try some additional device-specific quirk behavior more easily. When this option is set to non-zero, it overrides the quirk_flags, and the specific workaround is applied.
Signed-off-by: Takashi Iwai tiwai@suse.de --- sound/usb/card.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-)
diff --git a/sound/usb/card.c b/sound/usb/card.c index 9535df39c02f..cf8f3953f78f 100644 --- a/sound/usb/card.c +++ b/sound/usb/card.c @@ -71,6 +71,7 @@ static bool autoclock = true; static char *quirk_alias[SNDRV_CARDS]; static char *delayed_register[SNDRV_CARDS]; static bool implicit_fb[SNDRV_CARDS]; +static unsigned int quirk_flags[SNDRV_CARDS];
bool snd_usb_use_vmalloc = true; bool snd_usb_skip_validation; @@ -98,6 +99,8 @@ module_param_array(delayed_register, charp, NULL, 0444); MODULE_PARM_DESC(delayed_register, "Quirk for delayed registration, given by id:iface, e.g. 0123abcd:4."); module_param_array(implicit_fb, bool, NULL, 0444); MODULE_PARM_DESC(implicit_fb, "Apply generic implicit feedback sync mode."); +module_param_array(quirk_flags, uint, NULL, 0444); +MODULE_PARM_DESC(quirk_flags, "Driver quirk bit flags."); module_param_named(use_vmalloc, snd_usb_use_vmalloc, bool, 0444); MODULE_PARM_DESC(use_vmalloc, "Use vmalloc for PCM intermediate buffers (default: yes)."); module_param_named(skip_validation, snd_usb_skip_validation, bool, 0444); @@ -631,7 +634,10 @@ static int snd_usb_audio_create(struct usb_interface *intf, INIT_LIST_HEAD(&chip->midi_list); INIT_LIST_HEAD(&chip->mixer_list);
- snd_usb_init_quirk_flags(chip); + if (quirk_flags[idx]) + chip->quirk_flags = quirk_flags[idx]; + else + snd_usb_init_quirk_flags(chip);
card->private_free = snd_usb_audio_free;
Just briefly described about the new option.
Signed-off-by: Takashi Iwai tiwai@suse.de --- Documentation/sound/alsa-configuration.rst | 26 ++++++++++++++++++++-- 1 file changed, 24 insertions(+), 2 deletions(-)
diff --git a/Documentation/sound/alsa-configuration.rst b/Documentation/sound/alsa-configuration.rst index b36af65a08ed..f148b58502c0 100644 --- a/Documentation/sound/alsa-configuration.rst +++ b/Documentation/sound/alsa-configuration.rst @@ -2252,6 +2252,25 @@ delayed_register The driver prints a message like "Found post-registration device assignment: 1234abcd:04" for such a device, so that user can notice the need. +quirk_flags + Contains the bit flags for various device specific workarounds. + Applied to the corresponding card index. + * bit 0: Skip reading sample rate for devices + * bit 1: Create Media Controller API entries + * bit 2: Allow alignment on audio sub-slot at transfer + * bit 3: Add length specifier to transfers + * bit 4: Start playback stream at first in implement feedback mode + * bit 5: Skip clock selector setup + * bit 6: Ignore errors from clock source search + * bit 7: Indicates ITF-USB DSD based DACs + * bit 8: Add a delay of 20ms at each control message handling + * bit 9: Add a delay of 1-2ms at each control message handling + * bit 10: Add a delay of 5-6ms at each control message handling + * bit 11: Add a delay of 50ms at each interface setup + * bit 12: Perform sample rate validations at probe + * bit 13: Disable runtime PM autosuspend + * bit 14: Ignore errors for mixer access + * bit 15: Support generic DSD raw U32_BE format
This module supports multiple devices, autoprobe and hotplugging.
@@ -2261,11 +2280,14 @@ check.
NB: ``ignore_ctl_error=1`` may help when you get an error at accessing the mixer element such as URB error -22. This happens on some -buggy USB device or the controller. +buggy USB device or the controller. This workaround corresponds to +the ``quirk_flags`` bit 14, too.
-NB: quirk_alias option is provided only for testing / development. +NB: ``quirk_alias`` option is provided only for testing / development. If you want to have a proper support, contact to upstream for adding the matching quirk in the driver code statically. +Ditto for ``quirk_flags``. If a device is known to require specific +workarounds, please report to the upstream.
Module snd-usb-caiaq --------------------
participants (1)
-
Takashi Iwai