diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2020-07-08 11:07:09 -0700 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2020-07-08 11:07:09 -0700 |
commit | 63e1968a2c87e9461e9694a96991935116e0cec7 (patch) | |
tree | 0a388ef222d4e0f3891231be97fa51dd9e860da2 | |
parent | 6ec4476ac82512f09c94aff5972654b70f3772b2 (diff) | |
parent | f79a732a8325dfbd570d87f1435019d7e5501c6d (diff) | |
download | linux-63e1968a2c87e9461e9694a96991935116e0cec7.tar.bz2 |
Merge tag 'sound-5.8-rc5' of git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound
Pull sound fixes from Takashi Iwai:
"A collection of small, mostly device-specific fixes.
The significant one is the regression fix for USB-audio implicit
feedback devices due to the incorrect frame size calculation, which
landed in 5.8 and stable trees.
In addition, a few usual HD-audio and USB-audio quirks, Intel HDMI
fixes, ASoC fsl and rt5682 fixes, as well as the fix in
compress-offload partial drain operation"
* tag 'sound-5.8-rc5' of git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound:
ALSA: compress: fix partial_drain completion state
ALSA: usb-audio: Add implicit feedback quirk for RTX6001
ALSA: usb-audio: add quirk for MacroSilicon MS2109
ALSA: hda/realtek: Enable headset mic of Acer Veriton N4660G with ALC269VC
ALSA: hda/realtek: Enable headset mic of Acer C20-820 with ALC269VC
ALSA: hda/realtek - Enable audio jacks of Acer vCopperbox with ALC269VC
ALSA: hda/realtek - Fix Lenovo Thinkpad X1 Carbon 7th quirk subdevice id
ALSA: hda/hdmi: improve debug traces for stream lookups
ALSA: hda/hdmi: fix failures at PCM open on Intel ICL and later
ALSA: opl3: fix infoleak in opl3
ALSA: usb-audio: Replace s/frame/packet/ where appropriate
ALSA: usb-audio: Fix packet size calculation
AsoC: amd: add missing snd- module prefix to the acp3x-rn driver kernel module
ALSA: hda - let hs_mic be picked ahead of hp_mic
ASoC: rt5682: fix the pop noise while OMTP type headset plugin
ASoC: fsl_mqs: Fix unchecked return value for clk_prepare_enable
ASoC: fsl_mqs: Don't check clock is NULL before calling clk API
-rw-r--r-- | include/sound/compress_driver.h | 10 | ||||
-rw-r--r-- | sound/core/compress_offload.c | 4 | ||||
-rw-r--r-- | sound/drivers/opl3/opl3_synth.c | 2 | ||||
-rw-r--r-- | sound/pci/hda/hda_auto_parser.c | 6 | ||||
-rw-r--r-- | sound/pci/hda/patch_hdmi.c | 41 | ||||
-rw-r--r-- | sound/pci/hda/patch_realtek.c | 38 | ||||
-rw-r--r-- | sound/soc/amd/renoir/Makefile | 7 | ||||
-rw-r--r-- | sound/soc/codecs/rt5682.c | 9 | ||||
-rw-r--r-- | sound/soc/fsl/fsl_mqs.c | 23 | ||||
-rw-r--r-- | sound/usb/card.h | 6 | ||||
-rw-r--r-- | sound/usb/endpoint.c | 18 | ||||
-rw-r--r-- | sound/usb/pcm.c | 1 | ||||
-rw-r--r-- | sound/usb/quirks-table.h | 52 |
13 files changed, 174 insertions, 43 deletions
diff --git a/include/sound/compress_driver.h b/include/sound/compress_driver.h index 6ce8effa0b12..70cbc5095e72 100644 --- a/include/sound/compress_driver.h +++ b/include/sound/compress_driver.h @@ -66,6 +66,7 @@ struct snd_compr_runtime { * @direction: stream direction, playback/recording * @metadata_set: metadata set flag, true when set * @next_track: has userspace signal next track transition, true when set + * @partial_drain: undergoing partial_drain for stream, true when set * @private_data: pointer to DSP private data * @dma_buffer: allocated buffer if any */ @@ -78,6 +79,7 @@ struct snd_compr_stream { enum snd_compr_direction direction; bool metadata_set; bool next_track; + bool partial_drain; void *private_data; struct snd_dma_buffer dma_buffer; }; @@ -182,7 +184,13 @@ static inline void snd_compr_drain_notify(struct snd_compr_stream *stream) if (snd_BUG_ON(!stream)) return; - stream->runtime->state = SNDRV_PCM_STATE_SETUP; + /* for partial_drain case we are back to running state on success */ + if (stream->partial_drain) { + stream->runtime->state = SNDRV_PCM_STATE_RUNNING; + stream->partial_drain = false; /* clear this flag as well */ + } else { + stream->runtime->state = SNDRV_PCM_STATE_SETUP; + } wake_up(&stream->runtime->sleep); } diff --git a/sound/core/compress_offload.c b/sound/core/compress_offload.c index 509290f2efa8..0e53f6f31916 100644 --- a/sound/core/compress_offload.c +++ b/sound/core/compress_offload.c @@ -764,6 +764,9 @@ static int snd_compr_stop(struct snd_compr_stream *stream) retval = stream->ops->trigger(stream, SNDRV_PCM_TRIGGER_STOP); if (!retval) { + /* clear flags and stop any drain wait */ + stream->partial_drain = false; + stream->metadata_set = false; snd_compr_drain_notify(stream); stream->runtime->total_bytes_available = 0; stream->runtime->total_bytes_transferred = 0; @@ -921,6 +924,7 @@ static int snd_compr_partial_drain(struct snd_compr_stream *stream) if (stream->next_track == false) return -EPERM; + stream->partial_drain = true; retval = stream->ops->trigger(stream, SND_COMPR_TRIGGER_PARTIAL_DRAIN); if (retval) { pr_debug("Partial drain returned failure\n"); diff --git a/sound/drivers/opl3/opl3_synth.c b/sound/drivers/opl3/opl3_synth.c index e69a4ef0d6bd..08c10ac9d6c8 100644 --- a/sound/drivers/opl3/opl3_synth.c +++ b/sound/drivers/opl3/opl3_synth.c @@ -91,6 +91,8 @@ int snd_opl3_ioctl(struct snd_hwdep * hw, struct file *file, { struct snd_dm_fm_info info; + memset(&info, 0, sizeof(info)); + info.fm_mode = opl3->fm_mode; info.rhythm = opl3->rhythm; if (copy_to_user(argp, &info, sizeof(struct snd_dm_fm_info))) diff --git a/sound/pci/hda/hda_auto_parser.c b/sound/pci/hda/hda_auto_parser.c index 2c6d2becfe1a..824f4ac1a8ce 100644 --- a/sound/pci/hda/hda_auto_parser.c +++ b/sound/pci/hda/hda_auto_parser.c @@ -72,6 +72,12 @@ static int compare_input_type(const void *ap, const void *bp) if (a->type != b->type) return (int)(a->type - b->type); + /* If has both hs_mic and hp_mic, pick the hs_mic ahead of hp_mic. */ + if (a->is_headset_mic && b->is_headphone_mic) + return -1; /* don't swap */ + else if (a->is_headphone_mic && b->is_headset_mic) + return 1; /* swap */ + /* In case one has boost and the other one has not, pick the one with boost first. */ return (int)(b->has_boost_on_pin - a->has_boost_on_pin); diff --git a/sound/pci/hda/patch_hdmi.c b/sound/pci/hda/patch_hdmi.c index e2b21ef5d7d1..41eaa89660c3 100644 --- a/sound/pci/hda/patch_hdmi.c +++ b/sound/pci/hda/patch_hdmi.c @@ -259,7 +259,7 @@ static int hinfo_to_pcm_index(struct hda_codec *codec, if (get_pcm_rec(spec, pcm_idx)->stream == hinfo) return pcm_idx; - codec_warn(codec, "HDMI: hinfo %p not registered\n", hinfo); + codec_warn(codec, "HDMI: hinfo %p not tied to a PCM\n", hinfo); return -EINVAL; } @@ -277,7 +277,8 @@ static int hinfo_to_pin_index(struct hda_codec *codec, return pin_idx; } - codec_dbg(codec, "HDMI: hinfo %p not registered\n", hinfo); + codec_dbg(codec, "HDMI: hinfo %p (pcm %d) not registered\n", hinfo, + hinfo_to_pcm_index(codec, hinfo)); return -EINVAL; } @@ -1804,33 +1805,43 @@ static int hdmi_add_cvt(struct hda_codec *codec, hda_nid_t cvt_nid) static int hdmi_parse_codec(struct hda_codec *codec) { - hda_nid_t nid; + hda_nid_t start_nid; + unsigned int caps; int i, nodes; - nodes = snd_hda_get_sub_nodes(codec, codec->core.afg, &nid); - if (!nid || nodes < 0) { + nodes = snd_hda_get_sub_nodes(codec, codec->core.afg, &start_nid); + if (!start_nid || nodes < 0) { codec_warn(codec, "HDMI: failed to get afg sub nodes\n"); return -EINVAL; } - for (i = 0; i < nodes; i++, nid++) { - unsigned int caps; - unsigned int type; + /* + * hdmi_add_pin() assumes total amount of converters to + * be known, so first discover all converters + */ + for (i = 0; i < nodes; i++) { + hda_nid_t nid = start_nid + i; caps = get_wcaps(codec, nid); - type = get_wcaps_type(caps); if (!(caps & AC_WCAP_DIGITAL)) continue; - switch (type) { - case AC_WID_AUD_OUT: + if (get_wcaps_type(caps) == AC_WID_AUD_OUT) hdmi_add_cvt(codec, nid); - break; - case AC_WID_PIN: + } + + /* discover audio pins */ + for (i = 0; i < nodes; i++) { + hda_nid_t nid = start_nid + i; + + caps = get_wcaps(codec, nid); + + if (!(caps & AC_WCAP_DIGITAL)) + continue; + + if (get_wcaps_type(caps) == AC_WID_PIN) hdmi_add_pin(codec, nid); - break; - } } return 0; diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index 737ef82a75fd..194ffa8c66ce 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c @@ -6149,6 +6149,9 @@ enum { ALC236_FIXUP_HP_MUTE_LED, ALC298_FIXUP_SAMSUNG_HEADPHONE_VERY_QUIET, ALC295_FIXUP_ASUS_MIC_NO_PRESENCE, + ALC269VC_FIXUP_ACER_VCOPPERBOX_PINS, + ALC269VC_FIXUP_ACER_HEADSET_MIC, + ALC269VC_FIXUP_ACER_MIC_NO_PRESENCE, }; static const struct hda_fixup alc269_fixups[] = { @@ -7327,6 +7330,35 @@ static const struct hda_fixup alc269_fixups[] = { .chained = true, .chain_id = ALC269_FIXUP_HEADSET_MODE }, + [ALC269VC_FIXUP_ACER_VCOPPERBOX_PINS] = { + .type = HDA_FIXUP_PINS, + .v.pins = (const struct hda_pintbl[]) { + { 0x14, 0x90100120 }, /* use as internal speaker */ + { 0x18, 0x02a111f0 }, /* use as headset mic, without its own jack detect */ + { 0x1a, 0x01011020 }, /* use as line out */ + { }, + }, + .chained = true, + .chain_id = ALC269_FIXUP_HEADSET_MIC + }, + [ALC269VC_FIXUP_ACER_HEADSET_MIC] = { + .type = HDA_FIXUP_PINS, + .v.pins = (const struct hda_pintbl[]) { + { 0x18, 0x02a11030 }, /* use as headset mic */ + { } + }, + .chained = true, + .chain_id = ALC269_FIXUP_HEADSET_MIC + }, + [ALC269VC_FIXUP_ACER_MIC_NO_PRESENCE] = { + .type = HDA_FIXUP_PINS, + .v.pins = (const struct hda_pintbl[]) { + { 0x18, 0x01a11130 }, /* use as headset mic, without its own jack detect */ + { } + }, + .chained = true, + .chain_id = ALC269_FIXUP_HEADSET_MIC + }, }; static const struct snd_pci_quirk alc269_fixup_tbl[] = { @@ -7342,10 +7374,13 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = { SND_PCI_QUIRK(0x1025, 0x0775, "Acer Aspire E1-572", ALC271_FIXUP_HP_GATE_MIC_JACK_E1_572), SND_PCI_QUIRK(0x1025, 0x079b, "Acer Aspire V5-573G", ALC282_FIXUP_ASPIRE_V5_PINS), SND_PCI_QUIRK(0x1025, 0x102b, "Acer Aspire C24-860", ALC286_FIXUP_ACER_AIO_MIC_NO_PRESENCE), + SND_PCI_QUIRK(0x1025, 0x1065, "Acer Aspire C20-820", ALC269VC_FIXUP_ACER_HEADSET_MIC), SND_PCI_QUIRK(0x1025, 0x106d, "Acer Cloudbook 14", ALC283_FIXUP_CHROME_BOOK), SND_PCI_QUIRK(0x1025, 0x1099, "Acer Aspire E5-523G", ALC255_FIXUP_ACER_MIC_NO_PRESENCE), SND_PCI_QUIRK(0x1025, 0x110e, "Acer Aspire ES1-432", ALC255_FIXUP_ACER_MIC_NO_PRESENCE), SND_PCI_QUIRK(0x1025, 0x1246, "Acer Predator Helios 500", ALC299_FIXUP_PREDATOR_SPK), + SND_PCI_QUIRK(0x1025, 0x1247, "Acer vCopperbox", ALC269VC_FIXUP_ACER_VCOPPERBOX_PINS), + SND_PCI_QUIRK(0x1025, 0x1248, "Acer Veriton N4660G", ALC269VC_FIXUP_ACER_MIC_NO_PRESENCE), SND_PCI_QUIRK(0x1025, 0x128f, "Acer Veriton Z6860G", ALC286_FIXUP_ACER_AIO_HEADSET_MIC), SND_PCI_QUIRK(0x1025, 0x1290, "Acer Veriton Z4860G", ALC286_FIXUP_ACER_AIO_HEADSET_MIC), SND_PCI_QUIRK(0x1025, 0x1291, "Acer Veriton Z4660G", ALC286_FIXUP_ACER_AIO_HEADSET_MIC), @@ -7571,8 +7606,7 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = { SND_PCI_QUIRK(0x17aa, 0x224c, "Thinkpad", ALC298_FIXUP_TPT470_DOCK), SND_PCI_QUIRK(0x17aa, 0x224d, "Thinkpad", ALC298_FIXUP_TPT470_DOCK), SND_PCI_QUIRK(0x17aa, 0x225d, "Thinkpad T480", ALC269_FIXUP_LIMIT_INT_MIC_BOOST), - SND_PCI_QUIRK(0x17aa, 0x2292, "Thinkpad X1 Yoga 7th", ALC285_FIXUP_THINKPAD_HEADSET_JACK), - SND_PCI_QUIRK(0x17aa, 0x2293, "Thinkpad X1 Carbon 7th", ALC285_FIXUP_THINKPAD_HEADSET_JACK), + SND_PCI_QUIRK(0x17aa, 0x2292, "Thinkpad X1 Carbon 7th", ALC285_FIXUP_THINKPAD_HEADSET_JACK), SND_PCI_QUIRK(0x17aa, 0x22be, "Thinkpad X1 Carbon 8th", ALC285_FIXUP_THINKPAD_HEADSET_JACK), SND_PCI_QUIRK(0x17aa, 0x30bb, "ThinkCentre AIO", ALC233_FIXUP_LENOVO_LINE2_MIC_HOTKEY), SND_PCI_QUIRK(0x17aa, 0x30e2, "ThinkCentre AIO", ALC233_FIXUP_LENOVO_LINE2_MIC_HOTKEY), diff --git a/sound/soc/amd/renoir/Makefile b/sound/soc/amd/renoir/Makefile index e4371932a55a..4a82690aec16 100644 --- a/sound/soc/amd/renoir/Makefile +++ b/sound/soc/amd/renoir/Makefile @@ -2,6 +2,7 @@ # Renoir platform Support snd-rn-pci-acp3x-objs := rn-pci-acp3x.o snd-acp3x-pdm-dma-objs := acp3x-pdm-dma.o -obj-$(CONFIG_SND_SOC_AMD_RENOIR) += snd-rn-pci-acp3x.o -obj-$(CONFIG_SND_SOC_AMD_RENOIR) += snd-acp3x-pdm-dma.o -obj-$(CONFIG_SND_SOC_AMD_RENOIR_MACH) += acp3x-rn.o +snd-acp3x-rn-objs := acp3x-rn.o +obj-$(CONFIG_SND_SOC_AMD_RENOIR) += snd-rn-pci-acp3x.o +obj-$(CONFIG_SND_SOC_AMD_RENOIR) += snd-acp3x-pdm-dma.o +obj-$(CONFIG_SND_SOC_AMD_RENOIR_MACH) += snd-acp3x-rn.o diff --git a/sound/soc/codecs/rt5682.c b/sound/soc/codecs/rt5682.c index 3e9d2c6c51f9..7d6670abdb08 100644 --- a/sound/soc/codecs/rt5682.c +++ b/sound/soc/codecs/rt5682.c @@ -932,7 +932,9 @@ int rt5682_headset_detect(struct snd_soc_component *component, int jack_insert) RT5682_PWR_ANLG_1, RT5682_PWR_FV2, RT5682_PWR_FV2); snd_soc_component_update_bits(component, RT5682_PWR_ANLG_3, RT5682_PWR_CBJ, RT5682_PWR_CBJ); - + snd_soc_component_update_bits(component, + RT5682_HP_CHARGE_PUMP_1, + RT5682_OSW_L_MASK | RT5682_OSW_R_MASK, 0); snd_soc_component_update_bits(component, RT5682_CBJ_CTRL_1, RT5682_TRIG_JD_MASK, RT5682_TRIG_JD_HIGH); @@ -956,6 +958,11 @@ int rt5682_headset_detect(struct snd_soc_component *component, int jack_insert) rt5682->jack_type = SND_JACK_HEADPHONE; break; } + + snd_soc_component_update_bits(component, + RT5682_HP_CHARGE_PUMP_1, + RT5682_OSW_L_MASK | RT5682_OSW_R_MASK, + RT5682_OSW_L_EN | RT5682_OSW_R_EN); } else { rt5682_enable_push_button_irq(component, false); snd_soc_component_update_bits(component, RT5682_CBJ_CTRL_1, diff --git a/sound/soc/fsl/fsl_mqs.c b/sound/soc/fsl/fsl_mqs.c index 0c813a45bba7..69aeb0e71844 100644 --- a/sound/soc/fsl/fsl_mqs.c +++ b/sound/soc/fsl/fsl_mqs.c @@ -265,12 +265,20 @@ static int fsl_mqs_remove(struct platform_device *pdev) static int fsl_mqs_runtime_resume(struct device *dev) { struct fsl_mqs *mqs_priv = dev_get_drvdata(dev); + int ret; - if (mqs_priv->ipg) - clk_prepare_enable(mqs_priv->ipg); + ret = clk_prepare_enable(mqs_priv->ipg); + if (ret) { + dev_err(dev, "failed to enable ipg clock\n"); + return ret; + } - if (mqs_priv->mclk) - clk_prepare_enable(mqs_priv->mclk); + ret = clk_prepare_enable(mqs_priv->mclk); + if (ret) { + dev_err(dev, "failed to enable mclk clock\n"); + clk_disable_unprepare(mqs_priv->ipg); + return ret; + } if (mqs_priv->use_gpr) regmap_write(mqs_priv->regmap, IOMUXC_GPR2, @@ -292,11 +300,8 @@ static int fsl_mqs_runtime_suspend(struct device *dev) regmap_read(mqs_priv->regmap, REG_MQS_CTRL, &mqs_priv->reg_mqs_ctrl); - if (mqs_priv->mclk) - clk_disable_unprepare(mqs_priv->mclk); - - if (mqs_priv->ipg) - clk_disable_unprepare(mqs_priv->ipg); + clk_disable_unprepare(mqs_priv->mclk); + clk_disable_unprepare(mqs_priv->ipg); return 0; } diff --git a/sound/usb/card.h b/sound/usb/card.h index d6219fba9699..de43267b9c8a 100644 --- a/sound/usb/card.h +++ b/sound/usb/card.h @@ -84,10 +84,10 @@ struct snd_usb_endpoint { dma_addr_t sync_dma; /* DMA address of syncbuf */ unsigned int pipe; /* the data i/o pipe */ - unsigned int framesize[2]; /* small/large frame sizes in samples */ - unsigned int sample_rem; /* remainder from division fs/fps */ + unsigned int packsize[2]; /* small/large packet sizes in samples */ + unsigned int sample_rem; /* remainder from division fs/pps */ unsigned int sample_accum; /* sample accumulator */ - unsigned int fps; /* frames per second */ + unsigned int pps; /* packets per second */ unsigned int freqn; /* nominal sampling rate in fs/fps in Q16.16 format */ unsigned int freqm; /* momentary sampling rate in fs/fps in Q16.16 format */ int freqshift; /* how much to shift the feedback value to get Q16.16 */ diff --git a/sound/usb/endpoint.c b/sound/usb/endpoint.c index 9bea7d3f99f8..88760268fb55 100644 --- a/sound/usb/endpoint.c +++ b/sound/usb/endpoint.c @@ -159,11 +159,11 @@ int snd_usb_endpoint_next_packet_size(struct snd_usb_endpoint *ep) return ep->maxframesize; ep->sample_accum += ep->sample_rem; - if (ep->sample_accum >= ep->fps) { - ep->sample_accum -= ep->fps; - ret = ep->framesize[1]; + if (ep->sample_accum >= ep->pps) { + ep->sample_accum -= ep->pps; + ret = ep->packsize[1]; } else { - ret = ep->framesize[0]; + ret = ep->packsize[0]; } return ret; @@ -1088,15 +1088,15 @@ int snd_usb_endpoint_set_params(struct snd_usb_endpoint *ep, if (snd_usb_get_speed(ep->chip->dev) == USB_SPEED_FULL) { ep->freqn = get_usb_full_speed_rate(rate); - ep->fps = 1000; + ep->pps = 1000 >> ep->datainterval; } else { ep->freqn = get_usb_high_speed_rate(rate); - ep->fps = 8000; + ep->pps = 8000 >> ep->datainterval; } - ep->sample_rem = rate % ep->fps; - ep->framesize[0] = rate / ep->fps; - ep->framesize[1] = (rate + (ep->fps - 1)) / ep->fps; + ep->sample_rem = rate % ep->pps; + ep->packsize[0] = rate / ep->pps; + ep->packsize[1] = (rate + (ep->pps - 1)) / ep->pps; /* calculate the frequency in 16.16 format */ ep->freqm = ep->freqn; diff --git a/sound/usb/pcm.c b/sound/usb/pcm.c index a777d36c4f5a..40b7cd13fed9 100644 --- a/sound/usb/pcm.c +++ b/sound/usb/pcm.c @@ -368,6 +368,7 @@ static int set_sync_ep_implicit_fb_quirk(struct snd_usb_substream *subs, goto add_sync_ep_from_ifnum; case USB_ID(0x07fd, 0x0008): /* MOTU M Series */ case USB_ID(0x31e9, 0x0002): /* Solid State Logic SSL2+ */ + case USB_ID(0x0d9a, 0x00df): /* RTX6001 */ ep = 0x81; ifnum = 2; goto add_sync_ep_from_ifnum; diff --git a/sound/usb/quirks-table.h b/sound/usb/quirks-table.h index 4ec491011b19..9092cc0aa807 100644 --- a/sound/usb/quirks-table.h +++ b/sound/usb/quirks-table.h @@ -3633,4 +3633,56 @@ ALC1220_VB_DESKTOP(0x26ce, 0x0a01), /* Asrock TRX40 Creator */ } }, +/* + * 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 pretend to be 96kHz mono as a workaround for stereo being broken + * by that... + * + * They also have swapped L-R channels, but that's for userspace to deal + * with. + */ +{ + USB_DEVICE(0x534d, 0x2109), + .driver_info = (unsigned long) &(const struct snd_usb_audio_quirk) { + .vendor_name = "MacroSilicon", + .product_name = "MS2109", + .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, + }, + { + .ifnum = 3, + .type = QUIRK_AUDIO_FIXED_ENDPOINT, + .data = &(const struct audioformat) { + .formats = SNDRV_PCM_FMTBIT_S16_LE, + .channels = 2, + .iface = 3, + .altsetting = 1, + .altset_idx = 1, + .attributes = 0, + .endpoint = 0x82, + .ep_attr = USB_ENDPOINT_XFER_ISOC | + USB_ENDPOINT_SYNC_ASYNC, + .rates = SNDRV_PCM_RATE_CONTINUOUS, + .rate_min = 48000, + .rate_max = 48000, + } + }, + { + .ifnum = -1 + } + } + } +}, + #undef USB_DEVICE_VENDOR_SPEC |