ALSA: usb-audio: add two-way convert between name and bit for QUIRK_FLAG_*

Define quirk flags enum and its name.

Add helper for converting between quirk flags' name and bit.
  - snd_usb_quirk_flag_find_name()
  - snd_usb_quirk_flags_from_name()

Add helper for printing debug: log snd_usb_apply_flag_dbg()

Co-developed-by: Takashi Iwai <tiwai@suse.de>
Signed-off-by: Cryolitia PukNgae <cryolitia@uniontech.com>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
pull/1354/merge
Cryolitia PukNgae 2025-09-28 11:07:59 +08:00 committed by Takashi Iwai
parent 329bdcbbd2
commit ce01726273
3 changed files with 144 additions and 30 deletions

View File

@ -2443,6 +2443,84 @@ static const struct usb_audio_quirk_flags_table quirk_flags_table[] = {
{} /* terminator */ {} /* terminator */
}; };
#define QUIRK_STRING_ENTRY(x) \
[QUIRK_TYPE_ ## x] = __stringify(x)
static const char *const snd_usb_audio_quirk_flag_names[] = {
QUIRK_STRING_ENTRY(GET_SAMPLE_RATE),
QUIRK_STRING_ENTRY(SHARE_MEDIA_DEVICE),
QUIRK_STRING_ENTRY(ALIGN_TRANSFER),
QUIRK_STRING_ENTRY(TX_LENGTH),
QUIRK_STRING_ENTRY(PLAYBACK_FIRST),
QUIRK_STRING_ENTRY(SKIP_CLOCK_SELECTOR),
QUIRK_STRING_ENTRY(IGNORE_CLOCK_SOURCE),
QUIRK_STRING_ENTRY(ITF_USB_DSD_DAC),
QUIRK_STRING_ENTRY(CTL_MSG_DELAY),
QUIRK_STRING_ENTRY(CTL_MSG_DELAY_1M),
QUIRK_STRING_ENTRY(CTL_MSG_DELAY_5M),
QUIRK_STRING_ENTRY(IFACE_DELAY),
QUIRK_STRING_ENTRY(VALIDATE_RATES),
QUIRK_STRING_ENTRY(DISABLE_AUTOSUSPEND),
QUIRK_STRING_ENTRY(IGNORE_CTL_ERROR),
QUIRK_STRING_ENTRY(DSD_RAW),
QUIRK_STRING_ENTRY(SET_IFACE_FIRST),
QUIRK_STRING_ENTRY(GENERIC_IMPLICIT_FB),
QUIRK_STRING_ENTRY(SKIP_IMPLICIT_FB),
QUIRK_STRING_ENTRY(IFACE_SKIP_CLOSE),
QUIRK_STRING_ENTRY(FORCE_IFACE_RESET),
QUIRK_STRING_ENTRY(FIXED_RATE),
QUIRK_STRING_ENTRY(MIC_RES_16),
QUIRK_STRING_ENTRY(MIC_RES_384),
QUIRK_STRING_ENTRY(MIXER_PLAYBACK_MIN_MUTE),
QUIRK_STRING_ENTRY(MIXER_CAPTURE_MIN_MUTE),
NULL
};
const char *snd_usb_quirk_flag_find_name(unsigned long index)
{
if (index >= ARRAY_SIZE(snd_usb_audio_quirk_flag_names))
return NULL;
return snd_usb_audio_quirk_flag_names[index];
}
u32 snd_usb_quirk_flags_from_name(const char *name)
{
int i;
if (!name || !*name)
return 0;
for (i = 0; snd_usb_audio_quirk_flag_names[i]; i++) {
if (strcasecmp(name, snd_usb_audio_quirk_flag_names[i]) == 0)
return BIT_U32(i);
}
return 0;
}
void snd_usb_apply_flag_dbg(const char *reason,
struct snd_usb_audio *chip,
unsigned long flag)
{
unsigned long bit;
for_each_set_bit(bit, &flag, BYTES_TO_BITS(sizeof(flag))) {
const char *name = snd_usb_audio_quirk_flag_names[bit];
if (name)
usb_audio_dbg(chip,
"From %s apply quirk flag %s for device %04x:%04x\n",
reason, name, USB_ID_VENDOR(chip->usb_id),
USB_ID_PRODUCT(chip->usb_id));
else
usb_audio_warn(chip,
"From %s apply unknown quirk flag 0x%lx for device %04x:%04x\n",
reason, bit, USB_ID_VENDOR(chip->usb_id),
USB_ID_PRODUCT(chip->usb_id));
}
}
void snd_usb_init_quirk_flags(struct snd_usb_audio *chip) void snd_usb_init_quirk_flags(struct snd_usb_audio *chip)
{ {
const struct usb_audio_quirk_flags_table *p; const struct usb_audio_quirk_flags_table *p;
@ -2451,10 +2529,7 @@ void snd_usb_init_quirk_flags(struct snd_usb_audio *chip)
if (chip->usb_id == p->id || if (chip->usb_id == p->id ||
(!USB_ID_PRODUCT(p->id) && (!USB_ID_PRODUCT(p->id) &&
USB_ID_VENDOR(chip->usb_id) == USB_ID_VENDOR(p->id))) { USB_ID_VENDOR(chip->usb_id) == USB_ID_VENDOR(p->id))) {
usb_audio_dbg(chip, snd_usb_apply_flag_dbg("builtin table", chip, p->flags);
"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; chip->quirk_flags |= p->flags;
return; return;
} }

View File

@ -48,6 +48,13 @@ void snd_usb_audioformat_attributes_quirk(struct snd_usb_audio *chip,
struct audioformat *fp, struct audioformat *fp,
int stream); int stream);
void snd_usb_apply_flag_dbg(const char *reason,
struct snd_usb_audio *chip,
unsigned long flag);
void snd_usb_init_quirk_flags(struct snd_usb_audio *chip); void snd_usb_init_quirk_flags(struct snd_usb_audio *chip);
const char *snd_usb_quirk_flag_find_name(unsigned long flag);
u32 snd_usb_quirk_flags_from_name(const char *name);
#endif /* __USBAUDIO_QUIRKS_H */ #endif /* __USBAUDIO_QUIRKS_H */

View File

@ -226,31 +226,63 @@ extern bool snd_usb_skip_validation;
* Similar to QUIRK_FLAG_MIXER_PLAYBACK_MIN_MUTE, but for capture streams * Similar to QUIRK_FLAG_MIXER_PLAYBACK_MIN_MUTE, but for capture streams
*/ */
#define QUIRK_FLAG_GET_SAMPLE_RATE (1U << 0) enum {
#define QUIRK_FLAG_SHARE_MEDIA_DEVICE (1U << 1) QUIRK_TYPE_GET_SAMPLE_RATE = 0,
#define QUIRK_FLAG_ALIGN_TRANSFER (1U << 2) QUIRK_TYPE_SHARE_MEDIA_DEVICE = 1,
#define QUIRK_FLAG_TX_LENGTH (1U << 3) QUIRK_TYPE_ALIGN_TRANSFER = 2,
#define QUIRK_FLAG_PLAYBACK_FIRST (1U << 4) QUIRK_TYPE_TX_LENGTH = 3,
#define QUIRK_FLAG_SKIP_CLOCK_SELECTOR (1U << 5) QUIRK_TYPE_PLAYBACK_FIRST = 4,
#define QUIRK_FLAG_IGNORE_CLOCK_SOURCE (1U << 6) QUIRK_TYPE_SKIP_CLOCK_SELECTOR = 5,
#define QUIRK_FLAG_ITF_USB_DSD_DAC (1U << 7) QUIRK_TYPE_IGNORE_CLOCK_SOURCE = 6,
#define QUIRK_FLAG_CTL_MSG_DELAY (1U << 8) QUIRK_TYPE_ITF_USB_DSD_DAC = 7,
#define QUIRK_FLAG_CTL_MSG_DELAY_1M (1U << 9) QUIRK_TYPE_CTL_MSG_DELAY = 8,
#define QUIRK_FLAG_CTL_MSG_DELAY_5M (1U << 10) QUIRK_TYPE_CTL_MSG_DELAY_1M = 9,
#define QUIRK_FLAG_IFACE_DELAY (1U << 11) QUIRK_TYPE_CTL_MSG_DELAY_5M = 10,
#define QUIRK_FLAG_VALIDATE_RATES (1U << 12) QUIRK_TYPE_IFACE_DELAY = 11,
#define QUIRK_FLAG_DISABLE_AUTOSUSPEND (1U << 13) QUIRK_TYPE_VALIDATE_RATES = 12,
#define QUIRK_FLAG_IGNORE_CTL_ERROR (1U << 14) QUIRK_TYPE_DISABLE_AUTOSUSPEND = 13,
#define QUIRK_FLAG_DSD_RAW (1U << 15) QUIRK_TYPE_IGNORE_CTL_ERROR = 14,
#define QUIRK_FLAG_SET_IFACE_FIRST (1U << 16) QUIRK_TYPE_DSD_RAW = 15,
#define QUIRK_FLAG_GENERIC_IMPLICIT_FB (1U << 17) QUIRK_TYPE_SET_IFACE_FIRST = 16,
#define QUIRK_FLAG_SKIP_IMPLICIT_FB (1U << 18) QUIRK_TYPE_GENERIC_IMPLICIT_FB = 17,
#define QUIRK_FLAG_IFACE_SKIP_CLOSE (1U << 19) QUIRK_TYPE_SKIP_IMPLICIT_FB = 18,
#define QUIRK_FLAG_FORCE_IFACE_RESET (1U << 20) QUIRK_TYPE_IFACE_SKIP_CLOSE = 19,
#define QUIRK_FLAG_FIXED_RATE (1U << 21) QUIRK_TYPE_FORCE_IFACE_RESET = 20,
#define QUIRK_FLAG_MIC_RES_16 (1U << 22) QUIRK_TYPE_FIXED_RATE = 21,
#define QUIRK_FLAG_MIC_RES_384 (1U << 23) QUIRK_TYPE_MIC_RES_16 = 22,
#define QUIRK_FLAG_MIXER_PLAYBACK_MIN_MUTE (1U << 24) QUIRK_TYPE_MIC_RES_384 = 23,
#define QUIRK_FLAG_MIXER_CAPTURE_MIN_MUTE (1U << 25) QUIRK_TYPE_MIXER_PLAYBACK_MIN_MUTE = 24,
QUIRK_TYPE_MIXER_CAPTURE_MIN_MUTE = 25,
/* Please also edit snd_usb_audio_quirk_flag_names */
};
#define QUIRK_FLAG(x) BIT_U32(QUIRK_TYPE_ ## x)
#define QUIRK_FLAG_GET_SAMPLE_RATE QUIRK_FLAG(GET_SAMPLE_RATE)
#define QUIRK_FLAG_SHARE_MEDIA_DEVICE QUIRK_FLAG(SHARE_MEDIA_DEVICE)
#define QUIRK_FLAG_ALIGN_TRANSFER QUIRK_FLAG(ALIGN_TRANSFER)
#define QUIRK_FLAG_TX_LENGTH QUIRK_FLAG(TX_LENGTH)
#define QUIRK_FLAG_PLAYBACK_FIRST QUIRK_FLAG(PLAYBACK_FIRST)
#define QUIRK_FLAG_SKIP_CLOCK_SELECTOR QUIRK_FLAG(SKIP_CLOCK_SELECTOR)
#define QUIRK_FLAG_IGNORE_CLOCK_SOURCE QUIRK_FLAG(IGNORE_CLOCK_SOURCE)
#define QUIRK_FLAG_ITF_USB_DSD_DAC QUIRK_FLAG(ITF_USB_DSD_DAC)
#define QUIRK_FLAG_CTL_MSG_DELAY QUIRK_FLAG(CTL_MSG_DELAY)
#define QUIRK_FLAG_CTL_MSG_DELAY_1M QUIRK_FLAG(CTL_MSG_DELAY_1M)
#define QUIRK_FLAG_CTL_MSG_DELAY_5M QUIRK_FLAG(CTL_MSG_DELAY_5M)
#define QUIRK_FLAG_IFACE_DELAY QUIRK_FLAG(IFACE_DELAY)
#define QUIRK_FLAG_VALIDATE_RATES QUIRK_FLAG(VALIDATE_RATES)
#define QUIRK_FLAG_DISABLE_AUTOSUSPEND QUIRK_FLAG(DISABLE_AUTOSUSPEND)
#define QUIRK_FLAG_IGNORE_CTL_ERROR QUIRK_FLAG(IGNORE_CTL_ERROR)
#define QUIRK_FLAG_DSD_RAW QUIRK_FLAG(DSD_RAW)
#define QUIRK_FLAG_SET_IFACE_FIRST QUIRK_FLAG(SET_IFACE_FIRST)
#define QUIRK_FLAG_GENERIC_IMPLICIT_FB QUIRK_FLAG(GENERIC_IMPLICIT_FB)
#define QUIRK_FLAG_SKIP_IMPLICIT_FB QUIRK_FLAG(SKIP_IMPLICIT_FB)
#define QUIRK_FLAG_IFACE_SKIP_CLOSE QUIRK_FLAG(IFACE_SKIP_CLOSE)
#define QUIRK_FLAG_FORCE_IFACE_RESET QUIRK_FLAG(FORCE_IFACE_RESET)
#define QUIRK_FLAG_FIXED_RATE QUIRK_FLAG(FIXED_RATE)
#define QUIRK_FLAG_MIC_RES_16 QUIRK_FLAG(MIC_RES_16)
#define QUIRK_FLAG_MIC_RES_384 QUIRK_FLAG(MIC_RES_384)
#define QUIRK_FLAG_MIXER_PLAYBACK_MIN_MUTE QUIRK_FLAG(MIXER_PLAYBACK_MIN_MUTE)
#define QUIRK_FLAG_MIXER_CAPTURE_MIN_MUTE QUIRK_FLAG(MIXER_CAPTURE_MIN_MUTE)
#endif /* __USBAUDIO_H */ #endif /* __USBAUDIO_H */