From f0541edb2e7333f320642c7b491a67912c1f65db Mon Sep 17 00:00:00 2001 From: songxiebing Date: Sun, 5 Apr 2026 09:26:51 +0800 Subject: [PATCH 01/16] ALSA: hda/realtek: Add quirk for Lenovo Yoga Pro 7 14IAH10 The bass speakers are not working, and add the following entry in /etc/modprobe.d/snd.conf: options snd-sof-intel-hda-generic hda_model=alc287-yoga9-bass-spk-pin Fixes the bass speakers. So add the quick ALC287_FIXUP_YOGA9_14IAP7_BASS_SPK_PIN here. Reported-by: Fernando Garcia Corona Closes: https://bugzilla.kernel.org/show_bug.cgi?id=221317 Signed-off-by: songxiebing Link: https://patch.msgid.link/20260405012651.133838-1-songxiebing@kylinos.cn Signed-off-by: Takashi Iwai --- sound/hda/codecs/realtek/alc269.c | 1 + 1 file changed, 1 insertion(+) diff --git a/sound/hda/codecs/realtek/alc269.c b/sound/hda/codecs/realtek/alc269.c index 6db23ce8a5fe..45f9d6487388 100644 --- a/sound/hda/codecs/realtek/alc269.c +++ b/sound/hda/codecs/realtek/alc269.c @@ -7680,6 +7680,7 @@ static const struct hda_quirk alc269_fixup_tbl[] = { SND_PCI_QUIRK(0x17aa, 0x38fd, "ThinkBook plus Gen5 Hybrid", ALC287_FIXUP_TAS2781_I2C), SND_PCI_QUIRK(0x17aa, 0x3902, "Lenovo E50-80", ALC269_FIXUP_DMIC_THINKPAD_ACPI), SND_PCI_QUIRK(0x17aa, 0x390d, "Lenovo Yoga Pro 7 14ASP10", ALC287_FIXUP_YOGA9_14IAP7_BASS_SPK_PIN), + SND_PCI_QUIRK(0x17aa, 0x3911, "Lenovo Yoga Pro 7 14IAH10", ALC287_FIXUP_YOGA9_14IAP7_BASS_SPK_PIN), SND_PCI_QUIRK(0x17aa, 0x3913, "Lenovo 145", ALC236_FIXUP_LENOVO_INV_DMIC), SND_PCI_QUIRK(0x17aa, 0x391a, "Lenovo Yoga Slim 7 14AKP10", ALC287_FIXUP_YOGA9_14IAP7_BASS_SPK_PIN), SND_PCI_QUIRK(0x17aa, 0x391f, "Yoga S990-16 pro Quad YC Quad", ALC287_FIXUP_TXNW2781_I2C), From 5075d08e72af38b829fb71800c2a5be61d0b2e2c Mon Sep 17 00:00:00 2001 From: Marek Vasut Date: Mon, 6 Apr 2026 01:44:35 +0200 Subject: [PATCH 02/16] ASoC: dt-bindings: ti,tas2552: Add sound-dai-cells Add missing sound-sai-cells for this codec into schema. At the same time, drop trailing spaces from description. Fixes: 506e0825a4c9 ("ASoC: dt-bindings: Convert ti,tas2552 to DT schema") Signed-off-by: Marek Vasut Reviewed-by: Krzysztof Kozlowski Link: https://patch.msgid.link/20260405234502.154227-1-marex@nabladev.com Signed-off-by: Mark Brown --- .../devicetree/bindings/sound/ti,tas2552.yaml | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/Documentation/devicetree/bindings/sound/ti,tas2552.yaml b/Documentation/devicetree/bindings/sound/ti,tas2552.yaml index 10369aa5f0a8..85e3ebd2acd8 100644 --- a/Documentation/devicetree/bindings/sound/ti,tas2552.yaml +++ b/Documentation/devicetree/bindings/sound/ti,tas2552.yaml @@ -12,8 +12,8 @@ maintainers: - Baojun Xu description: > - The TAS2552 can receive its reference clock via MCLK, BCLK, IVCLKIN pin or - use the internal 1.8MHz. This CLKIN is used by the PLL. In addition to PLL, + The TAS2552 can receive its reference clock via MCLK, BCLK, IVCLKIN pin or + use the internal 1.8MHz. This CLKIN is used by the PLL. In addition to PLL, the PDM reference clock is also selectable: PLL, IVCLKIN, BCLK or MCLK. For system integration the dt-bindings/sound/tas2552.h header file provides @@ -34,6 +34,9 @@ properties: maxItems: 1 description: gpio pin to enable/disable the device + '#sound-dai-cells': + const: 0 + required: - compatible - reg @@ -41,7 +44,10 @@ required: - iovdd-supply - avdd-supply -additionalProperties: false +allOf: + - $ref: dai-common.yaml# + +unevaluatedProperties: false examples: - | @@ -54,6 +60,7 @@ examples: audio-codec@41 { compatible = "ti,tas2552"; reg = <0x41>; + #sound-dai-cells = <0>; vbat-supply = <®_vbat>; iovdd-supply = <®_iovdd>; avdd-supply = <®_avdd>; From 80a7916ca2d902b329a40e529c4c4131ae6ff273 Mon Sep 17 00:00:00 2001 From: Mark Pearson Date: Thu, 2 Apr 2026 21:03:25 -0400 Subject: [PATCH 03/16] ASoC: amd: acp: add Lenovo P16s G5 AMD quirk for legacy SDW machine Add a DMI quirk entry for Lenovo P16s G5 AMD to use ASOC_SDW_ACP_DMIC. Needed to allow the microphone to work on this platform Signed-off-by: Mark Pearson Reviewed-by: Vijendar Mukunda Link: https://patch.msgid.link/20260403010336.1223078-1-mpearson-lenovo@squebb.ca Signed-off-by: Mark Brown --- sound/soc/amd/acp/acp-sdw-legacy-mach.c | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/sound/soc/amd/acp/acp-sdw-legacy-mach.c b/sound/soc/amd/acp/acp-sdw-legacy-mach.c index 6388cd7cb28e..92749dc17df8 100644 --- a/sound/soc/amd/acp/acp-sdw-legacy-mach.c +++ b/sound/soc/amd/acp/acp-sdw-legacy-mach.c @@ -111,6 +111,22 @@ static const struct dmi_system_id soc_sdw_quirk_table[] = { }, .driver_data = (void *)(ASOC_SDW_CODEC_SPKR), }, + { + .callback = soc_sdw_quirk_cb, + .matches = { /* Lenovo P16s G5 AMD */ + DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), + DMI_MATCH(DMI_PRODUCT_SKU, "21XG"), + }, + .driver_data = (void *)(ASOC_SDW_ACP_DMIC), + }, + { + .callback = soc_sdw_quirk_cb, + .matches = { /* Lenovo P16s G5 AMD */ + DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), + DMI_MATCH(DMI_PRODUCT_SKU, "21XH"), + }, + .driver_data = (void *)(ASOC_SDW_ACP_DMIC), + }, { .callback = soc_sdw_quirk_cb, .matches = { From 4e53116437e919c4b9a9d95fb73ae14fe0cfc8f9 Mon Sep 17 00:00:00 2001 From: Charles Keepax Date: Mon, 16 Mar 2026 14:14:49 +0000 Subject: [PATCH 04/16] ASoC: SDCA: Fix errors in IRQ cleanup IRQs are enabled through sdca_irq_populate() from component probe using devm_request_threaded_irq(), this however means the IRQs can persist if the sound card is torn down. Some of the IRQ handlers store references to the card and the kcontrols which can then fail. Some detail of the crash was explained in [1]. Generally it is not advised to use devm outside of bus probe, so the code is updated to not use devm. The IRQ requests are not moved to bus probe time as it makes passing the snd_soc_component into the IRQs very awkward and would the require a second step once the component is available, so it is simpler to just register the IRQs at this point, even though that necessitates some manual cleanup. Link: https://lore.kernel.org/linux-sound/20260310183829.2907805-1-gaggery.tsai@intel.com/ [1] Fixes: b126394d9ec6 ("ASoC: SDCA: Generic interrupt support") Reported-by: Gaggery Tsai Signed-off-by: Charles Keepax Link: https://patch.msgid.link/20260316141449.2950215-1-ckeepax@opensource.cirrus.com Signed-off-by: Mark Brown --- include/sound/sdca_interrupts.h | 5 ++ sound/soc/sdca/sdca_class_function.c | 9 ++++ sound/soc/sdca/sdca_interrupts.c | 77 ++++++++++++++++++++++++++-- 3 files changed, 87 insertions(+), 4 deletions(-) diff --git a/include/sound/sdca_interrupts.h b/include/sound/sdca_interrupts.h index 9bcb5d8fd592..b47003c3d26e 100644 --- a/include/sound/sdca_interrupts.h +++ b/include/sound/sdca_interrupts.h @@ -69,6 +69,8 @@ struct sdca_interrupt_info { int sdca_irq_request(struct device *dev, struct sdca_interrupt_info *interrupt_info, int sdca_irq, const char *name, irq_handler_t handler, void *data); +void sdca_irq_free(struct device *dev, struct sdca_interrupt_info *interrupt_info, + int sdca_irq, const char *name, void *data); int sdca_irq_data_populate(struct device *dev, struct regmap *function_regmap, struct snd_soc_component *component, struct sdca_function_data *function, @@ -81,6 +83,9 @@ int sdca_irq_populate_early(struct device *dev, struct regmap *function_regmap, int sdca_irq_populate(struct sdca_function_data *function, struct snd_soc_component *component, struct sdca_interrupt_info *info); +void sdca_irq_cleanup(struct sdca_function_data *function, + struct snd_soc_component *component, + struct sdca_interrupt_info *info); struct sdca_interrupt_info *sdca_irq_allocate(struct device *dev, struct regmap *regmap, int irq); diff --git a/sound/soc/sdca/sdca_class_function.c b/sound/soc/sdca/sdca_class_function.c index 98fd3fd1052b..fe404d769c78 100644 --- a/sound/soc/sdca/sdca_class_function.c +++ b/sound/soc/sdca/sdca_class_function.c @@ -198,6 +198,14 @@ static int class_function_component_probe(struct snd_soc_component *component) return sdca_irq_populate(drv->function, component, core->irq_info); } +static void class_function_component_remove(struct snd_soc_component *component) +{ + struct class_function_drv *drv = snd_soc_component_get_drvdata(component); + struct sdca_class_drv *core = drv->core; + + sdca_irq_cleanup(drv->function, component, core->irq_info); +} + static int class_function_set_jack(struct snd_soc_component *component, struct snd_soc_jack *jack, void *d) { @@ -209,6 +217,7 @@ static int class_function_set_jack(struct snd_soc_component *component, static const struct snd_soc_component_driver class_function_component_drv = { .probe = class_function_component_probe, + .remove = class_function_component_remove, .endianness = 1, }; diff --git a/sound/soc/sdca/sdca_interrupts.c b/sound/soc/sdca/sdca_interrupts.c index 95b1ab4ba1b0..1838dabcdf60 100644 --- a/sound/soc/sdca/sdca_interrupts.c +++ b/sound/soc/sdca/sdca_interrupts.c @@ -252,8 +252,7 @@ static int sdca_irq_request_locked(struct device *dev, if (irq < 0) return irq; - ret = devm_request_threaded_irq(dev, irq, NULL, handler, - IRQF_ONESHOT, name, data); + ret = request_threaded_irq(irq, NULL, handler, IRQF_ONESHOT, name, data); if (ret) return ret; @@ -264,6 +263,22 @@ static int sdca_irq_request_locked(struct device *dev, return 0; } +static void sdca_irq_free_locked(struct device *dev, struct sdca_interrupt_info *info, + int sdca_irq, const char *name, void *data) +{ + int irq; + + irq = regmap_irq_get_virq(info->irq_data, sdca_irq); + if (irq < 0) + return; + + free_irq(irq, data); + + info->irqs[sdca_irq].irq = 0; + + dev_dbg(dev, "freed irq %d for %s\n", irq, name); +} + /** * sdca_irq_request - request an individual SDCA interrupt * @dev: Pointer to the struct device against which things should be allocated. @@ -302,6 +317,30 @@ int sdca_irq_request(struct device *dev, struct sdca_interrupt_info *info, } EXPORT_SYMBOL_NS_GPL(sdca_irq_request, "SND_SOC_SDCA"); +/** + * sdca_irq_free - free an individual SDCA interrupt + * @dev: Pointer to the struct device. + * @info: Pointer to the interrupt information structure. + * @sdca_irq: SDCA interrupt position. + * @name: Name to be given to the IRQ. + * @data: Private data pointer that will be passed to the handler. + * + * Typically this is handled internally by sdca_irq_cleanup, however if + * a device requires custom IRQ handling this can be called manually before + * calling sdca_irq_cleanup, which will then skip that IRQ whilst processing. + */ +void sdca_irq_free(struct device *dev, struct sdca_interrupt_info *info, + int sdca_irq, const char *name, void *data) +{ + if (sdca_irq < 0 || sdca_irq >= SDCA_MAX_INTERRUPTS) + return; + + guard(mutex)(&info->irq_lock); + + sdca_irq_free_locked(dev, info, sdca_irq, name, data); +} +EXPORT_SYMBOL_NS_GPL(sdca_irq_free, "SND_SOC_SDCA"); + /** * sdca_irq_data_populate - Populate common interrupt data * @dev: Pointer to the Function device. @@ -328,8 +367,8 @@ int sdca_irq_data_populate(struct device *dev, struct regmap *regmap, if (!dev) return -ENODEV; - name = devm_kasprintf(dev, GFP_KERNEL, "%s %s %s", function->desc->name, - entity->label, control->label); + name = kasprintf(GFP_KERNEL, "%s %s %s", function->desc->name, + entity->label, control->label); if (!name) return -ENOMEM; @@ -516,6 +555,36 @@ int sdca_irq_populate(struct sdca_function_data *function, } EXPORT_SYMBOL_NS_GPL(sdca_irq_populate, "SND_SOC_SDCA"); +/** + * sdca_irq_cleanup - Free all the individual IRQs for an SDCA Function + * @function: Pointer to the SDCA Function. + * @component: Pointer to the ASoC component for the Function. + * @info: Pointer to the SDCA interrupt info for this device. + * + * Typically this would be called from the driver for a single SDCA Function. + */ +void sdca_irq_cleanup(struct sdca_function_data *function, + struct snd_soc_component *component, + struct sdca_interrupt_info *info) +{ + struct device *dev = component->dev; + int i; + + guard(mutex)(&info->irq_lock); + + for (i = 0; i < SDCA_MAX_INTERRUPTS; i++) { + struct sdca_interrupt *interrupt = &info->irqs[i]; + + if (interrupt->function != function || !interrupt->irq) + continue; + + sdca_irq_free_locked(dev, info, i, interrupt->name, interrupt); + + kfree(interrupt->name); + } +} +EXPORT_SYMBOL_NS_GPL(sdca_irq_cleanup, "SND_SOC_SDCA"); + /** * sdca_irq_allocate - allocate an SDCA interrupt structure for a device * @sdev: Device pointer against which things should be allocated. From 86facd80a2a37536937f06de637abf9e8cabdb4b Mon Sep 17 00:00:00 2001 From: Maciej Strozek Date: Thu, 2 Apr 2026 14:45:30 +0800 Subject: [PATCH 05/16] ASoC: SOF: Intel: Fix endpoint index if endpoints are missing In case of missing endpoints, the sequential numbering will cause wrong mapping. Instead, assign the original DAI index from codec_info_list. Fixes: 5226d19d4cae ("ASoC: SOF: Intel: use sof_sdw as default SDW machine driver") Signed-off-by: Maciej Strozek Signed-off-by: Bard Liao Link: https://patch.msgid.link/20260402064531.2287261-2-yung-chuan.liao@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/intel/hda.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/sof/intel/hda.c b/sound/soc/sof/intel/hda.c index c0cc7d3ce526..57632b464117 100644 --- a/sound/soc/sof/intel/hda.c +++ b/sound/soc/sof/intel/hda.c @@ -1203,7 +1203,7 @@ static struct snd_soc_acpi_adr_device *find_acpi_adr_device(struct device *dev, codec_info_list[i].dais[j].dai_type)) continue; - endpoints[ep_index].num = ep_index; + endpoints[ep_index].num = j; if (codec_info_list[i].dais[j].dai_type == SOC_SDW_DAI_TYPE_AMP) { /* Assume all amp are aggregated */ endpoints[ep_index].aggregated = 1; From 1de6ddcddc954a69f96b1c23205e03ddd603e3c8 Mon Sep 17 00:00:00 2001 From: Maciej Strozek Date: Thu, 2 Apr 2026 14:45:31 +0800 Subject: [PATCH 06/16] ASoC: SOF: Intel: fix iteration in is_endpoint_present() is_endpoint_present() iterates over sdca_data.num_functions, but checks the dai_type according to codec info list, which will cause problems if not all endpoints from the codec info list are present. Make sure the type of actually present functions is compared against target dai_type. Fixes: 5226d19d4cae ("ASoC: SOF: Intel: use sof_sdw as default SDW machine driver") Signed-off-by: Maciej Strozek Signed-off-by: Bard Liao Link: https://patch.msgid.link/20260402064531.2287261-3-yung-chuan.liao@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/intel/hda.c | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/sound/soc/sof/intel/hda.c b/sound/soc/sof/intel/hda.c index 57632b464117..8a240dcb7fcb 100644 --- a/sound/soc/sof/intel/hda.c +++ b/sound/soc/sof/intel/hda.c @@ -1133,8 +1133,7 @@ static void hda_generic_machine_select(struct snd_sof_dev *sdev, #if IS_ENABLED(CONFIG_SND_SOC_SOF_INTEL_SOUNDWIRE) -static bool is_endpoint_present(struct sdw_slave *sdw_device, - struct asoc_sdw_codec_info *dai_info, int dai_type) +static bool is_endpoint_present(struct sdw_slave *sdw_device, int dai_type) { int i; @@ -1145,7 +1144,7 @@ static bool is_endpoint_present(struct sdw_slave *sdw_device, } for (i = 0; i < sdw_device->sdca_data.num_functions; i++) { - if (dai_type == dai_info->dais[i].dai_type) + if (dai_type == asoc_sdw_get_dai_type(sdw_device->sdca_data.function[i].type)) return true; } dev_dbg(&sdw_device->dev, "Endpoint DAI type %d not found\n", dai_type); @@ -1199,8 +1198,7 @@ static struct snd_soc_acpi_adr_device *find_acpi_adr_device(struct device *dev, } for (j = 0; j < codec_info_list[i].dai_num; j++) { /* Check if the endpoint is present by the SDCA DisCo table */ - if (!is_endpoint_present(sdw_device, &codec_info_list[i], - codec_info_list[i].dais[j].dai_type)) + if (!is_endpoint_present(sdw_device, codec_info_list[i].dais[j].dai_type)) continue; endpoints[ep_index].num = j; From c5408d818316061d6063c11a4f47f1ba25a3a708 Mon Sep 17 00:00:00 2001 From: Cezary Rojewski Date: Tue, 7 Apr 2026 10:54:58 +0200 Subject: [PATCH 07/16] ASoC: Intel: avs: Fix memory leak in avs_register_i2s_test_boards() Caller is responsible for freeing array allocated with parse_int_array(). Found out by Coverity. Fixes: 7d859189de13 ("ASoC: Intel: avs: Allow to specify custom configurations with i2s_test") Signed-off-by: Cezary Rojewski Link: https://patch.msgid.link/20260407085459.400628-1-cezary.rojewski@intel.com Signed-off-by: Mark Brown --- sound/soc/intel/avs/board_selection.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/sound/soc/intel/avs/board_selection.c b/sound/soc/intel/avs/board_selection.c index 8a46285181fa..dd0e7cd5a7dd 100644 --- a/sound/soc/intel/avs/board_selection.c +++ b/sound/soc/intel/avs/board_selection.c @@ -520,7 +520,8 @@ static int avs_register_i2s_test_boards(struct avs_dev *adev) if (num_elems > max_ssps) { dev_err(adev->dev, "board supports only %d SSP, %d specified\n", max_ssps, num_elems); - return -EINVAL; + ret = -EINVAL; + goto exit; } for (ssp_port = 0; ssp_port < num_elems; ssp_port++) { @@ -528,11 +529,13 @@ static int avs_register_i2s_test_boards(struct avs_dev *adev) for_each_set_bit(tdm_slot, &tdm_slots, 16) { ret = avs_register_i2s_test_board(adev, ssp_port, tdm_slot); if (ret) - return ret; + goto exit; } } - return 0; +exit: + kfree(array); + return ret; } static int avs_register_i2s_board(struct avs_dev *adev, struct snd_soc_acpi_mach *mach) From 8508e9118649f13f7b857e9e10147b241db615d7 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Tue, 7 Apr 2026 14:33:17 +0200 Subject: [PATCH 08/16] Revert "ALSA: hda/realtek: Add quirk for Gigabyte Technology to fix headphone" This reverts commit 56fbbe096a89ff4b52af78a21a4afd9d94bdcc80. It caused regressions on other Gigabyte models, and looking at the bugzilla entry again, the suggested change appears rather dubious, as incorrectly setting the front mic pin as the headphone. Fixes: 56fbbe096a89 ("ALSA: hda/realtek: Add quirk for Gigabyte Technology to fix headphone") Cc: Reported-by: Marcin Krycki Reported-by: Theodoros Orfanidis Closes: https://lore.kernel.org/CAEfRphPU_ABuVFzaHhspxgp2WAqi7kKNGo4yOOt0zeVFPSj8+Q@mail.gmail.com Link: https://patch.msgid.link/20260407123333.171130-1-tiwai@suse.de Signed-off-by: Takashi Iwai --- sound/hda/codecs/realtek/alc662.c | 9 --------- 1 file changed, 9 deletions(-) diff --git a/sound/hda/codecs/realtek/alc662.c b/sound/hda/codecs/realtek/alc662.c index 3a943adf9087..5073165d1f3c 100644 --- a/sound/hda/codecs/realtek/alc662.c +++ b/sound/hda/codecs/realtek/alc662.c @@ -313,7 +313,6 @@ enum { ALC897_FIXUP_HEADSET_MIC_PIN2, ALC897_FIXUP_UNIS_H3C_X500S, ALC897_FIXUP_HEADSET_MIC_PIN3, - ALC897_FIXUP_H610M_HP_PIN, }; static const struct hda_fixup alc662_fixups[] = { @@ -767,13 +766,6 @@ static const struct hda_fixup alc662_fixups[] = { { } }, }, - [ALC897_FIXUP_H610M_HP_PIN] = { - .type = HDA_FIXUP_PINS, - .v.pins = (const struct hda_pintbl[]) { - { 0x19, 0x0321403f }, /* HP out */ - { } - }, - }, }; static const struct hda_quirk alc662_fixup_tbl[] = { @@ -823,7 +815,6 @@ static const struct hda_quirk alc662_fixup_tbl[] = { SND_PCI_QUIRK(0x1043, 0x8469, "ASUS mobo", ALC662_FIXUP_NO_JACK_DETECT), SND_PCI_QUIRK(0x105b, 0x0cd6, "Foxconn", ALC662_FIXUP_ASUS_MODE2), SND_PCI_QUIRK(0x144d, 0xc051, "Samsung R720", ALC662_FIXUP_IDEAPAD), - SND_PCI_QUIRK(0x1458, 0xa194, "H610M H V2 DDR4", ALC897_FIXUP_H610M_HP_PIN), SND_PCI_QUIRK(0x14cd, 0x5003, "USI", ALC662_FIXUP_USI_HEADSET_MODE), SND_PCI_QUIRK(0x17aa, 0x1036, "Lenovo P520", ALC662_FIXUP_LENOVO_MULTI_CODECS), SND_PCI_QUIRK(0x17aa, 0x1057, "Lenovo P360", ALC897_FIXUP_HEADSET_MIC_PIN), From f4c90fb761f696ebbcf1e8fb7f83d83cbb30cb0c Mon Sep 17 00:00:00 2001 From: Neo Chang Date: Wed, 8 Apr 2026 13:26:39 +0800 Subject: [PATCH 09/16] ASoC: nau8325: Add software reset during probe Currently, the driver only performs a hardware reset during the I2C probe sequence. To ensure all internal states of the codec are properly cleared without affecting the configuration registers, a software reset is also required. According to the hardware specification, writing to the Software Reset register (R01) twice will reset all internal states safely. This patch adds the nau8325_software_reset() function, executes it right after the hardware reset in the probe function, and marks the R01 register as writeable in the regmap configuration. Signed-off-by: Neo Chang Reviewed-by: Cezary Rojewski Link: https://patch.msgid.link/20260408052639.187149-1-YLCHANG2@nuvoton.com Signed-off-by: Mark Brown --- sound/soc/codecs/nau8325.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/sound/soc/codecs/nau8325.c b/sound/soc/codecs/nau8325.c index e651263a9812..58ef5c493835 100644 --- a/sound/soc/codecs/nau8325.c +++ b/sound/soc/codecs/nau8325.c @@ -142,7 +142,7 @@ static bool nau8325_readable_reg(struct device *dev, unsigned int reg) static bool nau8325_writeable_reg(struct device *dev, unsigned int reg) { switch (reg) { - case NAU8325_R00_HARDWARE_RST: + case NAU8325_R00_HARDWARE_RST ... NAU8325_R01_SOFTWARE_RST: case NAU8325_R03_CLK_CTRL ... NAU8325_R06_INT_CLR_STATUS: case NAU8325_R09_IRQOUT ... NAU8325_R13_DAC_VOLUME: case NAU8325_R29_DAC_CTRL1 ... NAU8325_R2A_DAC_CTRL2: @@ -670,6 +670,12 @@ static void nau8325_reset_chip(struct regmap *regmap) regmap_write(regmap, NAU8325_R00_HARDWARE_RST, 0x0000); } +static void nau8325_software_reset(struct regmap *regmap) +{ + regmap_write(regmap, NAU8325_R01_SOFTWARE_RST, 0x0000); + regmap_write(regmap, NAU8325_R01_SOFTWARE_RST, 0x0000); +} + static void nau8325_init_regs(struct nau8325 *nau8325) { struct regmap *regmap = nau8325->regmap; @@ -856,6 +862,7 @@ static int nau8325_i2c_probe(struct i2c_client *i2c) nau8325_print_device_properties(nau8325); nau8325_reset_chip(nau8325->regmap); + nau8325_software_reset(nau8325->regmap); ret = regmap_read(nau8325->regmap, NAU8325_R02_DEVICE_ID, &value); if (ret) { dev_dbg(dev, "Failed to read device id (%d)", ret); From 082c192c0dd03f685514c9ce2eb0a80fd28e2175 Mon Sep 17 00:00:00 2001 From: Kai Vehmanen Date: Wed, 8 Apr 2026 11:45:13 +0300 Subject: [PATCH 10/16] ALSA: hda/intel: enforce stricter period-size alignment for Intel NVL MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Intel ACE4 based products set more strict constraints on HDA BDLE start address and length alignment. Modify capability flags to drop AZX_DCAPS_NO_ALIGN_BUFSIZE for Intel Nova Lake platforms. Fixes: 7f428282fde3 ("ALSA: hda: controllers: intel: add support for Nova Lake") Signed-off-by: Kai Vehmanen Reviewed-by: Péter Ujfalusi Reviewed-by: Liam Girdwood Cc: Link: https://patch.msgid.link/20260408084514.24325-2-peter.ujfalusi@linux.intel.com Signed-off-by: Takashi Iwai --- sound/hda/controllers/intel.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/sound/hda/controllers/intel.c b/sound/hda/controllers/intel.c index 8a7bd49e411f..a4104376523a 100644 --- a/sound/hda/controllers/intel.c +++ b/sound/hda/controllers/intel.c @@ -295,6 +295,9 @@ enum { #define AZX_DCAPS_INTEL_LNL \ (AZX_DCAPS_INTEL_SKYLAKE | AZX_DCAPS_PIO_COMMANDS) +#define AZX_DCAPS_INTEL_NVL \ + (AZX_DCAPS_INTEL_LNL & ~AZX_DCAPS_NO_ALIGN_BUFSIZE) + /* quirks for ATI SB / AMD Hudson */ #define AZX_DCAPS_PRESET_ATI_SB \ (AZX_DCAPS_NO_TCSEL | AZX_DCAPS_POSFIX_LPIB |\ @@ -2565,8 +2568,8 @@ static const struct pci_device_id azx_ids[] = { /* Wildcat Lake */ { PCI_DEVICE_DATA(INTEL, HDA_WCL, AZX_DRIVER_SKL | AZX_DCAPS_INTEL_LNL) }, /* Nova Lake */ - { PCI_DEVICE_DATA(INTEL, HDA_NVL, AZX_DRIVER_SKL | AZX_DCAPS_INTEL_LNL) }, - { PCI_DEVICE_DATA(INTEL, HDA_NVL_S, AZX_DRIVER_SKL | AZX_DCAPS_INTEL_LNL) }, + { PCI_DEVICE_DATA(INTEL, HDA_NVL, AZX_DRIVER_SKL | AZX_DCAPS_INTEL_NVL) }, + { PCI_DEVICE_DATA(INTEL, HDA_NVL_S, AZX_DRIVER_SKL | AZX_DCAPS_INTEL_NVL) }, /* Apollolake (Broxton-P) */ { PCI_DEVICE_DATA(INTEL, HDA_APL, AZX_DRIVER_SKL | AZX_DCAPS_INTEL_BROXTON) }, /* Gemini-Lake */ From 0f71866057262d669ed6a21246eaac0ad6d04d4e Mon Sep 17 00:00:00 2001 From: Kai Vehmanen Date: Wed, 8 Apr 2026 11:45:14 +0300 Subject: [PATCH 11/16] ASoC: SOF: Intel: hda: modify period size constraints for ACE4 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Intel ACE4 based products set more strict constraints on HDA BDLE start address and length alignment. Add a constraint to align period size to 128 bytes. The commit removes the "minimum as per HDA spec" comment. This comment was misleading as spec actually does allow a 2 byte BDLE length, and more importantly, period size also directly impacts how the BDLE start addresses are aligned, so it is not sufficient just to consider allowed buffer length. Fixes: d3df422f66e8 ("ASoC: SOF: Intel: add initial support for NVL-S") Cc: stable@vger.kernel.org Reported-by: Peter Ujfalusi Signed-off-by: Kai Vehmanen Reviewed-by: Péter Ujfalusi Reviewed-by: Liam Girdwood Link: https://patch.msgid.link/20260408084514.24325-3-peter.ujfalusi@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/intel/hda-pcm.c | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/sound/soc/sof/intel/hda-pcm.c b/sound/soc/sof/intel/hda-pcm.c index da6c1e7263cd..16a364072821 100644 --- a/sound/soc/sof/intel/hda-pcm.c +++ b/sound/soc/sof/intel/hda-pcm.c @@ -219,6 +219,7 @@ EXPORT_SYMBOL_NS(hda_dsp_pcm_pointer, "SND_SOC_SOF_INTEL_HDA_COMMON"); int hda_dsp_pcm_open(struct snd_sof_dev *sdev, struct snd_pcm_substream *substream) { + const struct sof_intel_dsp_desc *chip_info = get_chip_info(sdev->pdata); struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream); struct snd_pcm_runtime *runtime = substream->runtime; struct snd_soc_component *scomp = sdev->component; @@ -268,8 +269,17 @@ int hda_dsp_pcm_open(struct snd_sof_dev *sdev, return -ENODEV; } - /* minimum as per HDA spec */ - snd_pcm_hw_constraint_step(substream->runtime, 0, SNDRV_PCM_HW_PARAM_PERIOD_BYTES, 4); + /* + * Set period size constraint to ensure BDLE buffer length and + * start address alignment requirements are met. Align to 128 + * bytes for newer Intel platforms, with older ones using 4 byte alignment. + */ + if (chip_info->hw_ip_version >= SOF_INTEL_ACE_4_0) + snd_pcm_hw_constraint_step(substream->runtime, 0, + SNDRV_PCM_HW_PARAM_PERIOD_BYTES, 128); + else + snd_pcm_hw_constraint_step(substream->runtime, 0, + SNDRV_PCM_HW_PARAM_PERIOD_BYTES, 4); /* avoid circular buffer wrap in middle of period */ snd_pcm_hw_constraint_integer(substream->runtime, From 0669631dbccd41cf3ca7aa70213fcd8bb41c4b38 Mon Sep 17 00:00:00 2001 From: Tomasz Merta Date: Wed, 8 Apr 2026 10:40:56 +0200 Subject: [PATCH 12/16] ASoC: stm32_sai: fix incorrect BCLK polarity for DSP_A/B, LEFT_J The STM32 SAI driver do not set the clock strobing bit (CKSTR) for DSP_A, DSP_B and LEFT_J formats, causing data to be sampled on the wrong BCLK edge when SND_SOC_DAIFMT_NB_NF is used. Per ALSA convention, NB_NF requires sampling on the rising BCLK edge. The STM32MP25 SAI reference manual states that CKSTR=1 is required for signals received by the SAI to be sampled on the SCK rising edge. Without setting CKSTR=1, the SAI samples on the falling edge, violating the NB_NF convention. For comparison, the NXP FSL SAI driver correctly sets FSL_SAI_CR2_BCP for DSP_A, DSP_B and LEFT_J, consistent with its I2S handling. This patch adds SAI_XCR1_CKSTR for DSP_A, DSP_B and LEFT_J in stm32_sai_set_dai_fmt which was verified empirically with a cs47l35 codec. RIGHT_J (LSB) is not investigated and addressed by this patch. Note: the STM32 I2S driver (stm32_i2s_set_dai_fmt) may have the same issue for DSP_A mode, as I2S_CGFR_CKPOL is not set. This has not been verified and is left for a separate investigation. Signed-off-by: Tomasz Merta Link: https://patch.msgid.link/20260408084056.20588-1-tommerta@gmail.com Signed-off-by: Mark Brown --- sound/soc/stm/stm32_sai_sub.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/sound/soc/stm/stm32_sai_sub.c b/sound/soc/stm/stm32_sai_sub.c index 450e1585edee..3e82fa90e719 100644 --- a/sound/soc/stm/stm32_sai_sub.c +++ b/sound/soc/stm/stm32_sai_sub.c @@ -802,6 +802,7 @@ static int stm32_sai_set_dai_fmt(struct snd_soc_dai *cpu_dai, unsigned int fmt) break; /* Left justified */ case SND_SOC_DAIFMT_MSB: + cr1 |= SAI_XCR1_CKSTR; frcr |= SAI_XFRCR_FSPOL | SAI_XFRCR_FSDEF; break; /* Right justified */ @@ -809,9 +810,11 @@ static int stm32_sai_set_dai_fmt(struct snd_soc_dai *cpu_dai, unsigned int fmt) frcr |= SAI_XFRCR_FSPOL | SAI_XFRCR_FSDEF; break; case SND_SOC_DAIFMT_DSP_A: + cr1 |= SAI_XCR1_CKSTR; frcr |= SAI_XFRCR_FSPOL | SAI_XFRCR_FSOFF; break; case SND_SOC_DAIFMT_DSP_B: + cr1 |= SAI_XCR1_CKSTR; frcr |= SAI_XFRCR_FSPOL; break; default: From 23e0cbe55736de222ed975863cf06baf29bee5fe Mon Sep 17 00:00:00 2001 From: Maciej Strozek Date: Wed, 8 Apr 2026 10:38:31 +0100 Subject: [PATCH 13/16] ASoC: SDCA: Fix overwritten var within for loop mask variable should not be overwritten within the for loop or it will skip certain bits. Change to using BIT() macro. Fixes: b9ab3b618241 ("ASoC: SDCA: Add some initial IRQ handlers") Signed-off-by: Maciej Strozek Signed-off-by: Charles Keepax Link: https://patch.msgid.link/20260408093835.2881486-2-ckeepax@opensource.cirrus.com Signed-off-by: Mark Brown --- sound/soc/sdca/sdca_interrupts.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/sound/soc/sdca/sdca_interrupts.c b/sound/soc/sdca/sdca_interrupts.c index 1838dabcdf60..9acb0be84674 100644 --- a/sound/soc/sdca/sdca_interrupts.c +++ b/sound/soc/sdca/sdca_interrupts.c @@ -117,9 +117,7 @@ static irqreturn_t function_status_handler(int irq, void *data) status = val; for_each_set_bit(mask, &status, BITS_PER_BYTE) { - mask = 1 << mask; - - switch (mask) { + switch (BIT(mask)) { case SDCA_CTL_ENTITY_0_FUNCTION_NEEDS_INITIALIZATION: //FIXME: Add init writes break; From 58dec4fac4c46b42b8264f2d8aa6972ff951c18b Mon Sep 17 00:00:00 2001 From: Maciej Strozek Date: Wed, 8 Apr 2026 10:38:32 +0100 Subject: [PATCH 14/16] ASoC: SDCA: mask Function_Status value According to the SDCA specification [1], when writing Function_Status during handling this control, the value should mask off bit 7. [1] MIPI Specification for SoundWire Device Class for Audio, version 1.1, section 7.14.1.3 (Host Software Handling of Function_Status) Signed-off-by: Maciej Strozek Signed-off-by: Charles Keepax Link: https://patch.msgid.link/20260408093835.2881486-3-ckeepax@opensource.cirrus.com Signed-off-by: Mark Brown --- sound/soc/sdca/sdca_interrupts.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/sdca/sdca_interrupts.c b/sound/soc/sdca/sdca_interrupts.c index 9acb0be84674..0693209ffed1 100644 --- a/sound/soc/sdca/sdca_interrupts.c +++ b/sound/soc/sdca/sdca_interrupts.c @@ -138,7 +138,7 @@ static irqreturn_t function_status_handler(int irq, void *data) } } - ret = regmap_write(interrupt->function_regmap, reg, val); + ret = regmap_write(interrupt->function_regmap, reg, val & 0x7F); if (ret < 0) { dev_err(dev, "failed to clear function status: %d\n", ret); goto error; From 0b8757b220f94421bd4ff50cce03886387c4e71c Mon Sep 17 00:00:00 2001 From: Richard Fitzgerald Date: Wed, 8 Apr 2026 10:38:34 +0100 Subject: [PATCH 15/16] ASoC: SDCA: Unregister IRQ handlers on module remove Ensure that all interrupt handlers are unregistered before the parent regmap_irq is unregistered. sdca_irq_cleanup() was only called from the component_remove(). If the module was loaded and removed without ever being component probed the FDL interrupts would not be unregistered and this would hit a WARN when devm called regmap_del_irq_chip() during the removal of the parent IRQ. Fixes: 4e53116437e9 ("ASoC: SDCA: Fix errors in IRQ cleanup") Signed-off-by: Richard Fitzgerald Signed-off-by: Charles Keepax Link: https://patch.msgid.link/20260408093835.2881486-5-ckeepax@opensource.cirrus.com Signed-off-by: Mark Brown --- include/sound/sdca_interrupts.h | 4 ++-- sound/soc/sdca/sdca_class_function.c | 10 +++++++++- sound/soc/sdca/sdca_interrupts.c | 7 +++---- 3 files changed, 14 insertions(+), 7 deletions(-) diff --git a/include/sound/sdca_interrupts.h b/include/sound/sdca_interrupts.h index b47003c3d26e..a515cc3df097 100644 --- a/include/sound/sdca_interrupts.h +++ b/include/sound/sdca_interrupts.h @@ -83,8 +83,8 @@ int sdca_irq_populate_early(struct device *dev, struct regmap *function_regmap, int sdca_irq_populate(struct sdca_function_data *function, struct snd_soc_component *component, struct sdca_interrupt_info *info); -void sdca_irq_cleanup(struct sdca_function_data *function, - struct snd_soc_component *component, +void sdca_irq_cleanup(struct device *dev, + struct sdca_function_data *function, struct sdca_interrupt_info *info); struct sdca_interrupt_info *sdca_irq_allocate(struct device *dev, struct regmap *regmap, int irq); diff --git a/sound/soc/sdca/sdca_class_function.c b/sound/soc/sdca/sdca_class_function.c index fe404d769c78..730103120514 100644 --- a/sound/soc/sdca/sdca_class_function.c +++ b/sound/soc/sdca/sdca_class_function.c @@ -203,7 +203,7 @@ static void class_function_component_remove(struct snd_soc_component *component) struct class_function_drv *drv = snd_soc_component_get_drvdata(component); struct sdca_class_drv *core = drv->core; - sdca_irq_cleanup(drv->function, component, core->irq_info); + sdca_irq_cleanup(component->dev, drv->function, core->irq_info); } static int class_function_set_jack(struct snd_soc_component *component, @@ -411,6 +411,13 @@ static int class_function_probe(struct auxiliary_device *auxdev, return 0; } +static void class_function_remove(struct auxiliary_device *auxdev) +{ + struct class_function_drv *drv = auxiliary_get_drvdata(auxdev); + + sdca_irq_cleanup(drv->dev, drv->function, drv->core->irq_info); +} + static int class_function_runtime_suspend(struct device *dev) { struct auxiliary_device *auxdev = to_auxiliary_dev(dev); @@ -559,6 +566,7 @@ static struct auxiliary_driver class_function_drv = { }, .probe = class_function_probe, + .remove = class_function_remove, .id_table = class_function_id_table }; module_auxiliary_driver(class_function_drv); diff --git a/sound/soc/sdca/sdca_interrupts.c b/sound/soc/sdca/sdca_interrupts.c index 0693209ffed1..5cdabf8ae9da 100644 --- a/sound/soc/sdca/sdca_interrupts.c +++ b/sound/soc/sdca/sdca_interrupts.c @@ -555,17 +555,16 @@ EXPORT_SYMBOL_NS_GPL(sdca_irq_populate, "SND_SOC_SDCA"); /** * sdca_irq_cleanup - Free all the individual IRQs for an SDCA Function + * @sdev: Device pointer against which the sdca_interrupt_info was allocated. * @function: Pointer to the SDCA Function. - * @component: Pointer to the ASoC component for the Function. * @info: Pointer to the SDCA interrupt info for this device. * * Typically this would be called from the driver for a single SDCA Function. */ -void sdca_irq_cleanup(struct sdca_function_data *function, - struct snd_soc_component *component, +void sdca_irq_cleanup(struct device *dev, + struct sdca_function_data *function, struct sdca_interrupt_info *info) { - struct device *dev = component->dev; int i; guard(mutex)(&info->irq_lock); From 6b6f7263d626886a96fce6352f94dfab7a24c339 Mon Sep 17 00:00:00 2001 From: Syed Saba Kareem Date: Wed, 8 Apr 2026 19:00:06 +0530 Subject: [PATCH 16/16] ASoC: amd: acp: update DMI quirk and add ACP DMIC for Lenovo platforms Replace DMI_EXACT_MATCH with DMI_MATCH for Lenovo SKU entries (21YW, 21YX) so the quirk applies to all variants of these models, not just exact SKU matches. Add ASOC_SDW_ACP_DMIC flag alongside ASOC_SDW_CODEC_SPKR in driver_data for these Lenovo platform entries, as these platforms use ACP PDM DMIC instead of SoundWire DMIC for digital microphone support. Fixes: 3acf517e1ae0 ("ASoC: amd: amd_sdw: add machine driver quirk for Lenovo models") Tested-by: Mark Pearson Reviewed-by: Mark Pearson Signed-off-by: Syed Saba Kareem Reviewed-by: Vijendar Mukunda Link: https://patch.msgid.link/20260408133029.1368317-1-syed.sabakareem@amd.com Signed-off-by: Mark Brown --- sound/soc/amd/acp/acp-sdw-legacy-mach.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/sound/soc/amd/acp/acp-sdw-legacy-mach.c b/sound/soc/amd/acp/acp-sdw-legacy-mach.c index 92749dc17df8..cd7b1acc7216 100644 --- a/sound/soc/amd/acp/acp-sdw-legacy-mach.c +++ b/sound/soc/amd/acp/acp-sdw-legacy-mach.c @@ -99,17 +99,17 @@ static const struct dmi_system_id soc_sdw_quirk_table[] = { .callback = soc_sdw_quirk_cb, .matches = { DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), - DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "21YW"), + DMI_MATCH(DMI_PRODUCT_SKU, "21YW"), }, - .driver_data = (void *)(ASOC_SDW_CODEC_SPKR), + .driver_data = (void *)((ASOC_SDW_CODEC_SPKR) | (ASOC_SDW_ACP_DMIC)), }, { .callback = soc_sdw_quirk_cb, .matches = { DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), - DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "21YX"), + DMI_MATCH(DMI_PRODUCT_SKU, "21YX"), }, - .driver_data = (void *)(ASOC_SDW_CODEC_SPKR), + .driver_data = (void *)((ASOC_SDW_CODEC_SPKR) | (ASOC_SDW_ACP_DMIC)), }, { .callback = soc_sdw_quirk_cb,