diff options
Diffstat (limited to 'sound')
45 files changed, 538 insertions, 210 deletions
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/hda/intel-dsp-config.c b/sound/hda/intel-dsp-config.c index 20b8f6cb3ff8..99aec7349167 100644 --- a/sound/hda/intel-dsp-config.c +++ b/sound/hda/intel-dsp-config.c @@ -208,8 +208,8 @@ static const struct config_entry config_table[] = { }, #endif +#if IS_ENABLED(CONFIG_SND_SOC_SOF_COMETLAKE) /* Cometlake-LP */ -#if IS_ENABLED(CONFIG_SND_SOC_SOF_COMETLAKE_LP) { .flags = FLAG_SOF, .device = 0x02c8, @@ -240,9 +240,7 @@ static const struct config_entry config_table[] = { .flags = FLAG_SOF | FLAG_SOF_ONLY_IF_DMIC_OR_SOUNDWIRE, .device = 0x02c8, }, -#endif /* Cometlake-H */ -#if IS_ENABLED(CONFIG_SND_SOC_SOF_COMETLAKE_H) { .flags = FLAG_SOF, .device = 0x06c8, 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/hda_intel.c b/sound/pci/hda/hda_intel.c index d20aedd103c6..3565e2ab0965 100644 --- a/sound/pci/hda/hda_intel.c +++ b/sound/pci/hda/hda_intel.c @@ -2470,6 +2470,9 @@ static const struct pci_device_id azx_ids[] = { /* Icelake */ { PCI_DEVICE(0x8086, 0x34c8), .driver_data = AZX_DRIVER_SKL | AZX_DCAPS_INTEL_SKYLAKE}, + /* Icelake-H */ + { PCI_DEVICE(0x8086, 0x3dc8), + .driver_data = AZX_DRIVER_SKL | AZX_DCAPS_INTEL_SKYLAKE}, /* Jasperlake */ { PCI_DEVICE(0x8086, 0x38c8), .driver_data = AZX_DRIVER_SKL | AZX_DCAPS_INTEL_SKYLAKE}, @@ -2478,9 +2481,14 @@ static const struct pci_device_id azx_ids[] = { /* Tigerlake */ { PCI_DEVICE(0x8086, 0xa0c8), .driver_data = AZX_DRIVER_SKL | AZX_DCAPS_INTEL_SKYLAKE}, + /* Tigerlake-H */ + { PCI_DEVICE(0x8086, 0x43c8), + .driver_data = AZX_DRIVER_SKL | AZX_DCAPS_INTEL_SKYLAKE}, /* Elkhart Lake */ { PCI_DEVICE(0x8086, 0x4b55), .driver_data = AZX_DRIVER_SKL | AZX_DCAPS_INTEL_SKYLAKE}, + { PCI_DEVICE(0x8086, 0x4b58), + .driver_data = AZX_DRIVER_SKL | AZX_DCAPS_INTEL_SKYLAKE}, /* Broxton-P(Apollolake) */ { PCI_DEVICE(0x8086, 0x5a98), .driver_data = AZX_DRIVER_SKL | AZX_DCAPS_INTEL_BROXTON }, diff --git a/sound/pci/hda/patch_hdmi.c b/sound/pci/hda/patch_hdmi.c index fbd7cc6026d8..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; @@ -4145,6 +4156,11 @@ HDA_CODEC_ENTRY(0x10de0095, "GPU 95 HDMI/DP", patch_nvhdmi), HDA_CODEC_ENTRY(0x10de0097, "GPU 97 HDMI/DP", patch_nvhdmi), HDA_CODEC_ENTRY(0x10de0098, "GPU 98 HDMI/DP", patch_nvhdmi), HDA_CODEC_ENTRY(0x10de0099, "GPU 99 HDMI/DP", patch_nvhdmi), +HDA_CODEC_ENTRY(0x10de009a, "GPU 9a HDMI/DP", patch_nvhdmi), +HDA_CODEC_ENTRY(0x10de009d, "GPU 9d HDMI/DP", patch_nvhdmi), +HDA_CODEC_ENTRY(0x10de009e, "GPU 9e HDMI/DP", patch_nvhdmi), +HDA_CODEC_ENTRY(0x10de009f, "GPU 9f HDMI/DP", patch_nvhdmi), +HDA_CODEC_ENTRY(0x10de00a0, "GPU a0 HDMI/DP", patch_nvhdmi), HDA_CODEC_ENTRY(0x10de8001, "MCP73 HDMI", patch_nvhdmi_2ch), HDA_CODEC_ENTRY(0x10de8067, "MCP67/68 HDMI", patch_nvhdmi_2ch), HDA_CODEC_ENTRY(0x11069f80, "VX900 HDMI/DP", patch_via_hdmi), diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index 6d73f8beadb6..1b06c4261248 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c @@ -2461,6 +2461,7 @@ static const struct snd_pci_quirk alc882_fixup_tbl[] = { SND_PCI_QUIRK(0x1458, 0xa0b8, "Gigabyte AZ370-Gaming", ALC1220_FIXUP_GB_DUAL_CODECS), SND_PCI_QUIRK(0x1458, 0xa0cd, "Gigabyte X570 Aorus Master", ALC1220_FIXUP_CLEVO_P950), SND_PCI_QUIRK(0x1458, 0xa0ce, "Gigabyte X570 Aorus Xtreme", ALC1220_FIXUP_CLEVO_P950), + SND_PCI_QUIRK(0x1462, 0x11f7, "MSI-GE63", ALC1220_FIXUP_CLEVO_P950), SND_PCI_QUIRK(0x1462, 0x1228, "MSI-GP63", ALC1220_FIXUP_CLEVO_P950), SND_PCI_QUIRK(0x1462, 0x1275, "MSI-GL63", ALC1220_FIXUP_CLEVO_P950), SND_PCI_QUIRK(0x1462, 0x1276, "MSI-GL73", ALC1220_FIXUP_CLEVO_P950), @@ -6148,6 +6149,11 @@ 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, + ALC289_FIXUP_ASUS_G401, + ALC256_FIXUP_ACER_MIC_NO_PRESENCE, }; static const struct hda_fixup alc269_fixups[] = { @@ -7113,7 +7119,7 @@ static const struct hda_fixup alc269_fixups[] = { { } }, .chained = true, - .chain_id = ALC269_FIXUP_HEADSET_MODE_NO_HP_MIC + .chain_id = ALC269_FIXUP_HEADSET_MIC }, [ALC294_FIXUP_ASUS_HEADSET_MIC] = { .type = HDA_FIXUP_PINS, @@ -7122,7 +7128,7 @@ static const struct hda_fixup alc269_fixups[] = { { } }, .chained = true, - .chain_id = ALC269_FIXUP_HEADSET_MODE_NO_HP_MIC + .chain_id = ALC269_FIXUP_HEADSET_MIC }, [ALC294_FIXUP_ASUS_SPK] = { .type = HDA_FIXUP_VERBS, @@ -7130,6 +7136,8 @@ static const struct hda_fixup alc269_fixups[] = { /* Set EAPD high */ { 0x20, AC_VERB_SET_COEF_INDEX, 0x40 }, { 0x20, AC_VERB_SET_PROC_COEF, 0x8800 }, + { 0x20, AC_VERB_SET_COEF_INDEX, 0x0f }, + { 0x20, AC_VERB_SET_PROC_COEF, 0x7774 }, { } }, .chained = true, @@ -7326,6 +7334,51 @@ 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 + }, + [ALC289_FIXUP_ASUS_G401] = { + .type = HDA_FIXUP_PINS, + .v.pins = (const struct hda_pintbl[]) { + { 0x19, 0x03a11020 }, /* headset mic with jack detect */ + { } + }, + }, + [ALC256_FIXUP_ACER_MIC_NO_PRESENCE] = { + .type = HDA_FIXUP_PINS, + .v.pins = (const struct hda_pintbl[]) { + { 0x19, 0x02a11120 }, /* use as headset mic, without its own jack detect */ + { } + }, + .chained = true, + .chain_id = ALC256_FIXUP_ASUS_HEADSET_MODE + }, }; static const struct snd_pci_quirk alc269_fixup_tbl[] = { @@ -7341,16 +7394,20 @@ 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), SND_PCI_QUIRK(0x1025, 0x1308, "Acer Aspire Z24-890", ALC286_FIXUP_ACER_AIO_HEADSET_MIC), SND_PCI_QUIRK(0x1025, 0x132a, "Acer TravelMate B114-21", ALC233_FIXUP_ACER_HEADSET_MIC), SND_PCI_QUIRK(0x1025, 0x1330, "Acer TravelMate X514-51T", ALC255_FIXUP_ACER_HEADSET_MIC), + SND_PCI_QUIRK(0x1025, 0x1430, "Acer TravelMate B311R-31", ALC256_FIXUP_ACER_MIC_NO_PRESENCE), SND_PCI_QUIRK(0x1028, 0x0470, "Dell M101z", ALC269_FIXUP_DELL_M101Z), SND_PCI_QUIRK(0x1028, 0x054b, "Dell XPS one 2710", ALC275_FIXUP_DELL_XPS), SND_PCI_QUIRK(0x1028, 0x05bd, "Dell Latitude E6440", ALC292_FIXUP_DELL_E7X), @@ -7470,6 +7527,8 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = { SND_PCI_QUIRK(0x103c, 0x83b9, "HP Spectre x360", ALC269_FIXUP_HP_MUTE_LED_MIC3), SND_PCI_QUIRK(0x103c, 0x8497, "HP Envy x360", ALC269_FIXUP_HP_MUTE_LED_MIC3), SND_PCI_QUIRK(0x103c, 0x84e7, "HP Pavilion 15", ALC269_FIXUP_HP_MUTE_LED_MIC3), + SND_PCI_QUIRK(0x103c, 0x869d, "HP", ALC236_FIXUP_HP_MUTE_LED), + SND_PCI_QUIRK(0x103c, 0x8729, "HP", ALC285_FIXUP_HP_GPIO_LED), SND_PCI_QUIRK(0x103c, 0x8736, "HP", ALC285_FIXUP_HP_GPIO_LED), SND_PCI_QUIRK(0x103c, 0x877a, "HP", ALC285_FIXUP_HP_MUTE_LED), SND_PCI_QUIRK(0x103c, 0x877d, "HP", ALC236_FIXUP_HP_MUTE_LED), @@ -7492,6 +7551,7 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = { SND_PCI_QUIRK(0x1043, 0x17d1, "ASUS UX431FL", ALC294_FIXUP_ASUS_DUAL_SPK), SND_PCI_QUIRK(0x1043, 0x18b1, "Asus MJ401TA", ALC256_FIXUP_ASUS_HEADSET_MIC), SND_PCI_QUIRK(0x1043, 0x18f1, "Asus FX505DT", ALC256_FIXUP_ASUS_HEADSET_MIC), + SND_PCI_QUIRK(0x1043, 0x194e, "ASUS UX563FD", ALC294_FIXUP_ASUS_HPE), SND_PCI_QUIRK(0x1043, 0x19ce, "ASUS B9450FA", ALC294_FIXUP_ASUS_HPE), SND_PCI_QUIRK(0x1043, 0x19e1, "ASUS UX581LV", ALC295_FIXUP_ASUS_MIC_NO_PRESENCE), SND_PCI_QUIRK(0x1043, 0x1a13, "Asus G73Jw", ALC269_FIXUP_ASUS_G73JW), @@ -7501,6 +7561,7 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = { SND_PCI_QUIRK(0x1043, 0x1bbd, "ASUS Z550MA", ALC255_FIXUP_ASUS_MIC_NO_PRESENCE), SND_PCI_QUIRK(0x1043, 0x1c23, "Asus X55U", ALC269_FIXUP_LIMIT_INT_MIC_BOOST), SND_PCI_QUIRK(0x1043, 0x1ccd, "ASUS X555UB", ALC256_FIXUP_ASUS_MIC), + SND_PCI_QUIRK(0x1043, 0x1f11, "ASUS Zephyrus G14", ALC289_FIXUP_ASUS_G401), SND_PCI_QUIRK(0x1043, 0x3030, "ASUS ZN270IE", ALC256_FIXUP_ASUS_AIO_GPIO2), SND_PCI_QUIRK(0x1043, 0x831a, "ASUS P901", ALC269_FIXUP_STEREO_DMIC), SND_PCI_QUIRK(0x1043, 0x834a, "ASUS S101", ALC269_FIXUP_STEREO_DMIC), @@ -7520,6 +7581,7 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = { SND_PCI_QUIRK(0x10cf, 0x1629, "Lifebook U7x7", ALC255_FIXUP_LIFEBOOK_U7x7_HEADSET_MIC), SND_PCI_QUIRK(0x10cf, 0x1845, "Lifebook U904", ALC269_FIXUP_LIFEBOOK_EXTMIC), SND_PCI_QUIRK(0x10ec, 0x10f2, "Intel Reference board", ALC700_FIXUP_INTEL_REFERENCE), + SND_PCI_QUIRK(0x10ec, 0x1230, "Intel Reference board", ALC225_FIXUP_HEADSET_JACK), SND_PCI_QUIRK(0x10f7, 0x8338, "Panasonic CF-SZ6", ALC269_FIXUP_HEADSET_MODE), SND_PCI_QUIRK(0x144d, 0xc109, "Samsung Ativ book 9 (NP900X3G)", ALC269_FIXUP_INV_DMIC), SND_PCI_QUIRK(0x144d, 0xc169, "Samsung Notebook 9 Pen (NP930SBE-K01US)", ALC298_FIXUP_SAMSUNG_HEADPHONE_VERY_QUIET), @@ -7568,8 +7630,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/raven/acp3x-pcm-dma.c b/sound/soc/amd/raven/acp3x-pcm-dma.c index d8f554f369a8..e6386de20ac7 100644 --- a/sound/soc/amd/raven/acp3x-pcm-dma.c +++ b/sound/soc/amd/raven/acp3x-pcm-dma.c @@ -342,11 +342,34 @@ static int acp3x_dma_close(struct snd_soc_component *component, { struct snd_soc_pcm_runtime *prtd; struct i2s_dev_data *adata; + struct i2s_stream_instance *ins; prtd = substream->private_data; component = snd_soc_rtdcom_lookup(prtd, DRV_NAME); adata = dev_get_drvdata(component->dev); + ins = substream->runtime->private_data; + if (!ins) + return -EINVAL; + if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { + switch (ins->i2s_instance) { + case I2S_BT_INSTANCE: + adata->play_stream = NULL; + break; + case I2S_SP_INSTANCE: + default: + adata->i2ssp_play_stream = NULL; + } + } else { + switch (ins->i2s_instance) { + case I2S_BT_INSTANCE: + adata->capture_stream = NULL; + break; + case I2S_SP_INSTANCE: + default: + adata->i2ssp_capture_stream = NULL; + } + } /* Disable ACP irq, when the current stream is being closed and * another stream is also not active. @@ -354,13 +377,6 @@ static int acp3x_dma_close(struct snd_soc_component *component, if (!adata->play_stream && !adata->capture_stream && !adata->i2ssp_play_stream && !adata->i2ssp_capture_stream) rv_writel(0, adata->acp3x_base + mmACP_EXTERNAL_INTR_ENB); - if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { - adata->play_stream = NULL; - adata->i2ssp_play_stream = NULL; - } else { - adata->capture_stream = NULL; - adata->i2ssp_capture_stream = NULL; - } return 0; } 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/hdac_hda.c b/sound/soc/codecs/hdac_hda.c index de003acb1951..473efe9ef998 100644 --- a/sound/soc/codecs/hdac_hda.c +++ b/sound/soc/codecs/hdac_hda.c @@ -441,13 +441,13 @@ static int hdac_hda_codec_probe(struct snd_soc_component *component) ret = snd_hda_codec_set_name(hcodec, hcodec->preset->name); if (ret < 0) { dev_err(&hdev->dev, "name failed %s\n", hcodec->preset->name); - goto error; + goto error_pm; } ret = snd_hdac_regmap_init(&hcodec->core); if (ret < 0) { dev_err(&hdev->dev, "regmap init failed\n"); - goto error; + goto error_pm; } patch = (hda_codec_patch_t)hcodec->preset->driver_data; @@ -455,7 +455,7 @@ static int hdac_hda_codec_probe(struct snd_soc_component *component) ret = patch(hcodec); if (ret < 0) { dev_err(&hdev->dev, "patch failed %d\n", ret); - goto error; + goto error_regmap; } } else { dev_dbg(&hdev->dev, "no patch file found\n"); @@ -467,7 +467,7 @@ static int hdac_hda_codec_probe(struct snd_soc_component *component) ret = snd_hda_codec_parse_pcms(hcodec); if (ret < 0) { dev_err(&hdev->dev, "unable to map pcms to dai %d\n", ret); - goto error; + goto error_regmap; } /* HDMI controls need to be created in machine drivers */ @@ -476,7 +476,7 @@ static int hdac_hda_codec_probe(struct snd_soc_component *component) if (ret < 0) { dev_err(&hdev->dev, "unable to create controls %d\n", ret); - goto error; + goto error_regmap; } } @@ -496,7 +496,9 @@ static int hdac_hda_codec_probe(struct snd_soc_component *component) return 0; -error: +error_regmap: + snd_hdac_regmap_exit(hdev); +error_pm: pm_runtime_put(&hdev->dev); error_no_pm: snd_hdac_ext_bus_link_put(hdev->bus, hlink); @@ -518,6 +520,8 @@ static void hdac_hda_codec_remove(struct snd_soc_component *component) pm_runtime_disable(&hdev->dev); snd_hdac_ext_bus_link_put(hdev->bus, hlink); + + snd_hdac_regmap_exit(hdev); } static const struct snd_soc_dapm_route hdac_hda_dapm_routes[] = { diff --git a/sound/soc/codecs/max98390.c b/sound/soc/codecs/max98390.c index 0d63ebfbff2f..e6613b52bd78 100644 --- a/sound/soc/codecs/max98390.c +++ b/sound/soc/codecs/max98390.c @@ -700,8 +700,8 @@ static bool max98390_readable_register(struct device *dev, unsigned int reg) case MAX98390_IRQ_CTRL ... MAX98390_WDOG_CTRL: case MAX98390_MEAS_ADC_THERM_WARN_THRESH ... MAX98390_BROWNOUT_INFINITE_HOLD: - case MAX98390_BROWNOUT_LVL_HOLD ... THERMAL_COILTEMP_RD_BACK_BYTE0: - case DSMIG_DEBUZZER_THRESHOLD ... MAX98390_R24FF_REV_ID: + case MAX98390_BROWNOUT_LVL_HOLD ... DSMIG_DEBUZZER_THRESHOLD: + case DSM_VOL_ENA ... MAX98390_R24FF_REV_ID: return true; default: return false; @@ -717,7 +717,7 @@ static bool max98390_volatile_reg(struct device *dev, unsigned int reg) case MAX98390_BROWNOUT_LOWEST_STATUS: case MAX98390_ENV_TRACK_BOOST_VOUT_READ: case DSM_STBASS_HPF_B0_BYTE0 ... DSM_DEBUZZER_ATTACK_TIME_BYTE2: - case THERMAL_RDC_RD_BACK_BYTE1 ... THERMAL_COILTEMP_RD_BACK_BYTE0: + case THERMAL_RDC_RD_BACK_BYTE1 ... DSMIG_DEBUZZER_THRESHOLD: case DSM_THERMAL_GAIN ... DSM_WBDRC_GAIN: return true; default: diff --git a/sound/soc/codecs/rt1015.c b/sound/soc/codecs/rt1015.c index 67e2e944d21b..2cccb310fa96 100644 --- a/sound/soc/codecs/rt1015.c +++ b/sound/soc/codecs/rt1015.c @@ -34,30 +34,32 @@ static const struct reg_default rt1015_reg[] = { { 0x0000, 0x0000 }, { 0x0004, 0xa000 }, { 0x0006, 0x0003 }, - { 0x000a, 0x0802 }, - { 0x000c, 0x0020 }, + { 0x000a, 0x081e }, + { 0x000c, 0x0006 }, { 0x000e, 0x0000 }, { 0x0010, 0x0000 }, { 0x0012, 0x0000 }, + { 0x0014, 0x0000 }, + { 0x0016, 0x0000 }, + { 0x0018, 0x0000 }, { 0x0020, 0x8000 }, - { 0x0022, 0x471b }, - { 0x006a, 0x0000 }, - { 0x006c, 0x4020 }, + { 0x0022, 0x8043 }, { 0x0076, 0x0000 }, { 0x0078, 0x0000 }, - { 0x007a, 0x0000 }, + { 0x007a, 0x0002 }, { 0x007c, 0x10ec }, { 0x007d, 0x1015 }, { 0x00f0, 0x5000 }, - { 0x00f2, 0x0774 }, - { 0x00f3, 0x8400 }, + { 0x00f2, 0x004c }, + { 0x00f3, 0xecfe }, { 0x00f4, 0x0000 }, + { 0x00f6, 0x0400 }, { 0x0100, 0x0028 }, { 0x0102, 0xff02 }, - { 0x0104, 0x8232 }, + { 0x0104, 0xa213 }, { 0x0106, 0x200c }, - { 0x010c, 0x002f }, - { 0x010e, 0xc000 }, + { 0x010c, 0x0000 }, + { 0x010e, 0x0058 }, { 0x0111, 0x0200 }, { 0x0112, 0x0400 }, { 0x0114, 0x0022 }, @@ -65,38 +67,46 @@ static const struct reg_default rt1015_reg[] = { { 0x0118, 0x0000 }, { 0x011a, 0x0123 }, { 0x011c, 0x4567 }, - { 0x0300, 0xdddd }, - { 0x0302, 0x0000 }, - { 0x0311, 0x9330 }, - { 0x0313, 0x0000 }, - { 0x0314, 0x0000 }, + { 0x0300, 0x203d }, + { 0x0302, 0x001e }, + { 0x0311, 0x0000 }, + { 0x0313, 0x6014 }, + { 0x0314, 0x00a2 }, { 0x031a, 0x00a0 }, { 0x031c, 0x001f }, { 0x031d, 0xffff }, { 0x031e, 0x0000 }, { 0x031f, 0x0000 }, + { 0x0320, 0x0000 }, { 0x0321, 0x0000 }, - { 0x0322, 0x0000 }, - { 0x0328, 0x0000 }, - { 0x0329, 0x0000 }, - { 0x032a, 0x0000 }, - { 0x032b, 0x0000 }, - { 0x032c, 0x0000 }, - { 0x032d, 0x0000 }, - { 0x032e, 0x030e }, - { 0x0330, 0x0080 }, + { 0x0322, 0xd7df }, + { 0x0328, 0x10b2 }, + { 0x0329, 0x0175 }, + { 0x032a, 0x36ad }, + { 0x032b, 0x7e55 }, + { 0x032c, 0x0520 }, + { 0x032d, 0xaa00 }, + { 0x032e, 0x570e }, + { 0x0330, 0xe180 }, { 0x0332, 0x0034 }, - { 0x0334, 0x0000 }, - { 0x0336, 0x0000 }, + { 0x0334, 0x0001 }, + { 0x0336, 0x0010 }, + { 0x0338, 0x0000 }, + { 0x04fa, 0x0030 }, + { 0x04fc, 0x35c8 }, + { 0x04fe, 0x0800 }, + { 0x0500, 0x0400 }, + { 0x0502, 0x1000 }, + { 0x0504, 0x0000 }, { 0x0506, 0x04ff }, - { 0x0508, 0x0030 }, - { 0x050a, 0x0018 }, - { 0x0519, 0x307f }, - { 0x051a, 0xffff }, - { 0x051b, 0x4000 }, + { 0x0508, 0x0010 }, + { 0x050a, 0x001a }, + { 0x0519, 0x1c68 }, + { 0x051a, 0x0ccc }, + { 0x051b, 0x0666 }, { 0x051d, 0x0000 }, { 0x051f, 0x0000 }, - { 0x0536, 0x1000 }, + { 0x0536, 0x061c }, { 0x0538, 0x0000 }, { 0x053a, 0x0000 }, { 0x053c, 0x0000 }, @@ -110,19 +120,18 @@ static const struct reg_default rt1015_reg[] = { { 0x0544, 0x0000 }, { 0x0568, 0x0000 }, { 0x056a, 0x0000 }, - { 0x1000, 0x0000 }, - { 0x1002, 0x6505 }, + { 0x1000, 0x0040 }, + { 0x1002, 0x5405 }, { 0x1006, 0x5515 }, - { 0x1007, 0x003f }, - { 0x1009, 0x770f }, - { 0x100a, 0x01ff }, - { 0x100c, 0x0000 }, + { 0x1007, 0x05f7 }, + { 0x1009, 0x0b0a }, + { 0x100a, 0x00ef }, { 0x100d, 0x0003 }, { 0x1010, 0xa433 }, { 0x1020, 0x0000 }, - { 0x1200, 0x3d02 }, - { 0x1202, 0x0813 }, - { 0x1204, 0x0211 }, + { 0x1200, 0x5a01 }, + { 0x1202, 0x6524 }, + { 0x1204, 0x1f00 }, { 0x1206, 0x0000 }, { 0x1208, 0x0000 }, { 0x120a, 0x0000 }, @@ -130,16 +139,16 @@ static const struct reg_default rt1015_reg[] = { { 0x120e, 0x0000 }, { 0x1210, 0x0000 }, { 0x1212, 0x0000 }, - { 0x1300, 0x0701 }, - { 0x1302, 0x12f9 }, - { 0x1304, 0x3405 }, + { 0x1300, 0x10a1 }, + { 0x1302, 0x12ff }, + { 0x1304, 0x0400 }, { 0x1305, 0x0844 }, - { 0x1306, 0x1611 }, + { 0x1306, 0x4611 }, { 0x1308, 0x555e }, { 0x130a, 0x0000 }, - { 0x130c, 0x2400}, - { 0x130e, 0x7700 }, - { 0x130f, 0x0000 }, + { 0x130c, 0x2000 }, + { 0x130e, 0x0100 }, + { 0x130f, 0x0001 }, { 0x1310, 0x0000 }, { 0x1312, 0x0000 }, { 0x1314, 0x0000 }, @@ -209,6 +218,9 @@ static bool rt1015_volatile_register(struct device *dev, unsigned int reg) case RT1015_DC_CALIB_CLSD7: case RT1015_DC_CALIB_CLSD8: case RT1015_S_BST_TIMING_INTER1: + case RT1015_OSCK_STA: + case RT1015_MONO_DYNA_CTRL1: + case RT1015_MONO_DYNA_CTRL5: return true; default: @@ -224,6 +236,12 @@ static bool rt1015_readable_register(struct device *dev, unsigned int reg) case RT1015_CLK3: case RT1015_PLL1: case RT1015_PLL2: + case RT1015_DUM_RW1: + case RT1015_DUM_RW2: + case RT1015_DUM_RW3: + case RT1015_DUM_RW4: + case RT1015_DUM_RW5: + case RT1015_DUM_RW6: case RT1015_CLK_DET: case RT1015_SIL_DET: case RT1015_CUSTOMER_ID: @@ -235,6 +253,7 @@ static bool rt1015_readable_register(struct device *dev, unsigned int reg) case RT1015_PAD_DRV2: case RT1015_GAT_BOOST: case RT1015_PRO_ALT: + case RT1015_OSCK_STA: case RT1015_MAN_I2C: case RT1015_DAC1: case RT1015_DAC2: @@ -272,6 +291,13 @@ static bool rt1015_readable_register(struct device *dev, unsigned int reg) case RT1015_SMART_BST_CTRL2: case RT1015_ANA_CTRL1: case RT1015_ANA_CTRL2: + case RT1015_PWR_STATE_CTRL: + case RT1015_MONO_DYNA_CTRL: + case RT1015_MONO_DYNA_CTRL1: + case RT1015_MONO_DYNA_CTRL2: + case RT1015_MONO_DYNA_CTRL3: + case RT1015_MONO_DYNA_CTRL4: + case RT1015_MONO_DYNA_CTRL5: case RT1015_SPK_VOL: case RT1015_SHORT_DETTOP1: case RT1015_SHORT_DETTOP2: diff --git a/sound/soc/codecs/rt1015.h b/sound/soc/codecs/rt1015.h index 6fbe802082c4..8169962935a5 100644 --- a/sound/soc/codecs/rt1015.h +++ b/sound/soc/codecs/rt1015.h @@ -21,6 +21,12 @@ #define RT1015_CLK3 0x0006 #define RT1015_PLL1 0x000a #define RT1015_PLL2 0x000c +#define RT1015_DUM_RW1 0x000e +#define RT1015_DUM_RW2 0x0010 +#define RT1015_DUM_RW3 0x0012 +#define RT1015_DUM_RW4 0x0014 +#define RT1015_DUM_RW5 0x0016 +#define RT1015_DUM_RW6 0x0018 #define RT1015_CLK_DET 0x0020 #define RT1015_SIL_DET 0x0022 #define RT1015_CUSTOMER_ID 0x0076 @@ -32,6 +38,7 @@ #define RT1015_PAD_DRV2 0x00f2 #define RT1015_GAT_BOOST 0x00f3 #define RT1015_PRO_ALT 0x00f4 +#define RT1015_OSCK_STA 0x00f6 #define RT1015_MAN_I2C 0x0100 #define RT1015_DAC1 0x0102 #define RT1015_DAC2 0x0104 @@ -70,7 +77,13 @@ #define RT1015_ANA_CTRL1 0x0334 #define RT1015_ANA_CTRL2 0x0336 #define RT1015_PWR_STATE_CTRL 0x0338 -#define RT1015_SPK_VOL 0x0506 +#define RT1015_MONO_DYNA_CTRL 0x04fa +#define RT1015_MONO_DYNA_CTRL1 0x04fc +#define RT1015_MONO_DYNA_CTRL2 0x04fe +#define RT1015_MONO_DYNA_CTRL3 0x0500 +#define RT1015_MONO_DYNA_CTRL4 0x0502 +#define RT1015_MONO_DYNA_CTRL5 0x0504 +#define RT1015_SPK_VOL 0x0506 #define RT1015_SHORT_DETTOP1 0x0508 #define RT1015_SHORT_DETTOP2 0x050a #define RT1015_SPK_DC_DETECT1 0x0519 diff --git a/sound/soc/codecs/rt5682.c b/sound/soc/codecs/rt5682.c index d3245123101d..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, @@ -2829,12 +2836,13 @@ static int rt5682_probe(struct snd_soc_component *component) return ret; } rt5682->mclk = NULL; - } else { - /* Register CCF DAI clock control */ - ret = rt5682_register_dai_clks(component); - if (ret) - return ret; } + + /* Register CCF DAI clock control */ + ret = rt5682_register_dai_clks(component); + if (ret) + return ret; + /* Initial setup for CCF */ rt5682->lrck[RT5682_AIF1] = CLK_48; #endif diff --git a/sound/soc/fsl/fsl_asrc_common.h b/sound/soc/fsl/fsl_asrc_common.h index 77665b15c8db..7e1c13ca37f1 100644 --- a/sound/soc/fsl/fsl_asrc_common.h +++ b/sound/soc/fsl/fsl_asrc_common.h @@ -32,6 +32,7 @@ enum asrc_pair_index { * @dma_chan: inputer and output DMA channels * @dma_data: private dma data * @pos: hardware pointer position + * @req_dma_chan: flag to release dev_to_dev chan * @private: pair private area */ struct fsl_asrc_pair { @@ -45,6 +46,7 @@ struct fsl_asrc_pair { struct dma_chan *dma_chan[2]; struct imx_dma_data dma_data; unsigned int pos; + bool req_dma_chan; void *private; }; diff --git a/sound/soc/fsl/fsl_asrc_dma.c b/sound/soc/fsl/fsl_asrc_dma.c index d6a3fc5f87e5..5f01a58f422a 100644 --- a/sound/soc/fsl/fsl_asrc_dma.c +++ b/sound/soc/fsl/fsl_asrc_dma.c @@ -135,6 +135,8 @@ static int fsl_asrc_dma_hw_params(struct snd_soc_component *component, struct snd_dmaengine_dai_dma_data *dma_params_be = NULL; struct snd_pcm_runtime *runtime = substream->runtime; struct fsl_asrc_pair *pair = runtime->private_data; + struct dma_chan *tmp_chan = NULL, *be_chan = NULL; + struct snd_soc_component *component_be = NULL; struct fsl_asrc *asrc = pair->asrc; struct dma_slave_config config_fe, config_be; enum asrc_pair_index index = pair->index; @@ -142,7 +144,6 @@ static int fsl_asrc_dma_hw_params(struct snd_soc_component *component, int stream = substream->stream; struct imx_dma_data *tmp_data; struct snd_soc_dpcm *dpcm; - struct dma_chan *tmp_chan; struct device *dev_be; u8 dir = tx ? OUT : IN; dma_cap_mask_t mask; @@ -198,17 +199,29 @@ static int fsl_asrc_dma_hw_params(struct snd_soc_component *component, dma_cap_set(DMA_CYCLIC, mask); /* + * The Back-End device might have already requested a DMA channel, + * so try to reuse it first, and then request a new one upon NULL. + */ + component_be = snd_soc_lookup_component_nolocked(dev_be, SND_DMAENGINE_PCM_DRV_NAME); + if (component_be) { + be_chan = soc_component_to_pcm(component_be)->chan[substream->stream]; + tmp_chan = be_chan; + } + if (!tmp_chan) + tmp_chan = dma_request_slave_channel(dev_be, tx ? "tx" : "rx"); + + /* * An EDMA DEV_TO_DEV channel is fixed and bound with DMA event of each * peripheral, unlike SDMA channel that is allocated dynamically. So no - * need to configure dma_request and dma_request2, but get dma_chan via - * dma_request_slave_channel directly with dma name of Front-End device + * need to configure dma_request and dma_request2, but get dma_chan of + * Back-End device directly via dma_request_slave_channel. */ if (!asrc->use_edma) { /* Get DMA request of Back-End */ - tmp_chan = dma_request_slave_channel(dev_be, tx ? "tx" : "rx"); tmp_data = tmp_chan->private; pair->dma_data.dma_request = tmp_data->dma_request; - dma_release_channel(tmp_chan); + if (!be_chan) + dma_release_channel(tmp_chan); /* Get DMA request of Front-End */ tmp_chan = asrc->get_dma_channel(pair, dir); @@ -220,9 +233,11 @@ static int fsl_asrc_dma_hw_params(struct snd_soc_component *component, pair->dma_chan[dir] = dma_request_channel(mask, filter, &pair->dma_data); + pair->req_dma_chan = true; } else { - pair->dma_chan[dir] = - asrc->get_dma_channel(pair, dir); + pair->dma_chan[dir] = tmp_chan; + /* Do not flag to release if we are reusing the Back-End one */ + pair->req_dma_chan = !be_chan; } if (!pair->dma_chan[dir]) { @@ -261,7 +276,8 @@ static int fsl_asrc_dma_hw_params(struct snd_soc_component *component, ret = dmaengine_slave_config(pair->dma_chan[dir], &config_be); if (ret) { dev_err(dev, "failed to config DMA channel for Back-End\n"); - dma_release_channel(pair->dma_chan[dir]); + if (pair->req_dma_chan) + dma_release_channel(pair->dma_chan[dir]); return ret; } @@ -273,19 +289,22 @@ static int fsl_asrc_dma_hw_params(struct snd_soc_component *component, static int fsl_asrc_dma_hw_free(struct snd_soc_component *component, struct snd_pcm_substream *substream) { + bool tx = substream->stream == SNDRV_PCM_STREAM_PLAYBACK; struct snd_pcm_runtime *runtime = substream->runtime; struct fsl_asrc_pair *pair = runtime->private_data; + u8 dir = tx ? OUT : IN; snd_pcm_set_runtime_buffer(substream, NULL); - if (pair->dma_chan[IN]) - dma_release_channel(pair->dma_chan[IN]); + if (pair->dma_chan[!dir]) + dma_release_channel(pair->dma_chan[!dir]); - if (pair->dma_chan[OUT]) - dma_release_channel(pair->dma_chan[OUT]); + /* release dev_to_dev chan if we aren't reusing the Back-End one */ + if (pair->dma_chan[dir] && pair->req_dma_chan) + dma_release_channel(pair->dma_chan[dir]); - pair->dma_chan[IN] = NULL; - pair->dma_chan[OUT] = NULL; + pair->dma_chan[!dir] = NULL; + pair->dma_chan[dir] = NULL; return 0; } 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/soc/fsl/fsl_ssi.c b/sound/soc/fsl/fsl_ssi.c index bad89b0d129e..1a2fa7f18142 100644 --- a/sound/soc/fsl/fsl_ssi.c +++ b/sound/soc/fsl/fsl_ssi.c @@ -678,8 +678,9 @@ static int fsl_ssi_set_bclk(struct snd_pcm_substream *substream, struct regmap *regs = ssi->regs; u32 pm = 999, div2, psr, stccr, mask, afreq, factor, i; unsigned long clkrate, baudrate, tmprate; - unsigned int slots = params_channels(hw_params); - unsigned int slot_width = 32; + unsigned int channels = params_channels(hw_params); + unsigned int slot_width = params_width(hw_params); + unsigned int slots = 2; u64 sub, savesub = 100000; unsigned int freq; bool baudclk_is_used; @@ -688,10 +689,14 @@ static int fsl_ssi_set_bclk(struct snd_pcm_substream *substream, /* Override slots and slot_width if being specifically set... */ if (ssi->slots) slots = ssi->slots; - /* ...but keep 32 bits if slots is 2 -- I2S Master mode */ - if (ssi->slot_width && slots != 2) + if (ssi->slot_width) slot_width = ssi->slot_width; + /* ...but force 32 bits for stereo audio using I2S Master Mode */ + if (channels == 2 && + (ssi->i2s_net & SSI_SCR_I2S_MODE_MASK) == SSI_SCR_I2S_MODE_MASTER) + slot_width = 32; + /* Generate bit clock based on the slot number and slot width */ freq = slots * slot_width * params_rate(hw_params); diff --git a/sound/soc/intel/boards/Kconfig b/sound/soc/intel/boards/Kconfig index a2a5798c9139..5dc489a79454 100644 --- a/sound/soc/intel/boards/Kconfig +++ b/sound/soc/intel/boards/Kconfig @@ -492,7 +492,7 @@ config SND_SOC_INTEL_SOF_PCM512x_MACH endif ## SND_SOC_SOF_HDA_LINK || SND_SOC_SOF_BAYTRAIL -if (SND_SOC_SOF_COMETLAKE_LP && SND_SOC_SOF_HDA_LINK) +if (SND_SOC_SOF_COMETLAKE && SND_SOC_SOF_HDA_LINK) config SND_SOC_INTEL_CML_LP_DA7219_MAX98357A_MACH tristate "CML_LP with DA7219 and MAX98357A in I2S Mode" @@ -520,7 +520,7 @@ config SND_SOC_INTEL_SOF_CML_RT1011_RT5682_MACH Say Y if you have such a device. If unsure select "N". -endif ## SND_SOC_SOF_COMETLAKE_LP && SND_SOC_SOF_HDA_LINK +endif ## SND_SOC_SOF_COMETLAKE && SND_SOC_SOF_HDA_LINK if SND_SOC_SOF_JASPERLAKE diff --git a/sound/soc/qcom/common.c b/sound/soc/qcom/common.c index 6c20bdd850f3..8ada4ecba847 100644 --- a/sound/soc/qcom/common.c +++ b/sound/soc/qcom/common.c @@ -4,6 +4,7 @@ #include <linux/module.h> #include "common.h" +#include "qdsp6/q6afe.h" int qcom_snd_parse_of(struct snd_soc_card *card) { @@ -101,6 +102,15 @@ int qcom_snd_parse_of(struct snd_soc_card *card) } link->no_pcm = 1; link->ignore_pmdown_time = 1; + + if (q6afe_is_rx_port(link->id)) { + link->dpcm_playback = 1; + link->dpcm_capture = 0; + } else { + link->dpcm_playback = 0; + link->dpcm_capture = 1; + } + } else { dlc = devm_kzalloc(dev, sizeof(*dlc), GFP_KERNEL); if (!dlc) @@ -113,12 +123,12 @@ int qcom_snd_parse_of(struct snd_soc_card *card) link->codecs->dai_name = "snd-soc-dummy-dai"; link->codecs->name = "snd-soc-dummy"; link->dynamic = 1; + link->dpcm_playback = 1; + link->dpcm_capture = 1; } link->ignore_suspend = 1; link->nonatomic = 1; - link->dpcm_playback = 1; - link->dpcm_capture = 1; link->stream_name = link->name; link++; diff --git a/sound/soc/qcom/qdsp6/q6afe.c b/sound/soc/qcom/qdsp6/q6afe.c index e0945f7a58c8..0ce4eb60f984 100644 --- a/sound/soc/qcom/qdsp6/q6afe.c +++ b/sound/soc/qcom/qdsp6/q6afe.c @@ -800,6 +800,14 @@ int q6afe_get_port_id(int index) } EXPORT_SYMBOL_GPL(q6afe_get_port_id); +int q6afe_is_rx_port(int index) +{ + if (index < 0 || index >= AFE_PORT_MAX) + return -EINVAL; + + return port_maps[index].is_rx; +} +EXPORT_SYMBOL_GPL(q6afe_is_rx_port); static int afe_apr_send_pkt(struct q6afe *afe, struct apr_pkt *pkt, struct q6afe_port *port) { diff --git a/sound/soc/qcom/qdsp6/q6afe.h b/sound/soc/qcom/qdsp6/q6afe.h index c7ed5422baff..1a0f80a14afe 100644 --- a/sound/soc/qcom/qdsp6/q6afe.h +++ b/sound/soc/qcom/qdsp6/q6afe.h @@ -198,6 +198,7 @@ int q6afe_port_start(struct q6afe_port *port); int q6afe_port_stop(struct q6afe_port *port); void q6afe_port_put(struct q6afe_port *port); int q6afe_get_port_id(int index); +int q6afe_is_rx_port(int index); void q6afe_hdmi_port_prepare(struct q6afe_port *port, struct q6afe_hdmi_cfg *cfg); void q6afe_slim_port_prepare(struct q6afe_port *port, diff --git a/sound/soc/qcom/qdsp6/q6asm.c b/sound/soc/qcom/qdsp6/q6asm.c index 0e0e8f7a460a..ae4b2cabdf2d 100644 --- a/sound/soc/qcom/qdsp6/q6asm.c +++ b/sound/soc/qcom/qdsp6/q6asm.c @@ -25,6 +25,7 @@ #define ASM_STREAM_CMD_FLUSH 0x00010BCE #define ASM_SESSION_CMD_PAUSE 0x00010BD3 #define ASM_DATA_CMD_EOS 0x00010BDB +#define ASM_DATA_EVENT_RENDERED_EOS 0x00010C1C #define ASM_NULL_POPP_TOPOLOGY 0x00010C68 #define ASM_STREAM_CMD_FLUSH_READBUFS 0x00010C09 #define ASM_STREAM_CMD_SET_ENCDEC_PARAM 0x00010C10 @@ -622,9 +623,6 @@ static int32_t q6asm_stream_callback(struct apr_device *adev, case ASM_SESSION_CMD_SUSPEND: client_event = ASM_CLIENT_EVENT_CMD_SUSPEND_DONE; break; - case ASM_DATA_CMD_EOS: - client_event = ASM_CLIENT_EVENT_CMD_EOS_DONE; - break; case ASM_STREAM_CMD_FLUSH: client_event = ASM_CLIENT_EVENT_CMD_FLUSH_DONE; break; @@ -728,6 +726,9 @@ static int32_t q6asm_stream_callback(struct apr_device *adev, } break; + case ASM_DATA_EVENT_RENDERED_EOS: + client_event = ASM_CLIENT_EVENT_CMD_EOS_DONE; + break; } if (ac->cb) diff --git a/sound/soc/rockchip/rockchip_pdm.c b/sound/soc/rockchip/rockchip_pdm.c index 7cd42fcfcf38..1707414cfa92 100644 --- a/sound/soc/rockchip/rockchip_pdm.c +++ b/sound/soc/rockchip/rockchip_pdm.c @@ -590,8 +590,10 @@ static int rockchip_pdm_resume(struct device *dev) int ret; ret = pm_runtime_get_sync(dev); - if (ret < 0) + if (ret < 0) { + pm_runtime_put(dev); return ret; + } ret = regcache_sync(pdm->regmap); diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c index 7b387202c5db..0f30f5aabaa8 100644 --- a/sound/soc/soc-core.c +++ b/sound/soc/soc-core.c @@ -310,7 +310,7 @@ struct snd_soc_component *snd_soc_rtdcom_lookup(struct snd_soc_pcm_runtime *rtd, } EXPORT_SYMBOL_GPL(snd_soc_rtdcom_lookup); -static struct snd_soc_component +struct snd_soc_component *snd_soc_lookup_component_nolocked(struct device *dev, const char *driver_name) { struct snd_soc_component *component; @@ -329,6 +329,7 @@ static struct snd_soc_component return found_component; } +EXPORT_SYMBOL_GPL(snd_soc_lookup_component_nolocked); struct snd_soc_component *snd_soc_lookup_component(struct device *dev, const char *driver_name) diff --git a/sound/soc/soc-devres.c b/sound/soc/soc-devres.c index a9ea172a66a7..11e5d7962370 100644 --- a/sound/soc/soc-devres.c +++ b/sound/soc/soc-devres.c @@ -9,6 +9,43 @@ #include <sound/soc.h> #include <sound/dmaengine_pcm.h> +static void devm_dai_release(struct device *dev, void *res) +{ + snd_soc_unregister_dai(*(struct snd_soc_dai **)res); +} + +/** + * devm_snd_soc_register_dai - resource-managed dai registration + * @dev: Device used to manage component + * @component: The component the DAIs are registered for + * @dai_drv: DAI driver to use for the DAI + * @legacy_dai_naming: if %true, use legacy single-name format; + * if %false, use multiple-name format; + */ +struct snd_soc_dai *devm_snd_soc_register_dai(struct device *dev, + struct snd_soc_component *component, + struct snd_soc_dai_driver *dai_drv, + bool legacy_dai_naming) +{ + struct snd_soc_dai **ptr; + struct snd_soc_dai *dai; + + ptr = devres_alloc(devm_dai_release, sizeof(*ptr), GFP_KERNEL); + if (!ptr) + return NULL; + + dai = snd_soc_register_dai(component, dai_drv, legacy_dai_naming); + if (dai) { + *ptr = dai; + devres_add(dev, ptr); + } else { + devres_free(ptr); + } + + return dai; +} +EXPORT_SYMBOL_GPL(devm_snd_soc_register_dai); + static void devm_component_release(struct device *dev, void *res) { snd_soc_unregister_component(*(struct device **)res); diff --git a/sound/soc/soc-generic-dmaengine-pcm.c b/sound/soc/soc-generic-dmaengine-pcm.c index f728309a0833..80a4e71f2d95 100644 --- a/sound/soc/soc-generic-dmaengine-pcm.c +++ b/sound/soc/soc-generic-dmaengine-pcm.c @@ -21,18 +21,6 @@ */ #define SND_DMAENGINE_PCM_FLAG_NO_RESIDUE BIT(31) -struct dmaengine_pcm { - struct dma_chan *chan[SNDRV_PCM_STREAM_LAST + 1]; - const struct snd_dmaengine_pcm_config *config; - struct snd_soc_component component; - unsigned int flags; -}; - -static struct dmaengine_pcm *soc_component_to_pcm(struct snd_soc_component *p) -{ - return container_of(p, struct dmaengine_pcm, component); -} - static struct device *dmaengine_dma_dev(struct dmaengine_pcm *pcm, struct snd_pcm_substream *substream) { diff --git a/sound/soc/soc-pcm.c b/sound/soc/soc-pcm.c index 2c114b4542ce..c517064f5391 100644 --- a/sound/soc/soc-pcm.c +++ b/sound/soc/soc-pcm.c @@ -2630,15 +2630,15 @@ static int soc_dpcm_fe_runtime_update(struct snd_soc_pcm_runtime *fe, int new) int count, paths; int ret; + if (!fe->dai_link->dynamic) + return 0; + if (fe->num_cpus > 1) { dev_err(fe->dev, "%s doesn't support Multi CPU yet\n", __func__); return -EINVAL; } - if (!fe->dai_link->dynamic) - return 0; - /* only check active links */ if (!snd_soc_dai_active(asoc_rtd_to_cpu(fe, 0))) return 0; diff --git a/sound/soc/soc-topology.c b/sound/soc/soc-topology.c index 9e89633676b7..43e5745b06aa 100644 --- a/sound/soc/soc-topology.c +++ b/sound/soc/soc-topology.c @@ -1851,7 +1851,7 @@ static int soc_tplg_dai_create(struct soc_tplg *tplg, list_add(&dai_drv->dobj.list, &tplg->comp->dobj_list); /* register the DAI to the component */ - dai = snd_soc_register_dai(tplg->comp, dai_drv, false); + dai = devm_snd_soc_register_dai(tplg->comp->dev, tplg->comp, dai_drv, false); if (!dai) return -ENOMEM; @@ -1859,7 +1859,6 @@ static int soc_tplg_dai_create(struct soc_tplg *tplg, ret = snd_soc_dapm_new_dai_widgets(dapm, dai); if (ret != 0) { dev_err(dai->dev, "Failed to create DAI widgets %d\n", ret); - snd_soc_unregister_dai(dai); return ret; } diff --git a/sound/soc/sof/intel/Kconfig b/sound/soc/sof/intel/Kconfig index c9a2bee4b55c..3aaf25e4f766 100644 --- a/sound/soc/sof/intel/Kconfig +++ b/sound/soc/sof/intel/Kconfig @@ -25,8 +25,7 @@ config SND_SOC_SOF_INTEL_PCI select SND_SOC_SOF_CANNONLAKE if SND_SOC_SOF_CANNONLAKE_SUPPORT select SND_SOC_SOF_COFFEELAKE if SND_SOC_SOF_COFFEELAKE_SUPPORT select SND_SOC_SOF_ICELAKE if SND_SOC_SOF_ICELAKE_SUPPORT - select SND_SOC_SOF_COMETLAKE_LP if SND_SOC_SOF_COMETLAKE_LP_SUPPORT - select SND_SOC_SOF_COMETLAKE_H if SND_SOC_SOF_COMETLAKE_H_SUPPORT + select SND_SOC_SOF_COMETLAKE if SND_SOC_SOF_COMETLAKE_SUPPORT select SND_SOC_SOF_TIGERLAKE if SND_SOC_SOF_TIGERLAKE_SUPPORT select SND_SOC_SOF_ELKHARTLAKE if SND_SOC_SOF_ELKHARTLAKE_SUPPORT select SND_SOC_SOF_JASPERLAKE if SND_SOC_SOF_JASPERLAKE_SUPPORT @@ -201,34 +200,22 @@ config SND_SOC_SOF_ICELAKE This option is not user-selectable but automagically handled by 'select' statements at a higher level -config SND_SOC_SOF_COMETLAKE_LP +config SND_SOC_SOF_COMETLAKE tristate select SND_SOC_SOF_HDA_COMMON help This option is not user-selectable but automagically handled by 'select' statements at a higher level -config SND_SOC_SOF_COMETLAKE_LP_SUPPORT - bool "SOF support for CometLake-LP" - help - This adds support for Sound Open Firmware for Intel(R) platforms - using the Cometlake-LP processors. - Say Y if you have such a device. - If unsure select "N". +config SND_SOC_SOF_COMETLAKE_SUPPORT + bool -config SND_SOC_SOF_COMETLAKE_H - tristate - select SND_SOC_SOF_HDA_COMMON - help - This option is not user-selectable but automagically handled by - 'select' statements at a higher level - -config SND_SOC_SOF_COMETLAKE_H_SUPPORT - bool "SOF support for CometLake-H" +config SND_SOC_SOF_COMETLAKE_LP_SUPPORT + bool "SOF support for CometLake" + select SND_SOC_SOF_COMETLAKE_SUPPORT help This adds support for Sound Open Firmware for Intel(R) platforms - using the Cometlake-H processors. - Say Y if you have such a device. + using the Cometlake processors. If unsure select "N". config SND_SOC_SOF_TIGERLAKE_SUPPORT diff --git a/sound/soc/sof/intel/hda-stream.c b/sound/soc/sof/intel/hda-stream.c index 7f65dcc95811..1bda14c3590c 100644 --- a/sound/soc/sof/intel/hda-stream.c +++ b/sound/soc/sof/intel/hda-stream.c @@ -653,11 +653,16 @@ irqreturn_t hda_dsp_stream_threaded_handler(int irq, void *context) if (status & AZX_INT_CTRL_EN) { rirb_status = snd_hdac_chip_readb(bus, RIRBSTS); if (rirb_status & RIRB_INT_MASK) { + /* + * Clearing the interrupt status here ensures + * that no interrupt gets masked after the RIRB + * wp is read in snd_hdac_bus_update_rirb. + */ + snd_hdac_chip_writeb(bus, RIRBSTS, + RIRB_INT_MASK); active = true; if (rirb_status & RIRB_INT_RESPONSE) snd_hdac_bus_update_rirb(bus); - snd_hdac_chip_writeb(bus, RIRBSTS, - RIRB_INT_MASK); } } #endif diff --git a/sound/soc/sof/sof-pci-dev.c b/sound/soc/sof/sof-pci-dev.c index b13697dab7c0..aa3532ba1434 100644 --- a/sound/soc/sof/sof-pci-dev.c +++ b/sound/soc/sof/sof-pci-dev.c @@ -151,9 +151,7 @@ static const struct sof_dev_desc cfl_desc = { }; #endif -#if IS_ENABLED(CONFIG_SND_SOC_SOF_COMETLAKE_LP) || \ - IS_ENABLED(CONFIG_SND_SOC_SOF_COMETLAKE_H) - +#if IS_ENABLED(CONFIG_SND_SOC_SOF_COMETLAKE) static const struct sof_dev_desc cml_desc = { .machines = snd_soc_acpi_intel_cml_machines, .alt_machines = snd_soc_acpi_intel_cml_sdw_machines, @@ -411,8 +409,11 @@ static const struct pci_device_id sof_pci_ids[] = { .driver_data = (unsigned long)&cfl_desc}, #endif #if IS_ENABLED(CONFIG_SND_SOC_SOF_ICELAKE) - { PCI_DEVICE(0x8086, 0x34C8), + { PCI_DEVICE(0x8086, 0x34C8), /* ICL-LP */ + .driver_data = (unsigned long)&icl_desc}, + { PCI_DEVICE(0x8086, 0x3dc8), /* ICL-H */ .driver_data = (unsigned long)&icl_desc}, + #endif #if IS_ENABLED(CONFIG_SND_SOC_SOF_JASPERLAKE) { PCI_DEVICE(0x8086, 0x38c8), @@ -420,17 +421,20 @@ static const struct pci_device_id sof_pci_ids[] = { { PCI_DEVICE(0x8086, 0x4dc8), .driver_data = (unsigned long)&jsl_desc}, #endif -#if IS_ENABLED(CONFIG_SND_SOC_SOF_COMETLAKE_LP) - { PCI_DEVICE(0x8086, 0x02c8), +#if IS_ENABLED(CONFIG_SND_SOC_SOF_COMETLAKE) + { PCI_DEVICE(0x8086, 0x02c8), /* CML-LP */ .driver_data = (unsigned long)&cml_desc}, -#endif -#if IS_ENABLED(CONFIG_SND_SOC_SOF_COMETLAKE_H) - { PCI_DEVICE(0x8086, 0x06c8), + { PCI_DEVICE(0x8086, 0x06c8), /* CML-H */ + .driver_data = (unsigned long)&cml_desc}, + { PCI_DEVICE(0x8086, 0xa3f0), /* CML-S */ .driver_data = (unsigned long)&cml_desc}, #endif #if IS_ENABLED(CONFIG_SND_SOC_SOF_TIGERLAKE) - { PCI_DEVICE(0x8086, 0xa0c8), + { PCI_DEVICE(0x8086, 0xa0c8), /* TGL-LP */ + .driver_data = (unsigned long)&tgl_desc}, + { PCI_DEVICE(0x8086, 0x43c8), /* TGL-H */ .driver_data = (unsigned long)&tgl_desc}, + #endif #if IS_ENABLED(CONFIG_SND_SOC_SOF_ELKHARTLAKE) { PCI_DEVICE(0x8086, 0x4b55), 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/format.c b/sound/usb/format.c index 5ffb457cc88c..1b28d01d1f4c 100644 --- a/sound/usb/format.c +++ b/sound/usb/format.c @@ -394,8 +394,9 @@ skip_rate: return nr_rates; } -/* Line6 Helix series don't support the UAC2_CS_RANGE usb function - * call. Return a static table of known clock rates. +/* Line6 Helix series and the Rode Rodecaster Pro don't support the + * UAC2_CS_RANGE usb function call. Return a static table of known + * clock rates. */ static int line6_parse_audio_format_rates_quirk(struct snd_usb_audio *chip, struct audioformat *fp) @@ -408,6 +409,7 @@ static int line6_parse_audio_format_rates_quirk(struct snd_usb_audio *chip, case USB_ID(0x0e41, 0x4248): /* Line6 Helix >= fw 2.82 */ case USB_ID(0x0e41, 0x4249): /* Line6 Helix Rack >= fw 2.82 */ case USB_ID(0x0e41, 0x424a): /* Line6 Helix LT >= fw 2.82 */ + case USB_ID(0x19f7, 0x0011): /* Rode Rodecaster Pro */ return set_fixed_rate(fp, 48000, SNDRV_PCM_RATE_48000); } diff --git a/sound/usb/line6/capture.c b/sound/usb/line6/capture.c index 663d608c4287..970c9bdce0b2 100644 --- a/sound/usb/line6/capture.c +++ b/sound/usb/line6/capture.c @@ -286,6 +286,8 @@ int line6_create_audio_in_urbs(struct snd_line6_pcm *line6pcm) urb->interval = LINE6_ISO_INTERVAL; urb->error_count = 0; urb->complete = audio_in_callback; + if (usb_urb_ep_type_check(urb)) + return -EINVAL; } return 0; diff --git a/sound/usb/line6/driver.c b/sound/usb/line6/driver.c index 7629116f570e..2746d9698180 100644 --- a/sound/usb/line6/driver.c +++ b/sound/usb/line6/driver.c @@ -840,7 +840,7 @@ void line6_disconnect(struct usb_interface *interface) if (WARN_ON(usbdev != line6->usbdev)) return; - cancel_delayed_work(&line6->startup_work); + cancel_delayed_work_sync(&line6->startup_work); if (line6->urb_listen != NULL) line6_stop_listen(line6); diff --git a/sound/usb/line6/playback.c b/sound/usb/line6/playback.c index 01930ce7bd75..8233c61e23f1 100644 --- a/sound/usb/line6/playback.c +++ b/sound/usb/line6/playback.c @@ -431,6 +431,8 @@ int line6_create_audio_out_urbs(struct snd_line6_pcm *line6pcm) urb->interval = LINE6_ISO_INTERVAL; urb->error_count = 0; urb->complete = audio_out_callback; + if (usb_urb_ep_type_check(urb)) + return -EINVAL; } return 0; diff --git a/sound/usb/midi.c b/sound/usb/midi.c index 047b90595d65..354f57692938 100644 --- a/sound/usb/midi.c +++ b/sound/usb/midi.c @@ -1499,6 +1499,8 @@ void snd_usbmidi_disconnect(struct list_head *p) spin_unlock_irq(&umidi->disc_lock); up_write(&umidi->disc_rwsem); + del_timer_sync(&umidi->error_timer); + for (i = 0; i < MIDI_MAX_ENDPOINTS; ++i) { struct snd_usb_midi_endpoint *ep = &umidi->endpoints[i]; if (ep->out) @@ -1525,7 +1527,6 @@ void snd_usbmidi_disconnect(struct list_head *p) ep->in = NULL; } } - del_timer_sync(&umidi->error_timer); } EXPORT_SYMBOL(snd_usbmidi_disconnect); @@ -2301,16 +2302,22 @@ void snd_usbmidi_input_stop(struct list_head *p) } EXPORT_SYMBOL(snd_usbmidi_input_stop); -static void snd_usbmidi_input_start_ep(struct snd_usb_midi_in_endpoint *ep) +static void snd_usbmidi_input_start_ep(struct snd_usb_midi *umidi, + struct snd_usb_midi_in_endpoint *ep) { unsigned int i; + unsigned long flags; if (!ep) return; for (i = 0; i < INPUT_URBS; ++i) { struct urb *urb = ep->urbs[i]; - urb->dev = ep->umidi->dev; - snd_usbmidi_submit_urb(urb, GFP_KERNEL); + spin_lock_irqsave(&umidi->disc_lock, flags); + if (!atomic_read(&urb->use_count)) { + urb->dev = ep->umidi->dev; + snd_usbmidi_submit_urb(urb, GFP_ATOMIC); + } + spin_unlock_irqrestore(&umidi->disc_lock, flags); } } @@ -2326,7 +2333,7 @@ void snd_usbmidi_input_start(struct list_head *p) if (umidi->input_running || !umidi->opened[1]) return; for (i = 0; i < MIDI_MAX_ENDPOINTS; ++i) - snd_usbmidi_input_start_ep(umidi->endpoints[i].in); + snd_usbmidi_input_start_ep(umidi, umidi->endpoints[i].in); umidi->input_running = 1; } EXPORT_SYMBOL(snd_usbmidi_input_start); diff --git a/sound/usb/mixer.c b/sound/usb/mixer.c index 15769f266790..eab0fd4fd7c3 100644 --- a/sound/usb/mixer.c +++ b/sound/usb/mixer.c @@ -581,8 +581,9 @@ static int check_matrix_bitmap(unsigned char *bmap, * if failed, give up and free the control instance. */ -int snd_usb_mixer_add_control(struct usb_mixer_elem_list *list, - struct snd_kcontrol *kctl) +int snd_usb_mixer_add_list(struct usb_mixer_elem_list *list, + struct snd_kcontrol *kctl, + bool is_std_info) { struct usb_mixer_interface *mixer = list->mixer; int err; @@ -596,6 +597,7 @@ int snd_usb_mixer_add_control(struct usb_mixer_elem_list *list, return err; } list->kctl = kctl; + list->is_std_info = is_std_info; list->next_id_elem = mixer->id_elems[list->id]; mixer->id_elems[list->id] = list; return 0; @@ -3234,8 +3236,11 @@ void snd_usb_mixer_notify_id(struct usb_mixer_interface *mixer, int unitid) unitid = delegate_notify(mixer, unitid, NULL, NULL); for_each_mixer_elem(list, mixer, unitid) { - struct usb_mixer_elem_info *info = - mixer_elem_list_to_info(list); + struct usb_mixer_elem_info *info; + + if (!list->is_std_info) + continue; + info = mixer_elem_list_to_info(list); /* invalidate cache, so the value is read from the device */ info->cached = 0; snd_ctl_notify(mixer->chip->card, SNDRV_CTL_EVENT_MASK_VALUE, @@ -3315,6 +3320,8 @@ static void snd_usb_mixer_interrupt_v2(struct usb_mixer_interface *mixer, if (!list->kctl) continue; + if (!list->is_std_info) + continue; info = mixer_elem_list_to_info(list); if (count > 1 && info->control != control) diff --git a/sound/usb/mixer.h b/sound/usb/mixer.h index 41ec9dc4139b..c29e27ac43a7 100644 --- a/sound/usb/mixer.h +++ b/sound/usb/mixer.h @@ -66,6 +66,7 @@ struct usb_mixer_elem_list { struct usb_mixer_elem_list *next_id_elem; /* list of controls with same id */ struct snd_kcontrol *kctl; unsigned int id; + bool is_std_info; usb_mixer_elem_dump_func_t dump; usb_mixer_elem_resume_func_t resume; }; @@ -103,8 +104,12 @@ void snd_usb_mixer_notify_id(struct usb_mixer_interface *mixer, int unitid); int snd_usb_mixer_set_ctl_value(struct usb_mixer_elem_info *cval, int request, int validx, int value_set); -int snd_usb_mixer_add_control(struct usb_mixer_elem_list *list, - struct snd_kcontrol *kctl); +int snd_usb_mixer_add_list(struct usb_mixer_elem_list *list, + struct snd_kcontrol *kctl, + bool is_std_info); + +#define snd_usb_mixer_add_control(list, kctl) \ + snd_usb_mixer_add_list(list, kctl, true) void snd_usb_mixer_elem_init_std(struct usb_mixer_elem_list *list, struct usb_mixer_interface *mixer, diff --git a/sound/usb/mixer_quirks.c b/sound/usb/mixer_quirks.c index b6bcf2f92383..cec1cfd7edb7 100644 --- a/sound/usb/mixer_quirks.c +++ b/sound/usb/mixer_quirks.c @@ -158,7 +158,8 @@ static int add_single_ctl_with_resume(struct usb_mixer_interface *mixer, return -ENOMEM; } kctl->private_free = snd_usb_mixer_elem_free; - return snd_usb_mixer_add_control(list, kctl); + /* don't use snd_usb_mixer_add_control() here, this is a special list element */ + return snd_usb_mixer_add_list(list, kctl, false); } /* diff --git a/sound/usb/pcm.c b/sound/usb/pcm.c index 8a05dcb1344f..40b7cd13fed9 100644 --- a/sound/usb/pcm.c +++ b/sound/usb/pcm.c @@ -367,6 +367,8 @@ static int set_sync_ep_implicit_fb_quirk(struct snd_usb_substream *subs, ifnum = 0; 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; @@ -1786,6 +1788,7 @@ static int snd_usb_substream_capture_trigger(struct snd_pcm_substream *substream return 0; case SNDRV_PCM_TRIGGER_STOP: stop_endpoints(subs); + subs->data_endpoint->retire_data_urb = NULL; subs->running = 0; return 0; case SNDRV_PCM_TRIGGER_PAUSE_PUSH: 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 diff --git a/sound/usb/quirks.c b/sound/usb/quirks.c index bca0179a0ef8..fca72730a802 100644 --- a/sound/usb/quirks.c +++ b/sound/usb/quirks.c @@ -1532,6 +1532,7 @@ bool snd_usb_get_sample_rate_quirk(struct snd_usb_audio *chip) 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 */ @@ -1673,6 +1674,14 @@ void snd_usb_ctl_msg_quirk(struct usb_device *dev, unsigned int pipe, chip->usb_id == USB_ID(0x0951, 0x16ad)) && (requesttype & USB_TYPE_MASK) == USB_TYPE_CLASS) 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) + usleep_range(5000, 6000); } /* @@ -1856,6 +1865,7 @@ struct registration_quirk { static const struct registration_quirk registration_quirks[] = { REG_QUIRK_ENTRY(0x0951, 0x16d8, 2), /* Kingston HyperX AMP */ REG_QUIRK_ENTRY(0x0951, 0x16ed, 2), /* Kingston HyperX Cloud Alpha S */ + REG_QUIRK_ENTRY(0x0951, 0x16ea, 2), /* Kingston HyperX Cloud Flight S */ { 0 } /* terminator */ }; |