From bc9b1ebaa7624edde54d4ae842d11cebb26db09b Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Mon, 13 Apr 2026 09:00:45 +0200 Subject: [PATCH 01/41] ASoC: tas2781: fix unused-const-variable warning When both CONFIG_OF and CONFIG_ACPI are disabled, the ID table is not referenced any more: sound/soc/codecs/tas2781-i2c.c:102:35: error: 'tasdevice_id' defined but not used [-Werror=unused-const-variable=] 102 | static const struct i2c_device_id tasdevice_id[] = { | ^~~~~~~~~~~~ Remove the #ifdef checks and just include the ID tables unconditionally to get a clean build in all configurations. The code already uses IS_ENABLED() checks for both to benefit from dead code elimination and the ID tables are small enough that they can just be included all the time. Fixes: 9a52d1b7cb4a ("ASoC: tas2781: Explicit association of Device, Device Name, and Device ID") Signed-off-by: Arnd Bergmann Link: https://patch.msgid.link/20260413070059.3828364-1-arnd@kernel.org Signed-off-by: Mark Brown --- sound/soc/codecs/tas2781-i2c.c | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/sound/soc/codecs/tas2781-i2c.c b/sound/soc/codecs/tas2781-i2c.c index c593f9da0c5b..8af30f4d68da 100644 --- a/sound/soc/codecs/tas2781-i2c.c +++ b/sound/soc/codecs/tas2781-i2c.c @@ -122,7 +122,6 @@ static const struct i2c_device_id tasdevice_id[] = { {} }; -#ifdef CONFIG_OF static const struct of_device_id tasdevice_of_match[] = { { .compatible = "ti,tas2020", .data = &tasdevice_id[TAS2020] }, { .compatible = "ti,tas2118", .data = &tasdevice_id[TAS2118] }, @@ -146,7 +145,6 @@ static const struct of_device_id tasdevice_of_match[] = { {}, }; MODULE_DEVICE_TABLE(of, tasdevice_of_match); -#endif /** * tas2781_digital_getvol - get the volum control @@ -2083,7 +2081,6 @@ static void tasdevice_i2c_remove(struct i2c_client *client) tasdevice_remove(tas_priv); } -#ifdef CONFIG_ACPI static const struct acpi_device_id tasdevice_acpi_match[] = { { "TXNW2020", (kernel_ulong_t)&tasdevice_id[TAS2020] }, { "TXNW2118", (kernel_ulong_t)&tasdevice_id[TAS2118] }, @@ -2108,15 +2105,12 @@ static const struct acpi_device_id tasdevice_acpi_match[] = { }; MODULE_DEVICE_TABLE(acpi, tasdevice_acpi_match); -#endif static struct i2c_driver tasdevice_i2c_driver = { .driver = { .name = "tasdev-codec", - .of_match_table = of_match_ptr(tasdevice_of_match), -#ifdef CONFIG_ACPI - .acpi_match_table = ACPI_PTR(tasdevice_acpi_match), -#endif + .of_match_table = tasdevice_of_match, + .acpi_match_table = tasdevice_acpi_match, }, .probe = tasdevice_i2c_probe, .remove = tasdevice_i2c_remove, From 54a032d3e62fd1792cb16d8096aaf00397589c5f Mon Sep 17 00:00:00 2001 From: Peng Fan Date: Mon, 13 Apr 2026 18:52:43 +0800 Subject: [PATCH 02/41] ASoC: pxa2xx-ac97: fix error handling for reset GPIO descriptor The reset GPIO obtained via devm_gpiod_get() may return an ERR_PTR() when the GPIO is missing or an error occurs. The current code unconditionally assigns PTR_ERR() to ret and later dereferences rst_gpio via desc_to_gpio(), which is incorrect when rst_gpio is an error pointer. Rework the logic to first check IS_ERR(rst_gpio) before converting the descriptor. Handle -ENOENT by disabling reset GPIO support, and return other errors to the caller as expected. Fixes: c76d50b71e89 ("ASoC: ac97: Convert to GPIO descriptors") Reported-by: kernel test robot Reported-by: Dan Carpenter Closes: https://lore.kernel.org/r/202604041426.i2C1xqHk-lkp@intel.com/ Signed-off-by: Peng Fan Link: https://patch.msgid.link/20260413-ac97-v1-1-b44b9e084307@nxp.com Signed-off-by: Mark Brown --- sound/arm/pxa2xx-ac97-lib.c | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/sound/arm/pxa2xx-ac97-lib.c b/sound/arm/pxa2xx-ac97-lib.c index 1e114dbcf93c..79eb557d4942 100644 --- a/sound/arm/pxa2xx-ac97-lib.c +++ b/sound/arm/pxa2xx-ac97-lib.c @@ -331,12 +331,15 @@ int pxa2xx_ac97_hw_probe(struct platform_device *dev) if (dev->dev.of_node) { /* Assert reset using GPIOD_OUT_HIGH, because reset is GPIO_ACTIVE_LOW */ rst_gpio = devm_gpiod_get(&dev->dev, "reset", GPIOD_OUT_HIGH); - ret = PTR_ERR(rst_gpio); - if (ret == -ENOENT) - reset_gpio = -1; - else if (ret) - return ret; - reset_gpio = desc_to_gpio(rst_gpio); + if (IS_ERR(rst_gpio)) { + ret = PTR_ERR(rst_gpio); + if (ret == -ENOENT) + reset_gpio = -1; + else if (ret) + return ret; + } else { + reset_gpio = desc_to_gpio(rst_gpio); + } } else { if (cpu_is_pxa27x()) reset_gpio = 113; From cf162476f7e082662691e75f96bfc99c6a64810d Mon Sep 17 00:00:00 2001 From: Shuming Fan Date: Tue, 14 Apr 2026 15:14:41 +0800 Subject: [PATCH 03/41] ASoC: rt1320: fix the warning 'rae_fw' from request_firmware() not released New smatch warnings: sound/soc/codecs/rt1320-sdw.c:1575 rt1320_rae_load() warn: 'rae_fw' from request_firmware() not released on lines: 1575. Fixes: 22937af75abb ("ASoC: rt1320: support RAE parameters loading") Reported-by: kernel test robot Reported-by: Dan Carpenter Closes: https://lore.kernel.org/r/202604111548.EL450PMb-lkp@intel.com/ Signed-off-by: Shuming Fan Link: https://patch.msgid.link/20260414071441.1524039-1-shumingf@realtek.com Signed-off-by: Mark Brown --- sound/soc/codecs/rt1320-sdw.c | 1 + 1 file changed, 1 insertion(+) diff --git a/sound/soc/codecs/rt1320-sdw.c b/sound/soc/codecs/rt1320-sdw.c index b0aeeab26bd9..192faa431b5e 100644 --- a/sound/soc/codecs/rt1320-sdw.c +++ b/sound/soc/codecs/rt1320-sdw.c @@ -1498,6 +1498,7 @@ static int rt1320_rae_load(struct rt1320_sdw_priv *rt1320) } if (!retry && !(value & 0x40)) { dev_err(dev, "%s: RAE is not ready to load\n", __func__); + release_firmware(rae_fw); return -ETIMEDOUT; } From ab463b4655857b1865c611ff5fbcb752cd804b0b Mon Sep 17 00:00:00 2001 From: Bard Liao Date: Mon, 13 Apr 2026 14:07:59 +0800 Subject: [PATCH 04/41] ASoC: SOF: Intel: NVL: add platform name MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The platform name will be used in the topology name. Fixes: 1800bcdc68ead ("ASoC: SOF: Intel: add support for Nova Lake NVL") Signed-off-by: Bard Liao Reviewed-by: Péter Ujfalusi Link: https://patch.msgid.link/20260413060800.3156425-2-yung-chuan.liao@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/intel/nvl.c | 1 + 1 file changed, 1 insertion(+) diff --git a/sound/soc/sof/intel/nvl.c b/sound/soc/sof/intel/nvl.c index 0d763998558f..0ee3507824e5 100644 --- a/sound/soc/sof/intel/nvl.c +++ b/sound/soc/sof/intel/nvl.c @@ -48,6 +48,7 @@ const struct sof_intel_dsp_desc nvl_chip_info = { .power_down_dsp = mtl_power_down_dsp, .disable_interrupts = lnl_dsp_disable_interrupts, .hw_ip_version = SOF_INTEL_ACE_4_0, + .platform = "nvl", }; const struct sof_intel_dsp_desc nvl_s_chip_info = { From a158fe7b0c817eebcf2871fe1306347a376030e8 Mon Sep 17 00:00:00 2001 From: Bard Liao Date: Mon, 13 Apr 2026 14:08:00 +0800 Subject: [PATCH 05/41] ASoC: SOF: Intel: NVL-S: add platform name MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The platform name will be used in the topology name. Fixes: d3df422f66e8a ("ASoC: SOF: Intel: add initial support for NVL-S") Signed-off-by: Bard Liao Reviewed-by: Péter Ujfalusi Link: https://patch.msgid.link/20260413060800.3156425-3-yung-chuan.liao@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/intel/nvl.c | 1 + 1 file changed, 1 insertion(+) diff --git a/sound/soc/sof/intel/nvl.c b/sound/soc/sof/intel/nvl.c index 0ee3507824e5..86d2e1aa0eec 100644 --- a/sound/soc/sof/intel/nvl.c +++ b/sound/soc/sof/intel/nvl.c @@ -73,6 +73,7 @@ const struct sof_intel_dsp_desc nvl_s_chip_info = { .power_down_dsp = mtl_power_down_dsp, .disable_interrupts = lnl_dsp_disable_interrupts, .hw_ip_version = SOF_INTEL_ACE_4_0, + .platform = "nvl", }; MODULE_IMPORT_NS("SND_SOC_SOF_INTEL_MTL"); From 28abd224db4a49560b452115bca3672a20e45b2f Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Tue, 14 Apr 2026 12:59:00 +0200 Subject: [PATCH 06/41] ALSA: caiaq: Handle probe errors properly The probe procedure of setup_card() in caiaq driver doesn't treat the error cases gracefully, e.g. the error from snd_card_register() calls snd_card_free() but continues. This would lead to a UAF for the further calls like snd_usb_caiaq_control_init(), as Berk suggested in another patch in the link below. However, the problem is not only that; in general, this function drops the all error handlings (as it's a void function) although its caller can propagate an error to snd_probe(), which eventually calls snd_card_free() as a proper error path. That said, we should treat each error case in setup_card(), and just return the error code promptly, which is then handled later as a fatal error in snd_probe(). This patch achieves it by changing the setup_card() to return an error code. Also, the superfluous snd_card_free() call is removed, too. Note that card->private_free can be set still safely at returning an error. All called functions in card_free() have checks of the unassigned resources or NULL checks. Fixes: 8e3cd08ed8e5 ("[ALSA] caiaq - add control API and more input features") Cc: stable@vger.kernel.org Link: https://lore.kernel.org/20260413034941.1131465-2-berkcgoksel@gmail.com Link: https://patch.msgid.link/20260414105916.364073-1-tiwai@suse.de Signed-off-by: Takashi Iwai --- sound/usb/caiaq/device.c | 33 ++++++++++++++++++++++++--------- 1 file changed, 24 insertions(+), 9 deletions(-) diff --git a/sound/usb/caiaq/device.c b/sound/usb/caiaq/device.c index 51177ebfb8c6..8af0c04041ee 100644 --- a/sound/usb/caiaq/device.c +++ b/sound/usb/caiaq/device.c @@ -290,7 +290,7 @@ int snd_usb_caiaq_set_auto_msg(struct snd_usb_caiaqdev *cdev, tmp, sizeof(tmp)); } -static void setup_card(struct snd_usb_caiaqdev *cdev) +static int setup_card(struct snd_usb_caiaqdev *cdev) { int ret; char val[4]; @@ -325,8 +325,10 @@ static void setup_card(struct snd_usb_caiaqdev *cdev) snd_usb_caiaq_send_command(cdev, EP1_CMD_READ_IO, NULL, 0); if (!wait_event_timeout(cdev->ep1_wait_queue, - cdev->control_state[0] != 0xff, HZ)) - return; + cdev->control_state[0] != 0xff, HZ)) { + dev_err(dev, "Read timeout for control state\n"); + return -EINVAL; + } /* fix up some defaults */ if ((cdev->control_state[1] != 2) || @@ -347,33 +349,43 @@ static void setup_card(struct snd_usb_caiaqdev *cdev) cdev->spec.num_digital_audio_out + cdev->spec.num_digital_audio_in > 0) { ret = snd_usb_caiaq_audio_init(cdev); - if (ret < 0) + if (ret < 0) { dev_err(dev, "Unable to set up audio system (ret=%d)\n", ret); + return ret; + } } if (cdev->spec.num_midi_in + cdev->spec.num_midi_out > 0) { ret = snd_usb_caiaq_midi_init(cdev); - if (ret < 0) + if (ret < 0) { dev_err(dev, "Unable to set up MIDI system (ret=%d)\n", ret); + return ret; + } } #ifdef CONFIG_SND_USB_CAIAQ_INPUT ret = snd_usb_caiaq_input_init(cdev); - if (ret < 0) + if (ret < 0) { dev_err(dev, "Unable to set up input system (ret=%d)\n", ret); + return ret; + } #endif /* finally, register the card and all its sub-instances */ ret = snd_card_register(cdev->chip.card); if (ret < 0) { dev_err(dev, "snd_card_register() returned %d\n", ret); - snd_card_free(cdev->chip.card); + return ret; } ret = snd_usb_caiaq_control_init(cdev); - if (ret < 0) + if (ret < 0) { dev_err(dev, "Unable to set up control system (ret=%d)\n", ret); + return ret; + } + + return 0; } static void card_free(struct snd_card *card) @@ -499,8 +511,11 @@ static int init_card(struct snd_usb_caiaqdev *cdev) scnprintf(card->longname, sizeof(card->longname), "%s %s (%s)", cdev->vendor_name, cdev->product_name, usbpath); - setup_card(cdev); card->private_free = card_free; + err = setup_card(cdev); + if (err < 0) + return err; + return 0; err_kill_urb: From f3c80e76a0e94c7c9771997de90f6a284b4f10d9 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Tue, 14 Apr 2026 15:22:11 +0200 Subject: [PATCH 07/41] ALSA: 6fire: Cover the whole probe and disconnect calls with register_mutex In 6fire driver, we protect the concurrent calls against probe and disconnect with the register_mutex, but it's applied only partially. Since we handle two global pointers in devices[] and chips[] pairs, the assignment of the latter can be inconsistent upon concurrent interface probes, and the refcount handling isn't properly protected at disconnect, either. This patch extends the mutex application range to the whole probe and disconnect functions. It makes the code safer against potential concurrent probles and disconnects, while it makes the code easier to read, too. Signed-off-by: Takashi Iwai Link: https://patch.msgid.link/20260414132218.411013-2-tiwai@suse.de --- sound/usb/6fire/chip.c | 36 +++++++++++++++++------------------- 1 file changed, 17 insertions(+), 19 deletions(-) diff --git a/sound/usb/6fire/chip.c b/sound/usb/6fire/chip.c index 874f6cd503ca..18a25449bcd3 100644 --- a/sound/usb/6fire/chip.c +++ b/sound/usb/6fire/chip.c @@ -83,22 +83,21 @@ static int usb6fire_chip_probe(struct usb_interface *intf, struct snd_card *card = NULL; /* look if we already serve this card and return if so */ - scoped_guard(mutex, ®ister_mutex) { - for (i = 0; i < SNDRV_CARDS; i++) { - if (devices[i] == device) { - if (chips[i]) - chips[i]->intf_count++; - usb_set_intfdata(intf, chips[i]); - return 0; - } else if (!devices[i] && regidx < 0) - regidx = i; - } - if (regidx < 0) { - dev_err(&intf->dev, "too many cards registered.\n"); - return -ENODEV; - } - devices[regidx] = device; + guard(mutex)(®ister_mutex); + for (i = 0; i < SNDRV_CARDS; i++) { + if (devices[i] == device) { + if (chips[i]) + chips[i]->intf_count++; + usb_set_intfdata(intf, chips[i]); + return 0; + } else if (!devices[i] && regidx < 0) + regidx = i; } + if (regidx < 0) { + dev_err(&intf->dev, "too many cards registered.\n"); + return -ENODEV; + } + devices[regidx] = device; /* check, if firmware is present on device, upload it if not */ ret = usb6fire_fw_init(intf); @@ -165,14 +164,13 @@ static void usb6fire_chip_disconnect(struct usb_interface *intf) struct sfire_chip *chip; struct snd_card *card; + guard(mutex)(®ister_mutex); chip = usb_get_intfdata(intf); if (chip) { /* if !chip, fw upload has been performed */ chip->intf_count--; if (!chip->intf_count) { - scoped_guard(mutex, ®ister_mutex) { - devices[chip->regidx] = NULL; - chips[chip->regidx] = NULL; - } + devices[chip->regidx] = NULL; + chips[chip->regidx] = NULL; /* * Save card pointer before teardown. From 4d5de85b6a9961130666070061a2466913a5c607 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Tue, 14 Apr 2026 15:22:12 +0200 Subject: [PATCH 08/41] ALSA: 6fire: Fix leftover global pointers after probe failures snd-usb-6fire driver holds devices[] and chips[] pointer arrays to keep the usb_device and sfire_chip objects assigned to multiple interfaces. Those are, however, not properly cleared at the error path of usb6fire_chip_probe(), which may confuse the later probes. Also, the use of two pointer arrays makes things complicated; chips[] may be NULL while devices[] may be left over. For addressing this inconsistency, unify the pointer arrays, and use only chips[] for managing the multiple devices, while the device is checked with chip->dev pointer, instead. Also, the assignment of chips[] is moved at a later point where the probe successfully returns, so that we don't leave the pointer there after the error. Signed-off-by: Takashi Iwai Link: https://patch.msgid.link/20260414132218.411013-3-tiwai@suse.de --- sound/usb/6fire/chip.c | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/sound/usb/6fire/chip.c b/sound/usb/6fire/chip.c index 18a25449bcd3..dd787de986b1 100644 --- a/sound/usb/6fire/chip.c +++ b/sound/usb/6fire/chip.c @@ -31,7 +31,6 @@ static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; /* Index 0-max */ static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; /* Id for card */ static bool enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP; /* Enable card */ static struct sfire_chip *chips[SNDRV_CARDS] = SNDRV_DEFAULT_PTR; -static struct usb_device *devices[SNDRV_CARDS] = SNDRV_DEFAULT_PTR; module_param_array(index, int, NULL, 0444); MODULE_PARM_DESC(index, "Index value for the 6fire sound device"); @@ -85,19 +84,17 @@ static int usb6fire_chip_probe(struct usb_interface *intf, /* look if we already serve this card and return if so */ guard(mutex)(®ister_mutex); for (i = 0; i < SNDRV_CARDS; i++) { - if (devices[i] == device) { - if (chips[i]) - chips[i]->intf_count++; + if (chips[i] && chips[i]->dev == device) { + chips[i]->intf_count++; usb_set_intfdata(intf, chips[i]); return 0; - } else if (!devices[i] && regidx < 0) + } else if (!chips[i] && regidx < 0) regidx = i; } if (regidx < 0) { dev_err(&intf->dev, "too many cards registered.\n"); return -ENODEV; } - devices[regidx] = device; /* check, if firmware is present on device, upload it if not */ ret = usb6fire_fw_init(intf); @@ -123,7 +120,6 @@ static int usb6fire_chip_probe(struct usb_interface *intf, device->bus->busnum, device->devnum); chip = card->private_data; - chips[regidx] = chip; chip->dev = device; chip->regidx = regidx; chip->intf_count = 1; @@ -151,7 +147,10 @@ static int usb6fire_chip_probe(struct usb_interface *intf, dev_err(&intf->dev, "cannot register card."); goto destroy_chip; } + usb_set_intfdata(intf, chip); + chips[regidx] = chip; + return 0; destroy_chip: @@ -169,7 +168,6 @@ static void usb6fire_chip_disconnect(struct usb_interface *intf) if (chip) { /* if !chip, fw upload has been performed */ chip->intf_count--; if (!chip->intf_count) { - devices[chip->regidx] = NULL; chips[chip->regidx] = NULL; /* From 14101a067012ee227b7c3e5ec877e79885961cff Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Tue, 14 Apr 2026 15:22:13 +0200 Subject: [PATCH 09/41] ALSA: 6fire: Reduce multi-level conditionals in usb6fire_chip_disconnect() The current code has deep indentation levels because of multiple if's. Make it returning and reduce the multi-level conditionals for increasing the code readability. No functional change, just but a code refactoring. Signed-off-by: Takashi Iwai Link: https://patch.msgid.link/20260414132218.411013-4-tiwai@suse.de --- sound/usb/6fire/chip.c | 41 ++++++++++++++++++++++------------------- 1 file changed, 22 insertions(+), 19 deletions(-) diff --git a/sound/usb/6fire/chip.c b/sound/usb/6fire/chip.c index dd787de986b1..556882bd9022 100644 --- a/sound/usb/6fire/chip.c +++ b/sound/usb/6fire/chip.c @@ -165,26 +165,29 @@ static void usb6fire_chip_disconnect(struct usb_interface *intf) guard(mutex)(®ister_mutex); chip = usb_get_intfdata(intf); - if (chip) { /* if !chip, fw upload has been performed */ - chip->intf_count--; - if (!chip->intf_count) { - chips[chip->regidx] = NULL; + /* if !chip, fw upload has been performed */ + if (!chip) + return; - /* - * Save card pointer before teardown. - * snd_card_free_when_closed() may free card (and - * the embedded chip) immediately, so it must be - * called last and chip must not be accessed after. - */ - card = chip->card; - chip->shutdown = true; - if (card) - snd_card_disconnect(card); - usb6fire_chip_abort(chip); - if (card) - snd_card_free_when_closed(card); - } - } + chip->intf_count--; + if (chip->intf_count) + return; + + chips[chip->regidx] = NULL; + + /* + * Save card pointer before teardown. + * snd_card_free_when_closed() may free card (and + * the embedded chip) immediately, so it must be + * called last and chip must not be accessed after. + */ + card = chip->card; + chip->shutdown = true; + if (card) + snd_card_disconnect(card); + usb6fire_chip_abort(chip); + if (card) + snd_card_free_when_closed(card); } static const struct usb_device_id device_table[] = { From 02df59d0258cd97cc60b49e5570ebfcc95ea6030 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Tue, 14 Apr 2026 15:22:14 +0200 Subject: [PATCH 10/41] ALSA: 6fire: Drop unnecessary NULL checks The NULL checks of chip pointer in usb6fire_chip_abrt() and usb6fire_card_free() are utterly useless, as it's guaranteed to be non-NULL. Drop them for increasing the readability. Signed-off-by: Takashi Iwai Link: https://patch.msgid.link/20260414132218.411013-5-tiwai@suse.de --- sound/usb/6fire/chip.c | 36 ++++++++++++++++-------------------- 1 file changed, 16 insertions(+), 20 deletions(-) diff --git a/sound/usb/6fire/chip.c b/sound/usb/6fire/chip.c index 556882bd9022..2c5648966412 100644 --- a/sound/usb/6fire/chip.c +++ b/sound/usb/6fire/chip.c @@ -43,32 +43,28 @@ static DEFINE_MUTEX(register_mutex); static void usb6fire_chip_abort(struct sfire_chip *chip) { - if (chip) { - if (chip->pcm) - usb6fire_pcm_abort(chip); - if (chip->midi) - usb6fire_midi_abort(chip); - if (chip->comm) - usb6fire_comm_abort(chip); - if (chip->control) - usb6fire_control_abort(chip); - } + if (chip->pcm) + usb6fire_pcm_abort(chip); + if (chip->midi) + usb6fire_midi_abort(chip); + if (chip->comm) + usb6fire_comm_abort(chip); + if (chip->control) + usb6fire_control_abort(chip); } static void usb6fire_card_free(struct snd_card *card) { struct sfire_chip *chip = card->private_data; - if (chip) { - if (chip->pcm) - usb6fire_pcm_destroy(chip); - if (chip->midi) - usb6fire_midi_destroy(chip); - if (chip->comm) - usb6fire_comm_destroy(chip); - if (chip->control) - usb6fire_control_destroy(chip); - } + if (chip->pcm) + usb6fire_pcm_destroy(chip); + if (chip->midi) + usb6fire_midi_destroy(chip); + if (chip->comm) + usb6fire_comm_destroy(chip); + if (chip->control) + usb6fire_control_destroy(chip); } static int usb6fire_chip_probe(struct usb_interface *intf, From 37a6b2d67b0a08e5c3d2156c9178c158c3c0225f Mon Sep 17 00:00:00 2001 From: Rong Zhang Date: Tue, 14 Apr 2026 21:29:01 +0800 Subject: [PATCH 11/41] ALSA: usb-audio: Tidy up error check for processing unit There are two duplicated code paths calling get_min_max() with the same arguments in build_audio_procunit(). This once led to a failure to notice a code path that caused the `err' variable uninitialized when adding error checks for callers of get_min_max*() [1]. Move cases in the switch-case statement to tidy up the error check by merging the duplicated code paths together with a fallthrough attribute. This also eliminates the `err = 0' lines and aggregates the error check along with the corresponding call together, so that the intent of these code paths is clearer. The refactor also has an interesting effect that shrinks the .text size by 16 bytes (GCC 15 amd64). It seems that the compiler was unable to perform dead code elimination for the `err = 0' paths before. Link: https://lore.kernel.org/r/ad36dGpCBTGsyFr_@stanley.mountain/ [1] Signed-off-by: Rong Zhang Link: https://patch.msgid.link/20260414-uac-build_auto_procunit-refactor-v1-1-afeb7efa6518@rong.moe Signed-off-by: Takashi Iwai --- sound/usb/mixer.c | 34 +++++++++++++++------------------- 1 file changed, 15 insertions(+), 19 deletions(-) diff --git a/sound/usb/mixer.c b/sound/usb/mixer.c index aa6ea3be100a..85653112e7f3 100644 --- a/sound/usb/mixer.c +++ b/sound/usb/mixer.c @@ -2664,6 +2664,16 @@ static int build_audio_procunit(struct mixer_build *state, int unitid, /* get min/max values */ switch (type) { + case USB_XU_CLOCK_RATE: + /* + * E-Mu USB 0404/0202/TrackerPre/0204 + * samplerate control quirk + */ + cval->min = 0; + cval->max = 5; + cval->res = 1; + cval->initialized = 1; + break; case UAC_PROCESS_UP_DOWNMIX: { bool mode_sel = false; @@ -2687,31 +2697,17 @@ static int build_audio_procunit(struct mixer_build *state, int unitid, cval->max = control_spec[0]; cval->res = 1; cval->initialized = 1; - err = 0; break; } - err = get_min_max(cval, valinfo->min_value); - break; + fallthrough; } - case USB_XU_CLOCK_RATE: - /* - * E-Mu USB 0404/0202/TrackerPre/0204 - * samplerate control quirk - */ - cval->min = 0; - cval->max = 5; - cval->res = 1; - cval->initialized = 1; - err = 0; - break; default: err = get_min_max(cval, valinfo->min_value); - break; - } - if (err < 0 && err != -EAGAIN) { - usb_mixer_elem_info_free(cval); - return err; + if (err < 0 && err != -EAGAIN) { + usb_mixer_elem_info_free(cval); + return err; + } } err = get_cur_ctl_value(cval, cval->control << 8, &val); From d9448dca423543c6c0a9890d3ff53a5d51895318 Mon Sep 17 00:00:00 2001 From: Timofey Tarasenko Date: Wed, 15 Apr 2026 17:46:57 +1000 Subject: [PATCH 12/41] ALSA: hda/realtek: add quirk for HONOR MRB-XXX M1020 Adds pin fixups to enable subwoofer and JACK functionality on Honor Magicbook Art 14 2025 (HONOR MRB-XXX M1020) Closes: https://bugzilla.kernel.org/show_bug.cgi?id=221147 Signed-off-by: Timofey Tarasenko Link: https://patch.msgid.link/20260415074657.1217862-1-timka.tarasen@gmail.com Signed-off-by: Takashi Iwai --- sound/hda/codecs/realtek/alc269.c | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/sound/hda/codecs/realtek/alc269.c b/sound/hda/codecs/realtek/alc269.c index b33f425763f9..a10a6969471a 100644 --- a/sound/hda/codecs/realtek/alc269.c +++ b/sound/hda/codecs/realtek/alc269.c @@ -4111,6 +4111,7 @@ enum { ALC245_FIXUP_ACER_MICMUTE_LED, ALC245_FIXUP_CS35L41_I2C_2_MUTE_LED, ALC236_FIXUP_HP_DMIC, + ALC256_FIXUP_HONOR_MRB_XXX_M1020_AUDIO, }; /* A special fixup for Lenovo C940 and Yoga Duet 7; @@ -6653,6 +6654,16 @@ static const struct hda_fixup alc269_fixups[] = { { 0x12, 0x90a60160 }, /* use as internal mic */ { } }, + }, + [ALC256_FIXUP_HONOR_MRB_XXX_M1020_AUDIO] = { + .type = HDA_FIXUP_PINS, + .v.pins = (const struct hda_pintbl[]) { + { 0x14, 0x90170111 }, + { 0x19, 0x03a1113c }, + { 0x1a, 0x22a190a0 }, + { 0x1b, 0x90170110 }, + { } + } } }; @@ -7751,6 +7762,7 @@ static const struct hda_quirk alc269_fixup_tbl[] = { SND_PCI_QUIRK(0x1d72, 0x1947, "RedmiBook Air", ALC255_FIXUP_XIAOMI_HEADSET_MIC), SND_PCI_QUIRK(0x1e39, 0xca14, "MEDION NM14LNL", ALC233_FIXUP_MEDION_MTL_SPK), SND_PCI_QUIRK(0x1ee7, 0x2078, "HONOR BRB-X M1010", ALC2XX_FIXUP_HEADSET_MIC), + SND_PCI_QUIRK(0x1ee7, 0x2081, "HONOR MRB-XXX M1020", ALC256_FIXUP_HONOR_MRB_XXX_M1020_AUDIO), SND_PCI_QUIRK(0x1f4c, 0xe001, "Minisforum V3 (SE)", ALC245_FIXUP_BASS_HP_DAC), SND_PCI_QUIRK(0x1f66, 0x0105, "Ayaneo Portable Game Player", ALC287_FIXUP_CS35L41_I2C_2), SND_PCI_QUIRK(0x2014, 0x800a, "Positivo ARN50", ALC269_FIXUP_LIMIT_INT_MIC_BOOST), @@ -7971,6 +7983,7 @@ static const struct hda_model_fixup alc269_fixup_models[] = { {.id = ALC236_FIXUP_LENOVO_INV_DMIC, .name = "alc236-fixup-lenovo-inv-mic"}, {.id = ALC2XX_FIXUP_HEADSET_MIC, .name = "alc2xx-fixup-headset-mic"}, {.id = ALC245_FIXUP_BASS_HP_DAC, .name = "alc245-fixup-bass-hp-dac"}, + {.id = ALC256_FIXUP_HONOR_MRB_XXX_M1020_AUDIO, .name = "alc256-honor-mrb-xxx-m1020-audio"}, {} }; #define ALC225_STANDARD_PINS \ From eb90ae3cca783ebec65704597027811431465de4 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Wed, 15 Apr 2026 15:55:22 +0200 Subject: [PATCH 13/41] ALSA: hda/intel: Move firmware loading into the probe work The hda-intel driver uses request_firmware_nowait() for loading its patch, and tries to continue the probe directly from the fw loader callback. This works in principle, but it has a few drawbacks: - The driver may be released before the firmware callback completes - Having two ways of async probe makes the code flow unnecessarily complex The former issue is more severe, as it may potentially lead to a UAF, and there is no explicit way to cancel the pending firmware worker for now. This patch changes the firmware loading to be performed rather in the common probe work without *_nowait(). Then the pending work can be easily canceled, and the code becomes more straightforward. A nice bonus is that, by moving into the probe work, the firmware doesn't need any longer to be cached, hence we can get rid of struct azx.fw field, and release the firmware immediately after parsing it, too. Fixes: 5cb543dba986 ("ALSA: hda - Deferred probing with request_firmware_nowait()") Link: https://patch.msgid.link/20260415135526.1813126-1-tiwai@suse.de Signed-off-by: Takashi Iwai --- sound/hda/common/hda_controller.h | 4 --- sound/hda/controllers/intel.c | 58 ++++++++----------------------- 2 files changed, 15 insertions(+), 47 deletions(-) diff --git a/sound/hda/common/hda_controller.h b/sound/hda/common/hda_controller.h index c2d0109866e6..7434f38038a0 100644 --- a/sound/hda/common/hda_controller.h +++ b/sound/hda/common/hda_controller.h @@ -127,10 +127,6 @@ struct azx { unsigned int beep_mode; bool ctl_dev_id; -#ifdef CONFIG_SND_HDA_PATCH_LOADER - const struct firmware *fw; -#endif - /* flags */ int bdl_pos_adj; unsigned int running:1; diff --git a/sound/hda/controllers/intel.c b/sound/hda/controllers/intel.c index 257c498c3260..c87d75dbd8aa 100644 --- a/sound/hda/controllers/intel.c +++ b/sound/hda/controllers/intel.c @@ -1385,9 +1385,6 @@ static void azx_free(struct azx *chip) azx_free_streams(chip); snd_hdac_bus_exit(bus); -#ifdef CONFIG_SND_HDA_PATCH_LOADER - release_firmware(chip->fw); -#endif display_power(chip, false); if (chip->driver_caps & AZX_DCAPS_I915_COMPONENT) @@ -2037,24 +2034,6 @@ static int azx_first_init(struct azx *chip) return 0; } -#ifdef CONFIG_SND_HDA_PATCH_LOADER -/* callback from request_firmware_nowait() */ -static void azx_firmware_cb(const struct firmware *fw, void *context) -{ - struct snd_card *card = context; - struct azx *chip = card->private_data; - - if (fw) - chip->fw = fw; - else - dev_err(card->dev, "Cannot load firmware, continue without patching\n"); - if (!chip->disabled) { - /* continue probing */ - azx_probe_continue(chip); - } -} -#endif - static int disable_msi_reset_irq(struct azx *chip) { struct hdac_bus *bus = azx_bus(chip); @@ -2131,7 +2110,6 @@ static int azx_probe(struct pci_dev *pci, struct snd_card *card; struct hda_intel *hda; struct azx *chip; - bool schedule_probe; int dev; int err; @@ -2227,22 +2205,7 @@ static int azx_probe(struct pci_dev *pci, chip->disabled = true; } - schedule_probe = !chip->disabled; - -#ifdef CONFIG_SND_HDA_PATCH_LOADER - if (patch[dev] && *patch[dev]) { - dev_info(card->dev, "Applying patch firmware '%s'\n", - patch[dev]); - err = request_firmware_nowait(THIS_MODULE, true, patch[dev], - &pci->dev, GFP_KERNEL, card, - azx_firmware_cb); - if (err < 0) - goto out_free; - schedule_probe = false; /* continued in azx_firmware_cb() */ - } -#endif /* CONFIG_SND_HDA_PATCH_LOADER */ - - if (schedule_probe) + if (!chip->disabled) schedule_delayed_work(&hda->probe_work, 0); set_bit(dev, probed_devs); @@ -2371,11 +2334,20 @@ static int azx_probe_continue(struct azx *chip) } #ifdef CONFIG_SND_HDA_PATCH_LOADER - if (chip->fw) { - err = snd_hda_load_patch(&chip->bus, chip->fw->size, - chip->fw->data); - if (err < 0) - goto out_free; + if (patch[dev] && *patch[dev]) { + const struct firmware *fw = NULL; + + dev_info(&pci->dev, "Applying patch firmware '%s'\n", + patch[dev]); + if (request_firmware(&fw, patch[dev], &pci->dev) < 0) { + dev_err(&pci->dev, + "Cannot load firmware, continue without patching\n"); + } else { + err = snd_hda_load_patch(&chip->bus, fw->size, fw->data); + release_firmware(fw); + if (err < 0) + goto out_free; + } } #endif From 3c318f97dcc50b2e0556a1813bd6958678e881fd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A1ssio=20Gabriel?= Date: Wed, 15 Apr 2026 12:04:53 -0300 Subject: [PATCH 14/41] ALSA: usb-audio: stop parsing UAC2 rates at MAX_NR_RATES MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit parse_uac2_sample_rate_range() caps the number of enumerated rates at MAX_NR_RATES, but it only breaks out of the current rate loop. A malformed UAC2 RANGE response with additional triplets continues parsing the remaining triplets and repeatedly prints "invalid uac2 rates" while probe still holds register_mutex. Stop the whole parse once the cap is reached and return the number of rates collected so far. Fixes: 4fa0e81b8350 ("ALSA: usb-audio: fix possible hang and overflow in parse_uac2_sample_rate_range()") Cc: stable@vger.kernel.org Reported-by: syzbot+d56178c27a4710960820@syzkaller.appspotmail.com Closes: https://syzkaller.appspot.com/bug?extid=d56178c27a4710960820 Signed-off-by: Cássio Gabriel Link: https://patch.msgid.link/20260415-usb-audio-uac2-rate-cap-v1-1-5ecbafc120d8@gmail.com Signed-off-by: Takashi Iwai --- sound/usb/format.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/usb/format.c b/sound/usb/format.c index 030b4307927a..4830f9f93ad7 100644 --- a/sound/usb/format.c +++ b/sound/usb/format.c @@ -470,7 +470,7 @@ static int parse_uac2_sample_rate_range(struct snd_usb_audio *chip, nr_rates++; if (nr_rates >= MAX_NR_RATES) { usb_audio_err(chip, "invalid uac2 rates\n"); - break; + return nr_rates; } skip_rate: From 37e9faf21670cf86d36eebc3b4d27afe6819983a Mon Sep 17 00:00:00 2001 From: Hsieh Hung-En Date: Wed, 15 Apr 2026 11:02:51 +0800 Subject: [PATCH 15/41] ASoC: es8311: Check regcache_sync() error in resume The es8311_resume() function currently ignores the return value of regcache_sync(). If syncing the cache fails, the function still returns 0, leaving the codec in a potentially incorrect state. Check the return value and propagate it to the ASoC core to ensure resume failures are properly handled. Signed-off-by: Hsieh Hung-En Link: https://patch.msgid.link/20260415030252.5547-2-hungen3108@gmail.com Signed-off-by: Mark Brown --- sound/soc/codecs/es8311.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/sound/soc/codecs/es8311.c b/sound/soc/codecs/es8311.c index 0b07a53cc792..9e371e2d6eae 100644 --- a/sound/soc/codecs/es8311.c +++ b/sound/soc/codecs/es8311.c @@ -862,13 +862,18 @@ static int es8311_suspend(struct snd_soc_component *component) static int es8311_resume(struct snd_soc_component *component) { struct es8311_priv *es8311; + int ret; es8311 = snd_soc_component_get_drvdata(component); es8311_reset(component, false); regcache_cache_only(es8311->regmap, false); - regcache_sync(es8311->regmap); + ret = regcache_sync(es8311->regmap); + if (ret) { + dev_err(component->dev, "unable to sync regcache\n"); + return ret; + } return 0; } From c15bc1681045f158811643d6c990f87c590dd693 Mon Sep 17 00:00:00 2001 From: Hsieh Hung-En Date: Wed, 15 Apr 2026 11:02:52 +0800 Subject: [PATCH 16/41] ASoC: es8311: Fix clock leak and check update_bits in set_bias_level() In es8311_set_bias_level(), the return value of snd_soc_component_update_bits() was ignored. If this fails, not only is the VMID selection not applied, but the previously enabled mclk is left running, leading to an unbalanced clock reference count (clock leak). Check the return value and ensure clk_disable_unprepare() is called on failure to maintain proper resource management. Signed-off-by: Hsieh Hung-En Link: https://patch.msgid.link/20260415030252.5547-3-hungen3108@gmail.com Signed-off-by: Mark Brown --- sound/soc/codecs/es8311.c | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/sound/soc/codecs/es8311.c b/sound/soc/codecs/es8311.c index 9e371e2d6eae..564af5c04dbb 100644 --- a/sound/soc/codecs/es8311.c +++ b/sound/soc/codecs/es8311.c @@ -761,6 +761,7 @@ static int es8311_set_bias_level(struct snd_soc_component *component, { struct es8311_priv *es8311 = snd_soc_component_get_drvdata(component); struct snd_soc_dapm_context *dapm = snd_soc_component_to_dapm(component); + int ret; switch (level) { case SND_SOC_BIAS_ON: @@ -769,17 +770,21 @@ static int es8311_set_bias_level(struct snd_soc_component *component, break; case SND_SOC_BIAS_STANDBY: if (snd_soc_dapm_get_bias_level(dapm) == SND_SOC_BIAS_OFF) { - int ret = clk_prepare_enable(es8311->mclk); + ret = clk_prepare_enable(es8311->mclk); if (ret) { dev_err(component->dev, "unable to prepare mclk\n"); return ret; } - snd_soc_component_update_bits( - component, ES8311_SYS3, - ES8311_SYS3_PDN_VMIDSEL_MASK, - ES8311_SYS3_PDN_VMIDSEL_STARTUP_NORMAL_SPEED); + ret = snd_soc_component_update_bits( + component, ES8311_SYS3, + ES8311_SYS3_PDN_VMIDSEL_MASK, + ES8311_SYS3_PDN_VMIDSEL_STARTUP_NORMAL_SPEED); + if (ret < 0) { + clk_disable_unprepare(es8311->mclk); + return ret; + } } break; From d1aa2b9aad696c0434a5e0ac1d07810ce264e686 Mon Sep 17 00:00:00 2001 From: Juan Pablo Fuentealba Bizama Date: Thu, 16 Apr 2026 15:11:49 -0400 Subject: [PATCH 17/41] ALSA: usb-audio: Add quirk for SmartlinkTechnology M01 Add quirk entry for SmartlinkTechnology M01 USB microphone to enable the standard mixer interface. Signed-off-by: Juan Pablo Fuentealba Bizama Link: https://patch.msgid.link/20260416191149.12088-1-jpfuentealbabizama@gmail.com Signed-off-by: Takashi Iwai --- sound/usb/quirks-table.h | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/sound/usb/quirks-table.h b/sound/usb/quirks-table.h index 803e03d4d77b..283135d880db 100644 --- a/sound/usb/quirks-table.h +++ b/sound/usb/quirks-table.h @@ -3772,6 +3772,18 @@ YAMAHA_DEVICE(0x7010, "UB99"), } } }, +{ + /* + * SmartlinkTechnology M01 + * USB audio device that needs standard mixer quirk + */ + USB_DEVICE(0x301a, 0x159b), + QUIRK_DRIVER_INFO { + .vendor_name = "SmartlinkTechnology", + .product_name = "M01", + QUIRK_DATA_STANDARD_MIXER(QUIRK_ANY_INTERFACE) + } +}, #define QUIRK_RME_DIGIFACE(pid) \ { \ /* Only claim interface 0 */ \ From 4f01559b5ec490b58e4a74cba36b43fe5f06f1ee Mon Sep 17 00:00:00 2001 From: Randy Dunlap Date: Sun, 15 Feb 2026 21:59:56 -0800 Subject: [PATCH 18/41] ALSA: virtio: drop an extaneous kernel-doc comment Drop a kernel-doc struct comment since the struct member was removed. This eliminates a kernel-doc warning when make W=1 is used. virtio_pcm.h:65: warning: Excess struct member 'msg_last_enqueued' description in 'virtio_pcm_substream' Fixes: fe981e67568c ("ALSA: virtio: use ack callback") Signed-off-by: Randy Dunlap Signed-off-by: Takashi Iwai Link: https://patch.msgid.link/20260216055956.2784399-1-rdunlap@infradead.org --- sound/virtio/virtio_pcm.h | 1 - 1 file changed, 1 deletion(-) diff --git a/sound/virtio/virtio_pcm.h b/sound/virtio/virtio_pcm.h index 5dd1b43b9493..368dafa5df3f 100644 --- a/sound/virtio/virtio_pcm.h +++ b/sound/virtio/virtio_pcm.h @@ -37,7 +37,6 @@ struct virtio_pcm_msg; * the device side at resume. * @msgs: Allocated I/O messages. * @nmsgs: Number of allocated I/O messages. - * @msg_last_enqueued: Index of the last I/O message added to the virtqueue. * @msg_count: Number of pending I/O messages in the virtqueue. * @msg_empty: Notify when msg_count is zero. */ From 2866156e770c3c00aed96de9eab35cde0fd486cd Mon Sep 17 00:00:00 2001 From: Randy Dunlap Date: Sun, 15 Feb 2026 22:00:10 -0800 Subject: [PATCH 19/41] ALSA: vx: use correct function name in kernel-doc comment Use the correct function name to avoid a kernel-doc warning (when W=1 is used): vx_cmd.h:210: warning: expecting prototype for vx_send_pipe_cmd_params(). Prototype was for vx_set_pipe_cmd_params() instead Signed-off-by: Randy Dunlap Signed-off-by: Takashi Iwai Link: https://patch.msgid.link/20260216060010.2784438-1-rdunlap@infradead.org --- sound/drivers/vx/vx_cmd.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/drivers/vx/vx_cmd.h b/sound/drivers/vx/vx_cmd.h index c2a520274493..1fc70c98f041 100644 --- a/sound/drivers/vx/vx_cmd.h +++ b/sound/drivers/vx/vx_cmd.h @@ -199,7 +199,7 @@ struct vx_cmd_info { void vx_init_rmh(struct vx_rmh *rmh, unsigned int cmd); /** - * vx_send_pipe_cmd_params - fill first command word for pipe commands + * vx_set_pipe_cmd_params - fill first command word for pipe commands * @rmh: the rmh to be modified * @is_capture: 0 = playback, 1 = capture operation * @param1: first pipe-parameter From 17bc5dd49214b50c9eb6df0fad1d1aea287dd078 Mon Sep 17 00:00:00 2001 From: Johnathan Penberthy Date: Thu, 16 Apr 2026 19:01:23 -0600 Subject: [PATCH 20/41] ALSA: usb-audio: Add quirk entries for NexiGo N930W webcam The NexiGo N930W 60fps webcam (USB ID 3443:930d) hits the same 'cannot get freq at ep 0x84' error in snd-usb-audio as its sibling N930AF (1bcf:2283). Without QUIRK_FLAG_GET_SAMPLE_RATE the ADC clock is never configured and the microphone streams only zero samples. Testing on Linux 6.17 with QUIRK_FLAG_GET_SAMPLE_RATE | QUIRK_FLAG_MIC_RES_16 (via quirk_alias=3443930d:1bcf2283) confirmed the microphone captures real audio after a cold USB re-enumeration. Adding a native quirk_flags_table entry avoids the alias workaround. Signed-off-by: Johnathan Penberthy Link: https://patch.msgid.link/20260417010123.3080904-1-johnathan.penberthy@gmail.com Signed-off-by: Takashi Iwai --- sound/usb/quirks.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/sound/usb/quirks.c b/sound/usb/quirks.c index 8fc36d1cfb9d..7b803ad58487 100644 --- a/sound/usb/quirks.c +++ b/sound/usb/quirks.c @@ -2474,6 +2474,8 @@ static const struct usb_audio_quirk_flags_table quirk_flags_table[] = { QUIRK_FLAG_ITF_USB_DSD_DAC | QUIRK_FLAG_CTL_MSG_DELAY), DEVICE_FLG(0x339b, 0x3a07, /* Synaptics HONOR USB-C HEADSET */ QUIRK_FLAG_MIXER_PLAYBACK_MIN_MUTE), + DEVICE_FLG(0x3443, 0x930d, /* NexiGo N930W 60fps Webcam */ + QUIRK_FLAG_GET_SAMPLE_RATE | QUIRK_FLAG_MIC_RES_16), DEVICE_FLG(0x413c, 0xa506, /* Dell AE515 sound bar */ QUIRK_FLAG_GET_SAMPLE_RATE), DEVICE_FLG(0x534d, 0x0021, /* MacroSilicon MS2100/MS2106 */ From dc88eef8f55e85e92d016cdf7e291f5560efd79b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A1ssio=20Gabriel?= Date: Thu, 16 Apr 2026 10:24:40 -0300 Subject: [PATCH 21/41] ALSA: 6fire: Fix input volume change detection MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit usb6fire_control_input_vol_put() stores the analog capture volume as a signed offset in rt->input_vol[] (-15..+15), but it compares the cached value against the user-visible mixer value (0..30) before subtracting 15. This mixes two domains in the change detection path. Since the runtime is zero-initialized, the visible default is 15; writing 0 right after probe is ignored, while writing 15 is reported as a change even though the cached value remains 0. Normalize the user value before comparing it with the cached offset. Fixes: 06bb4e743501 ("ALSA: snd-usb-6fire: add analog input volume control") Cc: stable@vger.kernel.org Signed-off-by: Cássio Gabriel Link: https://patch.msgid.link/20260416-alsa-6fire-input-volume-change-detection-v1-1-ec78299168df@gmail.com Signed-off-by: Takashi Iwai --- sound/usb/6fire/control.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/sound/usb/6fire/control.c b/sound/usb/6fire/control.c index dd25a6407b63..c77a21a9acd7 100644 --- a/sound/usb/6fire/control.c +++ b/sound/usb/6fire/control.c @@ -290,15 +290,17 @@ static int usb6fire_control_input_vol_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { struct control_runtime *rt = snd_kcontrol_chip(kcontrol); + int vol0 = ucontrol->value.integer.value[0] - 15; + int vol1 = ucontrol->value.integer.value[1] - 15; int changed = 0; - if (rt->input_vol[0] != ucontrol->value.integer.value[0]) { - rt->input_vol[0] = ucontrol->value.integer.value[0] - 15; + if (rt->input_vol[0] != vol0) { + rt->input_vol[0] = vol0; rt->ivol_updated &= ~(1 << 0); changed = 1; } - if (rt->input_vol[1] != ucontrol->value.integer.value[1]) { - rt->input_vol[1] = ucontrol->value.integer.value[1] - 15; + if (rt->input_vol[1] != vol1) { + rt->input_vol[1] = vol1; rt->ivol_updated &= ~(1 << 1); changed = 1; } From 4ff036f95238f02c87e5d7c0a9d93748582a8950 Mon Sep 17 00:00:00 2001 From: Guangshuo Li Date: Thu, 16 Apr 2026 03:31:38 +0800 Subject: [PATCH 22/41] ALSA: pcmtest: fix reference leak on failed device registration When platform_device_register() fails in mod_init(), the embedded struct device in pcmtst_pdev has already been initialized by device_initialize(), but the failure path returns the error without dropping the device reference for the current platform device: mod_init() -> platform_device_register(&pcmtst_pdev) -> device_initialize(&pcmtst_pdev.dev) -> setup_pdev_dma_masks(&pcmtst_pdev) -> platform_device_add(&pcmtst_pdev) This leads to a reference leak when platform_device_register() fails. Fix this by calling platform_device_put() before returning the error. The issue was identified by a static analysis tool I developed and confirmed by manual review. Fixes: 315a3d57c64c5 ("ALSA: Implement the new Virtual PCM Test Driver") Cc: stable@vger.kernel.org Signed-off-by: Guangshuo Li Link: https://patch.msgid.link/20260415193138.3861297-1-lgs201920130244@gmail.com Signed-off-by: Takashi Iwai --- sound/drivers/pcmtest.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/sound/drivers/pcmtest.c b/sound/drivers/pcmtest.c index 768bb698adfb..20ceb9082fa9 100644 --- a/sound/drivers/pcmtest.c +++ b/sound/drivers/pcmtest.c @@ -756,8 +756,10 @@ static int __init mod_init(void) if (err) return err; err = platform_device_register(&pcmtst_pdev); - if (err) + if (err) { + platform_device_put(&pcmtst_pdev); return err; + } err = platform_driver_register(&pcmtst_pdrv); if (err) platform_device_unregister(&pcmtst_pdev); From a3542d1b30f92307f545f2def14e8d988dffdff0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A1ssio=20Gabriel?= Date: Fri, 17 Apr 2026 10:41:33 -0300 Subject: [PATCH 23/41] ALSA: caiaq: Fix control_put() result and cache rollback MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit control_put() always returns 1 and updates cdev->control_state[] before sending the USB command. It also ignores transport errors from usb_bulk_msg(), snd_usb_caiaq_send_command(), and snd_usb_caiaq_send_command_bank(). That breaks the ALSA .put() contract and can leave control_get() reporting a cached value the device never accepted. Return 0 for unchanged values, propagate transport failures, and restore the cached byte when the write fails. Fixes: 8e3cd08ed8e59 ("[ALSA] caiaq - add control API and more input features") Cc: stable@vger.kernel.org Signed-off-by: Cássio Gabriel Link: https://patch.msgid.link/20260417-caiaq-control-put-v1-1-c37826e92447@gmail.com Signed-off-by: Takashi Iwai --- sound/usb/caiaq/control.c | 52 +++++++++++++++++++++++++++------------ 1 file changed, 36 insertions(+), 16 deletions(-) diff --git a/sound/usb/caiaq/control.c b/sound/usb/caiaq/control.c index af459c49baf4..4598fb7e8be0 100644 --- a/sound/usb/caiaq/control.c +++ b/sound/usb/caiaq/control.c @@ -87,6 +87,7 @@ static int control_put(struct snd_kcontrol *kcontrol, struct snd_usb_caiaqdev *cdev = caiaqdev(chip->card); int pos = kcontrol->private_value; int v = ucontrol->value.integer.value[0]; + int ret; unsigned char cmd; switch (cdev->chip.usb_id) { @@ -103,6 +104,10 @@ static int control_put(struct snd_kcontrol *kcontrol, if (pos & CNT_INTVAL) { int i = pos & ~CNT_INTVAL; + unsigned char old = cdev->control_state[i]; + + if (old == v) + return 0; cdev->control_state[i] = v; @@ -113,10 +118,11 @@ static int control_put(struct snd_kcontrol *kcontrol, cdev->ep8_out_buf[0] = i; cdev->ep8_out_buf[1] = v; - usb_bulk_msg(cdev->chip.dev, - usb_sndbulkpipe(cdev->chip.dev, 8), - cdev->ep8_out_buf, sizeof(cdev->ep8_out_buf), - &actual_len, 200); + ret = usb_bulk_msg(cdev->chip.dev, + usb_sndbulkpipe(cdev->chip.dev, 8), + cdev->ep8_out_buf, + sizeof(cdev->ep8_out_buf), + &actual_len, 200); } else if (cdev->chip.usb_id == USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_MASCHINECONTROLLER)) { @@ -128,21 +134,36 @@ static int control_put(struct snd_kcontrol *kcontrol, offset = MASCHINE_BANK_SIZE; } - snd_usb_caiaq_send_command_bank(cdev, cmd, bank, - cdev->control_state + offset, - MASCHINE_BANK_SIZE); + ret = snd_usb_caiaq_send_command_bank(cdev, cmd, bank, + cdev->control_state + offset, + MASCHINE_BANK_SIZE); } else { - snd_usb_caiaq_send_command(cdev, cmd, - cdev->control_state, sizeof(cdev->control_state)); + ret = snd_usb_caiaq_send_command(cdev, cmd, + cdev->control_state, + sizeof(cdev->control_state)); + } + + if (ret < 0) { + cdev->control_state[i] = old; + return ret; } } else { - if (v) - cdev->control_state[pos / 8] |= 1 << (pos % 8); - else - cdev->control_state[pos / 8] &= ~(1 << (pos % 8)); + int idx = pos / 8; + unsigned char mask = 1 << (pos % 8); + unsigned char old = cdev->control_state[idx]; + unsigned char val = v ? (old | mask) : (old & ~mask); - snd_usb_caiaq_send_command(cdev, cmd, - cdev->control_state, sizeof(cdev->control_state)); + if (old == val) + return 0; + + cdev->control_state[idx] = val; + ret = snd_usb_caiaq_send_command(cdev, cmd, + cdev->control_state, + sizeof(cdev->control_state)); + if (ret < 0) { + cdev->control_state[idx] = old; + return ret; + } } return 1; @@ -640,4 +661,3 @@ int snd_usb_caiaq_control_init(struct snd_usb_caiaqdev *cdev) return ret; } - From 8a7be65e7e9a95c7776f997b50a4893c9315e710 Mon Sep 17 00:00:00 2001 From: Bob Song Date: Mon, 20 Apr 2026 13:33:51 +0800 Subject: [PATCH 24/41] ALSA: hda/realtek: add quirk for Acer Nitro 16 AN16-41 The combo jack microphone is not detected/working on the laptop featuring the Realtek ALC245 codec, and mic pincfg is the default value. So here, add quirk for it and test good. Reported-by: Yenilmez99 Closes: https://bugzilla.kernel.org/show_bug.cgi?id=221344 Signed-off-by: Bob Song Signed-off-by: Takashi Iwai Link: https://patch.msgid.link/20260420053351.547352-1-songxiebing@kylinos.cn --- 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 a10a6969471a..4b6266536ee2 100644 --- a/sound/hda/codecs/realtek/alc269.c +++ b/sound/hda/codecs/realtek/alc269.c @@ -6717,6 +6717,7 @@ static const struct hda_quirk alc269_fixup_tbl[] = { SND_PCI_QUIRK(0x1025, 0x159c, "Acer Nitro 5 AN515-58", ALC2XX_FIXUP_HEADSET_MIC), SND_PCI_QUIRK(0x1025, 0x1597, "Acer Nitro 5 AN517-55", ALC2XX_FIXUP_HEADSET_MIC), SND_PCI_QUIRK(0x1025, 0x160e, "Acer PT316-51S", ALC2XX_FIXUP_HEADSET_MIC), + SND_PCI_QUIRK(0x1025, 0x1679, "Acer Nitro 16 AN16-41", ALC2XX_FIXUP_HEADSET_MIC), SND_PCI_QUIRK(0x1025, 0x169a, "Acer Swift SFG16", ALC256_FIXUP_ACER_SFG16_MICMUTE_LED), SND_PCI_QUIRK(0x1025, 0x171e, "Acer Nitro ANV15-51", ALC245_FIXUP_ACER_MICMUTE_LED), SND_PCI_QUIRK(0x1025, 0x173a, "Acer Swift SFG14-73", ALC245_FIXUP_ACER_MICMUTE_LED), From 93985110329d9a66101c3de37aa7232f8c0bc3c9 Mon Sep 17 00:00:00 2001 From: Baojun Xu Date: Sat, 18 Apr 2026 13:50:30 +0800 Subject: [PATCH 25/41] ALSA: hda/tas2781: Fix sound abnormal issue on some SPI device In the SPI driver probe, the chip ID must be set to TAS2781. Without this initialization, calibration data fails to load correctly, causing audio abnormalities on some devices. And update the register bulk read API to handle the distinct requirements of SPI and I2C devices. Fixes: 05ac3846ffe5 ("ALSA: hda/tas2781: A workaround solution to lower-vol issue among lower calibrated-impedance micro-speaker on TAS2781") Signed-off-by: Baojun Xu Link: https://patch.msgid.link/20260418055030.765-1-baojun.xu@ti.com Signed-off-by: Takashi Iwai --- sound/hda/codecs/side-codecs/tas2781_hda_spi.c | 1 + sound/soc/codecs/tas2781-fmwlib.c | 7 +++---- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/sound/hda/codecs/side-codecs/tas2781_hda_spi.c b/sound/hda/codecs/side-codecs/tas2781_hda_spi.c index f860e0eb7602..560f2385212d 100644 --- a/sound/hda/codecs/side-codecs/tas2781_hda_spi.c +++ b/sound/hda/codecs/side-codecs/tas2781_hda_spi.c @@ -788,6 +788,7 @@ static int tas2781_hda_spi_probe(struct spi_device *spi) } if (strstr(dev_name(&spi->dev), "TXNW2781")) { device_name = "TXNW2781"; + tas_hda->priv->chip_id = TAS2781; } else { dev_err(tas_priv->dev, "Unmatched spi dev %s\n", dev_name(&spi->dev)); diff --git a/sound/soc/codecs/tas2781-fmwlib.c b/sound/soc/codecs/tas2781-fmwlib.c index a1d86bd309f4..885e0b6fed00 100644 --- a/sound/soc/codecs/tas2781-fmwlib.c +++ b/sound/soc/codecs/tas2781-fmwlib.c @@ -2487,7 +2487,7 @@ static int tas2781_cali_preproc(struct tasdevice_priv *priv, int i) if (spec == NULL) return -ENOMEM; priv->tasdevice[i].cali_specific = spec; - rc = tasdevice_dev_bulk_read(priv, i, p->r0_reg, r0_deflt, 4); + rc = priv->dev_bulk_read(priv, i, p->r0_reg, r0_deflt, 4); if (rc < 0) { dev_err(priv->dev, "invalid RE from %d = %d\n", i, rc); return rc; @@ -2511,9 +2511,8 @@ static int tas2781_cali_preproc(struct tasdevice_priv *priv, int i) TASDEVICE_REG(0, 0x1b, 0x34) : TASDEVICE_REG(0, 0x18, 0x1c); - rc = tasdevice_dev_bulk_read(priv, i, - spec->sin_gni_reg, - spec->sin_gni, 4); + rc = priv->dev_bulk_read(priv, i, spec->sin_gni_reg, + spec->sin_gni, 4); if (rc < 0) { dev_err(priv->dev, "wrong sinegaini %d = %d\n", i, rc); From 8146cd333d235ed32d48bb803fdf743472d7c783 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Mon, 20 Apr 2026 08:17:20 +0200 Subject: [PATCH 26/41] ALSA: core: Fix potential data race at fasync handling In snd_fasync_work_fn(), which is the offload work for traversing and processing the pending fasync list, the call of kill_fasync() is done outside the snd_fasync_lock for avoiding deadlocks. The problem is that its the references of fasync->on, fasync->signal and fasync->poll are done there also outside the lock. Since these may be modified by snd_kill_fasync() call concurrently from other process, inconsistent values might be passed to kill_fasync(). Although there shouldn't be critical UAF, it's still better to be addressed. This patch moves the kill_fasync() argument evaluations inside the snd_fasync_lock for avoiding the data races above. The handling in fasync->on flag is optimized in the loop to skip directly. Also, for more clarity, snd_fasync_free() takes the lock and unlink the pending entry more directly instead of clearing fasync->on flag. Reported-by: Jake Lamberson Fixes: ef34a0ae7a26 ("ALSA: core: Add async signal helpers") Cc: Link: https://patch.msgid.link/20260420061721.3253644-1-tiwai@suse.de Signed-off-by: Takashi Iwai --- sound/core/misc.c | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/sound/core/misc.c b/sound/core/misc.c index 88d9e1f9a6e9..5aca09edf971 100644 --- a/sound/core/misc.c +++ b/sound/core/misc.c @@ -100,14 +100,18 @@ static LIST_HEAD(snd_fasync_list); static void snd_fasync_work_fn(struct work_struct *work) { struct snd_fasync *fasync; + int signal, poll; spin_lock_irq(&snd_fasync_lock); while (!list_empty(&snd_fasync_list)) { fasync = list_first_entry(&snd_fasync_list, struct snd_fasync, list); list_del_init(&fasync->list); + if (!fasync->on) + continue; + signal = fasync->signal; + poll = fasync->poll; spin_unlock_irq(&snd_fasync_lock); - if (fasync->on) - kill_fasync(&fasync->fasync, fasync->signal, fasync->poll); + kill_fasync(&fasync->fasync, signal, poll); spin_lock_irq(&snd_fasync_lock); } spin_unlock_irq(&snd_fasync_lock); @@ -158,7 +162,10 @@ void snd_fasync_free(struct snd_fasync *fasync) { if (!fasync) return; - fasync->on = 0; + + scoped_guard(spinlock_irq, &snd_fasync_lock) + list_del_init(&fasync->list); + flush_work(&snd_fasync_work); kfree(fasync); } From 4cc3ec3d8b3536f2293a5a984c28ba2a09e8b22d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A1ssio=20Gabriel?= Date: Fri, 17 Apr 2026 17:30:18 -0300 Subject: [PATCH 27/41] ALSA: als4000: Fix capture trigger chip->mode race MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit snd_als4000_capture_trigger() updates chip->mode under mixer_lock, while snd_als4000_set_rate() and snd_als4000_playback_trigger() serialize the same rate-lock state with reg_lock. The PCM core serializes callbacks only per acted-on substream, or for an explicitly linked group, so unlinked playback and capture streams can run concurrently. That leaves two races on ALS4000 rate-lock state: - playback and capture trigger callbacks can concurrently update chip->mode and lose one of the SB_RATE_LOCK bits - snd_als4000_set_rate() can observe chip->mode without the capture lock bit set and reprogram the shared sample rate while capture is being started Fix this by taking reg_lock as the outer lock in snd_als4000_capture_trigger() and nesting mixer_lock only for the CR1E write. This keeps chip->mode serialized with the rest of the ALS4000 rate-lock users while preserving the existing CR1E programming sequence. Signed-off-by: Cássio Gabriel Link: https://patch.msgid.link/20260417-als4000-capture-trigger-race-v1-1-daeffc2feb67@gmail.com Signed-off-by: Takashi Iwai --- sound/pci/als4000.c | 44 ++++++++++++++++++++------------------------ 1 file changed, 20 insertions(+), 24 deletions(-) diff --git a/sound/pci/als4000.c b/sound/pci/als4000.c index 33034e07b3d6..636f309c9424 100644 --- a/sound/pci/als4000.c +++ b/sound/pci/als4000.c @@ -421,30 +421,26 @@ static int snd_als4000_capture_trigger(struct snd_pcm_substream *substream, int { struct snd_sb *chip = snd_pcm_substream_chip(substream); int result = 0; - - /* FIXME race condition in here!!! - chip->mode non-atomic update gets consistently protected - by reg_lock always, _except_ for this place!! - Probably need to take reg_lock as outer (or inner??) lock, too. - (or serialize both lock operations? probably not, though... - racy?) - */ - guard(spinlock)(&chip->mixer_lock); - switch (cmd) { - case SNDRV_PCM_TRIGGER_START: - case SNDRV_PCM_TRIGGER_RESUME: - chip->mode |= SB_RATE_LOCK_CAPTURE; - snd_als4_cr_write(chip, ALS4K_CR1E_FIFO2_CONTROL, - capture_cmd(chip)); - break; - case SNDRV_PCM_TRIGGER_STOP: - case SNDRV_PCM_TRIGGER_SUSPEND: - chip->mode &= ~SB_RATE_LOCK_CAPTURE; - snd_als4_cr_write(chip, ALS4K_CR1E_FIFO2_CONTROL, - capture_cmd(chip)); - break; - default: - result = -EINVAL; - break; + + guard(spinlock)(&chip->reg_lock); + scoped_guard(spinlock, &chip->mixer_lock) { + switch (cmd) { + case SNDRV_PCM_TRIGGER_START: + case SNDRV_PCM_TRIGGER_RESUME: + chip->mode |= SB_RATE_LOCK_CAPTURE; + snd_als4_cr_write(chip, ALS4K_CR1E_FIFO2_CONTROL, + capture_cmd(chip)); + break; + case SNDRV_PCM_TRIGGER_STOP: + case SNDRV_PCM_TRIGGER_SUSPEND: + chip->mode &= ~SB_RATE_LOCK_CAPTURE; + snd_als4_cr_write(chip, ALS4K_CR1E_FIFO2_CONTROL, + capture_cmd(chip)); + break; + default: + result = -EINVAL; + break; + } } return result; } From 314665e67b3e27ff442d8e0879f1c1df8d63ccbd Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Mon, 20 Apr 2026 18:00:13 +0200 Subject: [PATCH 28/41] Revert "ALSA: usb-audio: Add quirk for SmartlinkTechnology M01" This reverts commit d1aa2b9aad696c0434a5e0ac1d07810ce264e686. Juan reported that the patch didn't work as expected at the later check, failing to create PCM capture devices that has worked beforehand. Drop the change again for addressing the regression, and we'll continue developing a proper fix later. Reported-by: Juan Pablo Fuentealba Bizama Closes: https://lore.kernel.org/20260417150748.6684-1-jpfuentealbabizama@gmail.com Signed-off-by: Takashi Iwai --- sound/usb/quirks-table.h | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/sound/usb/quirks-table.h b/sound/usb/quirks-table.h index 283135d880db..803e03d4d77b 100644 --- a/sound/usb/quirks-table.h +++ b/sound/usb/quirks-table.h @@ -3772,18 +3772,6 @@ YAMAHA_DEVICE(0x7010, "UB99"), } } }, -{ - /* - * SmartlinkTechnology M01 - * USB audio device that needs standard mixer quirk - */ - USB_DEVICE(0x301a, 0x159b), - QUIRK_DRIVER_INFO { - .vendor_name = "SmartlinkTechnology", - .product_name = "M01", - QUIRK_DATA_STANDARD_MIXER(QUIRK_ANY_INTERFACE) - } -}, #define QUIRK_RME_DIGIFACE(pid) \ { \ /* Only claim interface 0 */ \ From ca1b11b36d8231a748c77e4732e40de9998fa9d8 Mon Sep 17 00:00:00 2001 From: Charles Keepax Date: Mon, 13 Apr 2026 13:46:20 +0100 Subject: [PATCH 29/41] regmap: sdw-mbq: Allow defers on undeferrable controls It is a fairly common DisCo issue to have the deferrability of controls marked incorrectly and Windows seems very permissive in this regard. As there isn't really any down side to trying a defer even if the control isn't deferrable, allow this but add a warning message. Signed-off-by: Charles Keepax Link: https://patch.msgid.link/20260413124621.1345315-2-ckeepax@opensource.cirrus.com Signed-off-by: Mark Brown --- drivers/base/regmap/regmap-sdw-mbq.c | 36 ++++++++++++++-------------- 1 file changed, 18 insertions(+), 18 deletions(-) diff --git a/drivers/base/regmap/regmap-sdw-mbq.c b/drivers/base/regmap/regmap-sdw-mbq.c index 6a61629f5f89..4533fe793c5f 100644 --- a/drivers/base/regmap/regmap-sdw-mbq.c +++ b/drivers/base/regmap/regmap-sdw-mbq.c @@ -74,7 +74,7 @@ static int regmap_sdw_mbq_poll_busy(struct sdw_slave *slave, unsigned int reg, static int regmap_sdw_mbq_write_impl(struct sdw_slave *slave, unsigned int reg, unsigned int val, - int mbq_size, bool deferrable) + int mbq_size) { int shift = mbq_size * BITS_PER_BYTE; int ret; @@ -88,17 +88,14 @@ static int regmap_sdw_mbq_write_impl(struct sdw_slave *slave, return ret; } - ret = sdw_write_no_pm(slave, reg, val & 0xff); - if (deferrable && ret == -ENODATA) - return -EAGAIN; - - return ret; + return sdw_write_no_pm(slave, reg, val & 0xff); } static int regmap_sdw_mbq_write(void *context, unsigned int reg, unsigned int val) { struct regmap_mbq_context *ctx = context; struct sdw_slave *slave = ctx->sdw; + struct device *dev = ctx->dev; bool deferrable = regmap_sdw_mbq_deferrable(ctx, reg); int mbq_size = regmap_sdw_mbq_size(ctx, reg); int ret; @@ -113,13 +110,16 @@ static int regmap_sdw_mbq_write(void *context, unsigned int reg, unsigned int va * process a single wait/timeout on function busy and a single retry * of the transaction. */ - ret = regmap_sdw_mbq_write_impl(slave, reg, val, mbq_size, deferrable); - if (ret == -EAGAIN) { + ret = regmap_sdw_mbq_write_impl(slave, reg, val, mbq_size); + if (ret == -ENODATA) { + if (!deferrable) + dev_warn(dev, "Defer on undeferrable control: %x\n", reg); + ret = regmap_sdw_mbq_poll_busy(slave, reg, ctx); if (ret) return ret; - ret = regmap_sdw_mbq_write_impl(slave, reg, val, mbq_size, false); + ret = regmap_sdw_mbq_write_impl(slave, reg, val, mbq_size); } return ret; @@ -127,18 +127,14 @@ static int regmap_sdw_mbq_write(void *context, unsigned int reg, unsigned int va static int regmap_sdw_mbq_read_impl(struct sdw_slave *slave, unsigned int reg, unsigned int *val, - int mbq_size, bool deferrable) + int mbq_size) { int shift = BITS_PER_BYTE; int read; read = sdw_read_no_pm(slave, reg); - if (read < 0) { - if (deferrable && read == -ENODATA) - return -EAGAIN; - + if (read < 0) return read; - } *val = read; @@ -158,6 +154,7 @@ static int regmap_sdw_mbq_read(void *context, unsigned int reg, unsigned int *va { struct regmap_mbq_context *ctx = context; struct sdw_slave *slave = ctx->sdw; + struct device *dev = ctx->dev; bool deferrable = regmap_sdw_mbq_deferrable(ctx, reg); int mbq_size = regmap_sdw_mbq_size(ctx, reg); int ret; @@ -172,13 +169,16 @@ static int regmap_sdw_mbq_read(void *context, unsigned int reg, unsigned int *va * process a single wait/timeout on function busy and a single retry * of the transaction. */ - ret = regmap_sdw_mbq_read_impl(slave, reg, val, mbq_size, deferrable); - if (ret == -EAGAIN) { + ret = regmap_sdw_mbq_read_impl(slave, reg, val, mbq_size); + if (ret == -ENODATA) { + if (!deferrable) + dev_warn(dev, "Defer on undeferable control: %x\n", reg); + ret = regmap_sdw_mbq_poll_busy(slave, reg, ctx); if (ret) return ret; - ret = regmap_sdw_mbq_read_impl(slave, reg, val, mbq_size, false); + ret = regmap_sdw_mbq_read_impl(slave, reg, val, mbq_size); } return ret; From 956c032be7ca3f440d4786ea37e941bf862bb170 Mon Sep 17 00:00:00 2001 From: Charles Keepax Date: Mon, 13 Apr 2026 13:46:21 +0100 Subject: [PATCH 30/41] ASoC: SDCA: Fix reading of mipi-sdca-control-deferrable The discussion in [1] highlighted that the SDCA code shouldn't be using fwnode_property_read_bool() for DisCo controls, as the spec allows setting the value to zero meaning the property should not be used. Correct a small bug in the SDCA code that will mark such controls as deferrable. Link: https://lore.kernel.org/linux-sound/20260311142153.2201761-1-rf@opensource.cirrus.com/ [1] Fixes: 42b144cb6a2d ("ASoC: SDCA: Add SDCA Control parsing") Signed-off-by: Charles Keepax Link: https://patch.msgid.link/20260413124621.1345315-3-ckeepax@opensource.cirrus.com Signed-off-by: Mark Brown --- sound/soc/sdca/sdca_functions.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/sound/soc/sdca/sdca_functions.c b/sound/soc/sdca/sdca_functions.c index dca60ee8e62c..c5fe1a471c36 100644 --- a/sound/soc/sdca/sdca_functions.c +++ b/sound/soc/sdca/sdca_functions.c @@ -1006,8 +1006,11 @@ static int find_sdca_entity_control(struct device *dev, struct sdca_entity *enti control->has_fixed = true; fallthrough; case SDCA_ACCESS_MODE_RO: - control->deferrable = fwnode_property_read_bool(control_node, - "mipi-sdca-control-deferrable"); + ret = fwnode_property_read_u32(control_node, + "mipi-sdca-control-deferrable", + &tmp); + if (ret == 0) + control->deferrable = !!tmp; break; default: break; From cb78517e60cf4829c7ddaae6a21a8bdf8c9da0e4 Mon Sep 17 00:00:00 2001 From: Chris Chiu Date: Tue, 21 Apr 2026 02:34:28 +0000 Subject: [PATCH 31/41] ALSA: hda/realtek: Add LED fixup for HP EliteBook 6 G2a Laptops The HP EliteBook 6 G2a laptops requires specific LED control method ALC236_FIXUP_HP_MUTE_LED_MICMUTE_VREF to work. Signed-off-by: Chris Chiu Link: https://patch.msgid.link/20260421023429.3723154-1-chris.chiu@canonical.com Signed-off-by: Takashi Iwai --- sound/hda/codecs/realtek/alc269.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/sound/hda/codecs/realtek/alc269.c b/sound/hda/codecs/realtek/alc269.c index 4b6266536ee2..8087eaaf1408 100644 --- a/sound/hda/codecs/realtek/alc269.c +++ b/sound/hda/codecs/realtek/alc269.c @@ -7226,6 +7226,8 @@ static const struct hda_quirk alc269_fixup_tbl[] = { SND_PCI_QUIRK(0x103c, 0x8f0e, "HP ZBook X G2i 16W", ALC236_FIXUP_HP_GPIO_LED), SND_PCI_QUIRK(0x103c, 0x8f2d, "HP Auster 14", ALC287_FIXUP_CS35L41_I2C_2), SND_PCI_QUIRK(0x103c, 0x8f2e, "HP Auster 14", ALC287_FIXUP_CS35L41_I2C_2), + SND_PCI_QUIRK(0x103c, 0x8f3c, "HP EliteBook 6 G2a", ALC236_FIXUP_HP_MUTE_LED_MICMUTE_VREF), + SND_PCI_QUIRK(0x103c, 0x8f3d, "HP EliteBook 6 G2a", ALC236_FIXUP_HP_MUTE_LED_MICMUTE_VREF), SND_PCI_QUIRK(0x103c, 0x8f40, "HP ZBook 8 G2a 14", ALC245_FIXUP_HP_TAS2781_I2C_MUTE_LED), SND_PCI_QUIRK(0x103c, 0x8f41, "HP ZBook 8 G2a 16", ALC245_FIXUP_HP_TAS2781_I2C_MUTE_LED), SND_PCI_QUIRK(0x103c, 0x8f42, "HP ZBook 8 G2a 14W", ALC245_FIXUP_HP_TAS2781_I2C_MUTE_LED), From 12c1c672d46dba62bad1293977780c98e29315b4 Mon Sep 17 00:00:00 2001 From: Phil Willoughby Date: Mon, 20 Apr 2026 16:23:49 +0100 Subject: [PATCH 32/41] ALSA: usb-audio/line6: Add support for POD HD PRO The POD HD PRO is the rackmount version of the POD 500, with most of the same behaviors. As with some of the other rackmount POD devices it will not send captured audio to the host unless the host is sending playback audio, so it has LINE6_CAP_IN_NEEDS_OUT in addition to the POD 500 flags. Tested-By: Phil Willoughby Signed-off-by: Phil Willoughby Link: https://patch.msgid.link/20260420152405.7230-1-willerz@gmail.com Signed-off-by: Takashi Iwai --- sound/usb/line6/podhd.c | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/sound/usb/line6/podhd.c b/sound/usb/line6/podhd.c index ea1324c22f46..841b64479252 100644 --- a/sound/usb/line6/podhd.c +++ b/sound/usb/line6/podhd.c @@ -28,6 +28,7 @@ enum { LINE6_PODHD500X, LINE6_PODHDDESKTOP, LINE6_PODHDPROX, + LINE6_PODHDPRO, }; struct usb_line6_podhd { @@ -442,6 +443,7 @@ static const struct usb_device_id podhd_id_table[] = { { LINE6_IF_NUM(0x4159, 0), .driver_info = LINE6_PODHD500X }, { LINE6_IF_NUM(0x4156, 0), .driver_info = LINE6_PODHDDESKTOP }, { LINE6_IF_NUM(0x415A, 0), .driver_info = LINE6_PODHDPROX }, + { LINE6_IF_NUM(0x4157, 0), .driver_info = LINE6_PODHDPRO }, {} }; @@ -542,6 +544,18 @@ static const struct line6_properties podhd_properties_table[] = { .ep_audio_r = 0x86, .ep_audio_w = 0x02, }, + [LINE6_PODHDPRO] = { + .id = "PODHDPRO", + .name = "POD HD PRO", + .capabilities = LINE6_CAP_PCM | LINE6_CAP_CONTROL + | LINE6_CAP_HWMON | LINE6_CAP_HWMON_CTL | LINE6_CAP_IN_NEEDS_OUT, + .altsetting = 1, + .ctrl_if = 1, + .ep_ctrl_r = 0x81, + .ep_ctrl_w = 0x01, + .ep_audio_r = 0x86, + .ep_audio_w = 0x02, + }, }; /* From d5d5f80416a3a749906c04d56575e2290792654b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A1ssio=20Gabriel?= Date: Tue, 21 Apr 2026 10:03:06 -0300 Subject: [PATCH 33/41] ALSA: pcmtest: Fix resource leaks in module init error paths MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit pcmtest allocates its pattern buffers and creates its debugfs tree before registering the platform device and driver, but mod_init() does not release those resources when a later init step fails. As a result, a debugfs directory creation failure leaks the pattern buffers, while platform_device_register() and platform_driver_register() failures leave both the pattern buffers and the debugfs tree behind. The recent fix for failed device registration only dropped the embedded device reference. Add the missing cleanup for the debugfs tree and pattern buffers in the remaining module init error paths. Fixes: 315a3d57c64c ("ALSA: Implement the new Virtual PCM Test Driver") Cc: stable@vger.kernel.org Signed-off-by: Cássio Gabriel Link: https://patch.msgid.link/20260421-alsa-pcmtest-init-unwind-v1-1-03fe0c423dbb@gmail.com Signed-off-by: Takashi Iwai --- sound/drivers/pcmtest.c | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/sound/drivers/pcmtest.c b/sound/drivers/pcmtest.c index 20ceb9082fa9..fe31ff1e5b3c 100644 --- a/sound/drivers/pcmtest.c +++ b/sound/drivers/pcmtest.c @@ -754,15 +754,24 @@ static int __init mod_init(void) err = init_debug_files(buf_allocated); if (err) - return err; + goto err_free_patterns; err = platform_device_register(&pcmtst_pdev); if (err) { platform_device_put(&pcmtst_pdev); - return err; + goto err_clear_debug; } err = platform_driver_register(&pcmtst_pdrv); - if (err) + if (err) { platform_device_unregister(&pcmtst_pdev); + goto err_clear_debug; + } + + return 0; + +err_clear_debug: + clear_debug_files(); +err_free_patterns: + free_pattern_buffers(); return err; } From eacda758e3c01db98b5c231f56cf9a6e05ced75c Mon Sep 17 00:00:00 2001 From: Spencer Payton Date: Tue, 21 Apr 2026 10:49:18 +0200 Subject: [PATCH 34/41] ALSA: hda/realtek - Add mute LED support for HP Victus 15-fa2xxx The mute LED on this laptop uses ALC245 but requires a quirk to work. This patch enables the existing ALC245_FIXUP_HP_MUTE_LED_COEFBIT quirk for the device. Tested my Victus 15-fa2xxx (PCI SSID 103c:8dcd). The LED behaviour works as intended. Cc: stable@vger.kernel.org Signed-off-by: Spencer Payton Link: https://patch.msgid.link/20260421084918.14685-1-spayton681@gmail.com 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 8087eaaf1408..d720565db4aa 100644 --- a/sound/hda/codecs/realtek/alc269.c +++ b/sound/hda/codecs/realtek/alc269.c @@ -7154,6 +7154,7 @@ static const struct hda_quirk alc269_fixup_tbl[] = { SND_PCI_QUIRK(0x103c, 0x8d90, "HP EliteBook 16 G12", ALC285_FIXUP_HP_GPIO_LED), SND_PCI_QUIRK(0x103c, 0x8d91, "HP ZBook Firefly 14 G12", ALC285_FIXUP_HP_GPIO_LED), SND_PCI_QUIRK(0x103c, 0x8d92, "HP ZBook Firefly 16 G12", ALC285_FIXUP_HP_GPIO_LED), + SND_PCI_QUIRK(0x103c, 0x8dcd, "HP Victus 15-fa2xxx", ALC245_FIXUP_HP_MUTE_LED_COEFBIT), SND_PCI_QUIRK(0x103c, 0x8d9b, "HP 17 Turbine OmniBook 7 UMA", ALC287_FIXUP_CS35L41_I2C_2), SND_PCI_QUIRK(0x103c, 0x8d9c, "HP 17 Turbine OmniBook 7 DIS", ALC287_FIXUP_CS35L41_I2C_2), SND_PCI_QUIRK(0x103c, 0x8d9d, "HP 17 Turbine OmniBook X UMA", ALC287_FIXUP_CS35L41_I2C_2), From 0a5ee0e520eff98ee2b4568194562870877b050f Mon Sep 17 00:00:00 2001 From: Tobias Heider Date: Wed, 22 Apr 2026 15:30:59 +0200 Subject: [PATCH 35/41] ASoC: qcom: x1e80100: limit speaker volumes Limit the digital gain and PA volumes to a combined -3 dB in the machine driver to reduce the risk of speaker damage until we have active speaker protection in place (or higher safe levels have been established). Based on commit c481016bb4f8 ("ASoC: qcom: sc8280xp: limit speaker volumes") which addressed the same issue on the sc8280x SoC with some minor changes as explained below. The Digital Volume behaves almost identical to sc8280x since both use the same lpass-wsa-macro, but x1e80100 has two sets of controls prefixed with WSA and WSA2. For PA x1e80100 machines use wsa884x amplifiers which expose a linear scale from -9 dB to 9 dB with a 1.5 dB step size giving us 0 dB = -9 dB + 6 * 1.5 dB. On x1e80100 there are two different speaker topologies we need to handle: 2-Speakers: SpkrLeft, Spkr Right 4-Speakers: WooferLeft, WooferRight, TweeterLeft, TweeterRight Signed-off-by: Tobias Heider Tested-by: Srinivas Kandagatla Reviewed-by: Srinivas Kandagatla Link: https://patch.msgid.link/20260422-x1e80100-audio-limit-v2-1-333258b97697@canonical.com Signed-off-by: Mark Brown --- sound/soc/qcom/x1e80100.c | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/sound/soc/qcom/x1e80100.c b/sound/soc/qcom/x1e80100.c index a3f4785c4bbe..c81df41ace88 100644 --- a/sound/soc/qcom/x1e80100.c +++ b/sound/soc/qcom/x1e80100.c @@ -27,10 +27,29 @@ static int x1e80100_snd_init(struct snd_soc_pcm_runtime *rtd) { struct x1e80100_snd_data *data = snd_soc_card_get_drvdata(rtd->card); struct snd_soc_dai *cpu_dai = snd_soc_rtd_to_cpu(rtd, 0); + struct snd_soc_card *card = rtd->card; struct snd_soc_jack *dp_jack = NULL; int dp_pcm_id = 0; switch (cpu_dai->id) { + case WSA_CODEC_DMA_RX_0: + case WSA_CODEC_DMA_RX_1: + /* + * Set limit of -3 dB on Digital Volume and 0 dB on PA Volume + * to reduce the risk of speaker damage until we have active + * speaker protection in place. + */ + snd_soc_limit_volume(card, "WSA WSA_RX0 Digital Volume", 81); + snd_soc_limit_volume(card, "WSA WSA_RX1 Digital Volume", 81); + snd_soc_limit_volume(card, "WSA2 WSA_RX0 Digital Volume", 81); + snd_soc_limit_volume(card, "WSA2 WSA_RX1 Digital Volume", 81); + snd_soc_limit_volume(card, "SpkrLeft PA Volume", 6); + snd_soc_limit_volume(card, "SpkrRight PA Volume", 6); + snd_soc_limit_volume(card, "WooferLeft PA Volume", 6); + snd_soc_limit_volume(card, "TweeterLeft PA Volume", 6); + snd_soc_limit_volume(card, "WooferRight PA Volume", 6); + snd_soc_limit_volume(card, "TweeterRight PA Volume", 6); + break; case DISPLAY_PORT_RX_0: dp_pcm_id = 0; dp_jack = &data->dp_jack[dp_pcm_id]; From 87a3f5c8ac2096e9406ce2ed3bf5b9bc1589a92d Mon Sep 17 00:00:00 2001 From: Maciej Strozek Date: Mon, 20 Apr 2026 12:48:17 +0100 Subject: [PATCH 36/41] ASoC: sdw_utils: cs42l43: allow spk component names to be combined Move handling of cs42l43-spk component string into SOF mechanism [1] which will allow it to be aggregated with other speakers. Likewise handle the cs35l56-bridge special case which should not be combined to keep compatibility with UCM. Link: https://github.com/thesofproject/linux/pull/5445 [1] Link: https://github.com/alsa-project/alsa-ucm-conf/pull/747 Reviewed-by: Bard Liao Signed-off-by: Maciej Strozek Suggested-by: Aaron Ma Tested-by: Aaron Ma Link: https://patch.msgid.link/20260420114823.194226-1-mstrozek@opensource.cirrus.com Signed-off-by: Mark Brown --- sound/soc/sdw_utils/soc_sdw_bridge_cs35l56.c | 6 ------ sound/soc/sdw_utils/soc_sdw_cs42l43.c | 12 +----------- sound/soc/sdw_utils/soc_sdw_utils.c | 20 ++++++++++++++++---- 3 files changed, 17 insertions(+), 21 deletions(-) diff --git a/sound/soc/sdw_utils/soc_sdw_bridge_cs35l56.c b/sound/soc/sdw_utils/soc_sdw_bridge_cs35l56.c index 2a7109d53cbe..e0e32a279787 100644 --- a/sound/soc/sdw_utils/soc_sdw_bridge_cs35l56.c +++ b/sound/soc/sdw_utils/soc_sdw_bridge_cs35l56.c @@ -40,12 +40,6 @@ static int asoc_sdw_bridge_cs35l56_asp_init(struct snd_soc_pcm_runtime *rtd) struct snd_soc_dai *codec_dai; struct snd_soc_dai *cpu_dai; - card->components = devm_kasprintf(card->dev, GFP_KERNEL, - "%s spk:cs35l56-bridge", - card->components); - if (!card->components) - return -ENOMEM; - ret = snd_soc_dapm_new_controls(dapm, bridge_widgets, ARRAY_SIZE(bridge_widgets)); if (ret) { diff --git a/sound/soc/sdw_utils/soc_sdw_cs42l43.c b/sound/soc/sdw_utils/soc_sdw_cs42l43.c index 4a451b9d4f13..e99ea3c4e5dd 100644 --- a/sound/soc/sdw_utils/soc_sdw_cs42l43.c +++ b/sound/soc/sdw_utils/soc_sdw_cs42l43.c @@ -107,21 +107,11 @@ EXPORT_SYMBOL_NS(asoc_sdw_cs42l43_hs_rtd_init, "SND_SOC_SDW_UTILS"); int asoc_sdw_cs42l43_spk_rtd_init(struct snd_soc_pcm_runtime *rtd, struct snd_soc_dai *dai) { - struct snd_soc_component *component = snd_soc_rtd_to_codec(rtd, 0)->component; + struct snd_soc_component *component = dai->component; struct snd_soc_card *card = rtd->card; struct snd_soc_dapm_context *dapm = snd_soc_card_to_dapm(card); - struct asoc_sdw_mc_private *ctx = snd_soc_card_get_drvdata(card); int ret; - if (!(ctx->mc_quirk & SOC_SDW_SIDECAR_AMPS)) { - /* Will be set by the bridge code in this case */ - card->components = devm_kasprintf(card->dev, GFP_KERNEL, - "%s spk:cs42l43-spk", - card->components); - if (!card->components) - return -ENOMEM; - } - ret = snd_soc_limit_volume(card, "cs42l43 Speaker Digital Volume", CS42L43_SPK_VOLUME_0DB); if (ret) diff --git a/sound/soc/sdw_utils/soc_sdw_utils.c b/sound/soc/sdw_utils/soc_sdw_utils.c index 2807f536eef0..1637cc3f3d59 100644 --- a/sound/soc/sdw_utils/soc_sdw_utils.c +++ b/sound/soc/sdw_utils/soc_sdw_utils.c @@ -758,6 +758,7 @@ struct asoc_sdw_codec_info codec_info_list[] = { { .direction = {true, false}, .codec_name = "cs42l43-codec", + .component_name = "cs42l43-spk", .dai_name = "cs42l43-dp6", .dai_type = SOC_SDW_DAI_TYPE_AMP, .dailink = {SOC_SDW_AMP_OUT_DAI_ID, SOC_SDW_UNUSED_DAI_ID}, @@ -1104,6 +1105,7 @@ static int asoc_sdw_find_codec_info_dai_index(const struct asoc_sdw_codec_info * int asoc_sdw_rtd_init(struct snd_soc_pcm_runtime *rtd) { struct snd_soc_card *card = rtd->card; + struct asoc_sdw_mc_private *ctx = snd_soc_card_get_drvdata(card); struct snd_soc_dapm_context *dapm = snd_soc_card_to_dapm(card); struct asoc_sdw_codec_info *codec_info; struct snd_soc_dai *dai; @@ -1179,16 +1181,26 @@ int asoc_sdw_rtd_init(struct snd_soc_pcm_runtime *rtd) /* Generate the spk component string for card->components string */ if (codec_info->dais[dai_index].dai_type == SOC_SDW_DAI_TYPE_AMP && codec_info->dais[dai_index].component_name) { + const char *component; + + /* + * For the special case of cs42l43 with sidecar amps, use only + * "cs35l56-bridge" as the component name in card->components + */ + if (ctx->mc_quirk & SOC_SDW_SIDECAR_AMPS && + !strcmp(codec_info->dais[dai_index].component_name, "cs42l43-spk")) + component = "cs35l56-bridge"; + else + component = codec_info->dais[dai_index].component_name; + if (strlen (spk_components) == 0) spk_components = - devm_kasprintf(card->dev, GFP_KERNEL, "%s", - codec_info->dais[dai_index].component_name); + devm_kasprintf(card->dev, GFP_KERNEL, "%s", component); else /* Append component name to spk_components */ spk_components = devm_kasprintf(card->dev, GFP_KERNEL, - "%s+%s", spk_components, - codec_info->dais[dai_index].component_name); + "%s+%s", spk_components, component); } codec_info->dais[dai_index].rtd_init_done = true; From fca9c850042a7ab4828ce3a9caa8bc40ea09856a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A1ssio=20Gabriel?= Date: Tue, 21 Apr 2026 21:53:52 -0300 Subject: [PATCH 37/41] ALSA: usb-audio: Avoid false E-MU sample-rate notifications MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit snd_emuusb_set_samplerate() unconditionally notifies the E-MU SampleRate Extension Unit control after issuing SET_CUR. If snd_usb_mixer_set_ctl_value() fails, the control value has not changed, yet snd_usb_mixer_notify_id() still invalidates the cache and emits a value-change event to userspace. Notify the control only after a successful write. Fixes: 7d2b451e65d2 ("ALSA: usb-audio - Added functionality for E-mu 0404USB/0202USB/TrackerPre") Cc: stable@vger.kernel.org Signed-off-by: Cássio Gabriel Link: https://patch.msgid.link/20260421-alsa-emuusb-samplerate-notify-v1-1-8b63bbc1d7f1@gmail.com Signed-off-by: Takashi Iwai --- sound/usb/mixer_quirks.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/sound/usb/mixer_quirks.c b/sound/usb/mixer_quirks.c index a01510a855c2..5194a2ac1ea8 100644 --- a/sound/usb/mixer_quirks.c +++ b/sound/usb/mixer_quirks.c @@ -1538,15 +1538,17 @@ void snd_emuusb_set_samplerate(struct snd_usb_audio *chip, { struct usb_mixer_interface *mixer; struct usb_mixer_elem_info *cval; + int err; int unitid = 12; /* SampleRate ExtensionUnit ID */ list_for_each_entry(mixer, &chip->mixer_list, list) { if (mixer->id_elems[unitid]) { cval = mixer_elem_list_to_info(mixer->id_elems[unitid]); - snd_usb_mixer_set_ctl_value(cval, UAC_SET_CUR, - cval->control << 8, - samplerate_id); - snd_usb_mixer_notify_id(mixer, unitid); + err = snd_usb_mixer_set_ctl_value(cval, UAC_SET_CUR, + cval->control << 8, + samplerate_id); + if (!err) + snd_usb_mixer_notify_id(mixer, unitid); break; } } From a9224f26b754b5034719248891ff3c2ea0d11144 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A1ssio=20Gabriel?= Date: Tue, 21 Apr 2026 22:07:41 -0300 Subject: [PATCH 38/41] ALSA: usb-audio: Fix Audio Advantage Micro II SPDIF switch MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit snd_microii_spdif_switch_put() returns 0 when the requested vendor register value differs from the cached one. This comparison was inverted by the resume-support conversion, so real SPDIF switch toggles are ignored while no-op writes still issue SET_CUR and report success. Return early only when the requested value matches the cached one. Fixes: 288673beae6c ("ALSA: usb-audio: Add resume support for MicroII SPDIF ctls") Cc: stable@vger.kernel.org Signed-off-by: Cássio Gabriel Link: https://patch.msgid.link/20260421-microii-spdif-switch-fix-v1-1-5c50dc28b88f@gmail.com Signed-off-by: Takashi Iwai --- sound/usb/mixer_quirks.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/usb/mixer_quirks.c b/sound/usb/mixer_quirks.c index 5194a2ac1ea8..1bdaa46d4fe1 100644 --- a/sound/usb/mixer_quirks.c +++ b/sound/usb/mixer_quirks.c @@ -2027,7 +2027,7 @@ static int snd_microii_spdif_switch_put(struct snd_kcontrol *kcontrol, int err; reg = ucontrol->value.integer.value[0] ? 0x28 : 0x2a; - if (reg != list->kctl->private_value) + if (reg == list->kctl->private_value) return 0; kcontrol->private_value = reg; From 6d619f73970397e13d2d3f830b183fcd9f58e749 Mon Sep 17 00:00:00 2001 From: Baojun Xu Date: Tue, 14 Apr 2026 09:54:40 +0800 Subject: [PATCH 39/41] ASoC: dt-bindings: ti,tas2781: Add TAS5832 support TAS5832 is in same family with TAS5827/28/30. Signed-off-by: Baojun Xu Reviewed-by: Krzysztof Kozlowski Link: https://patch.msgid.link/20260414015441.2439-1-baojun.xu@ti.com Signed-off-by: Mark Brown --- Documentation/devicetree/bindings/sound/ti,tas2781.yaml | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/Documentation/devicetree/bindings/sound/ti,tas2781.yaml b/Documentation/devicetree/bindings/sound/ti,tas2781.yaml index f3a5638f4239..b21466bb0730 100644 --- a/Documentation/devicetree/bindings/sound/ti,tas2781.yaml +++ b/Documentation/devicetree/bindings/sound/ti,tas2781.yaml @@ -1,5 +1,5 @@ # SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) -# Copyright (C) 2022 - 2025 Texas Instruments Incorporated +# Copyright (C) 2022 - 2026 Texas Instruments Incorporated %YAML 1.2 --- $id: http://devicetree.org/schemas/sound/ti,tas2781.yaml# @@ -107,6 +107,9 @@ properties: ti,tas5830: 65-W Stereo, Digital Input, High Efficiency Closed-Loop Class-D Amplifier with Class-H Algorithm + + ti,tas5832: 81-W Stereo, Digital Input, High Efficiency Closed-Loop + Class-D Amplifier with Class-H Algorithm oneOf: - items: - enum: @@ -128,6 +131,7 @@ properties: - ti,tas5827 - ti,tas5828 - ti,tas5830 + - ti,tas5832 - const: ti,tas2781 - enum: - ti,tas2781 @@ -264,6 +268,7 @@ allOf: - ti,tas5827 - ti,tas5828 - ti,tas5830 + - ti,tas5832 then: properties: reg: From 1f95fdef685ee76393981de062e6b26210d88a9c Mon Sep 17 00:00:00 2001 From: Baojun Xu Date: Tue, 14 Apr 2026 09:54:41 +0800 Subject: [PATCH 40/41] ASoC: tas2781: Add tas5832 support TAS5832 is in same family with TAS5827/28/30. Signed-off-by: Baojun Xu Link: https://patch.msgid.link/20260414015441.2439-2-baojun.xu@ti.com Signed-off-by: Mark Brown --- include/sound/tas2781.h | 1 + sound/soc/codecs/tas2781-i2c.c | 5 +++++ 2 files changed, 6 insertions(+) diff --git a/include/sound/tas2781.h b/include/sound/tas2781.h index e847cf51878c..95296bb4a33a 100644 --- a/include/sound/tas2781.h +++ b/include/sound/tas2781.h @@ -131,6 +131,7 @@ enum audio_device { TAS5827, TAS5828, TAS5830, + TAS5832, TAS_OTHERS, }; diff --git a/sound/soc/codecs/tas2781-i2c.c b/sound/soc/codecs/tas2781-i2c.c index 8af30f4d68da..a78a8f9b9833 100644 --- a/sound/soc/codecs/tas2781-i2c.c +++ b/sound/soc/codecs/tas2781-i2c.c @@ -119,6 +119,7 @@ static const struct i2c_device_id tasdevice_id[] = { { "tas5827", TAS5827 }, { "tas5828", TAS5828 }, { "tas5830", TAS5830 }, + { "tas5832", TAS5832 }, {} }; @@ -142,6 +143,7 @@ static const struct of_device_id tasdevice_of_match[] = { { .compatible = "ti,tas5827", .data = &tasdevice_id[TAS5827] }, { .compatible = "ti,tas5828", .data = &tasdevice_id[TAS5828] }, { .compatible = "ti,tas5830", .data = &tasdevice_id[TAS5830] }, + { .compatible = "ti,tas5832", .data = &tasdevice_id[TAS5832] }, {}, }; MODULE_DEVICE_TABLE(of, tasdevice_of_match); @@ -1744,6 +1746,7 @@ static void tasdevice_fw_ready(const struct firmware *fmw, case TAS5827: case TAS5828: case TAS5830: + case TAS5832: /* If DSP FW fail, DSP kcontrol won't be created. */ tasdevice_dsp_remove(tas_priv); } @@ -1915,6 +1918,7 @@ static int tasdevice_codec_probe(struct snd_soc_component *codec) case TAS5827: case TAS5828: case TAS5830: + case TAS5832: p = (struct snd_kcontrol_new *)tas5825_snd_controls; size = ARRAY_SIZE(tas5825_snd_controls); break; @@ -2101,6 +2105,7 @@ static const struct acpi_device_id tasdevice_acpi_match[] = { { "TXNW5827", (kernel_ulong_t)&tasdevice_id[TAS5827] }, { "TXNW5828", (kernel_ulong_t)&tasdevice_id[TAS5828] }, { "TXNW5830", (kernel_ulong_t)&tasdevice_id[TAS5830] }, + { "TXNW5832", (kernel_ulong_t)&tasdevice_id[TAS5832] }, {}, }; From 2724fbc90e5c133fbbd030e72fe8a3869a20df08 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Thu, 23 Apr 2026 09:52:05 +0200 Subject: [PATCH 41/41] Revert "ALSA: pcmtest: fix reference leak on failed device registration" We'd like to address the problem rather in the error code path of platform_device_register() itself instead of leaving it all callers, since less than 1% of all callers of over 100 platform_device_register() do call platform_device_put() properly as of now. For making the work easier, revert the previous change commit 4ff036f95238 ("ALSA: pcmtest: fix reference leak on failed device registration") again. Link: https://lore.kernel.org/20260415193138.3861297-1-lgs201920130244@gmail.com Link: https://patch.msgid.link/20260423075211.3977366-1-tiwai@suse.de Signed-off-by: Takashi Iwai --- sound/drivers/pcmtest.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/sound/drivers/pcmtest.c b/sound/drivers/pcmtest.c index fe31ff1e5b3c..5bfec4c7bf71 100644 --- a/sound/drivers/pcmtest.c +++ b/sound/drivers/pcmtest.c @@ -756,10 +756,8 @@ static int __init mod_init(void) if (err) goto err_free_patterns; err = platform_device_register(&pcmtst_pdev); - if (err) { - platform_device_put(&pcmtst_pdev); + if (err) goto err_clear_debug; - } err = platform_driver_register(&pcmtst_pdrv); if (err) { platform_device_unregister(&pcmtst_pdev);