Merge tag 'sound-7.2-rc2' of git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound

Pull sound fixes from Takashi Iwai:
 "A standard set of driver-specific fixes and quirks accumulated since
  the merge window:

  ASoC:
   - SOF: Sanity check to prevent OOB reads
   - rsnd: Fix clock leak and double-disable issues with PM
   - tas675x: Misc fixes for register fields, etc
   - lpass-va-macro: Correct codec version for Qualcomm SC7280
   - amd-yc: DMIC quirk for Alienware m15 R7 AMD

  Others:
   - us144mkii: Fix a UAF on disconnect and anchor list corruption
   - HD-audio: Realtek quirks for HP models"

* tag 'sound-7.2-rc2' of git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound:
  ASoC: rsnd: src: Add missing scu_supply clock to suspend/resume
  Documentation: sound: tas675x: Fix temperature range and impedance documentation
  ASoC: codecs: tas675x: Fix CHx temperature range register bit fields
  ASoC: codecs: tas675x: use READ_ONCE for params to be used concurrently
  ASoC: rsnd: adg: make rsnd_adg_clk_control() idempotent
  ASoC: SOF: validate probe info element counts
  ALSA: usx2y: us144mkii: fix work UAF on disconnect
  ASoC: amd: yc: Add Alienware m15 R7 AMD to DMIC quirk table
  ALSA: hda/realtek: Add quirk for HP Victus 16-e0xxx (88EE) to enable mute LED
  MAINTAINERS: ASoC: SOF: add AMD reviewer for Sound Open Firmware
  ASoC: codecs: lpass-va-macro: Fix LPASS Codec Version for SC7280
  ALSA: us144mkii: capture_urb_complete: redundant usb_anchor_urb corrupts anchor list on each resubmission
This commit is contained in:
Linus Torvalds
2026-07-05 05:26:45 -10:00
12 changed files with 99 additions and 26 deletions

View File

@@ -281,7 +281,7 @@ Global Temperature
:Description: Global die temperature sense register.
:Type: Integer (read-only)
:Range: 0 to 255
:Conversion: (value × 0.5 °C) 50 °C
:Conversion: value × 2.19 K; subtract 273.15 for °C
:Register: 0x75
CHx Temperature Range
@@ -289,10 +289,11 @@ CHx Temperature Range
:Description: Per-channel coarse temperature range indicator (x = 1, 2, 3, 4).
:Type: Integer (read-only)
:Range: 0 to 3
:Mapping: 0 = <80 °C, 1 = 80100 °C, 2 = 100120 °C, 3 = >120 °C
:Register: 0xBB bits [7:6] (CH1), bits [5:4] (CH2),
0xBC bits [3:2] (CH3), bits [1:0] (CH4)
:Range: 0 to 7
:Mapping: 0 = <95 °C, 1 = 95110 °C, 2 = 110125 °C, 3 = 125135 °C,
4 = 135145 °C, 5 = 145155 °C, 6 = 155165 °C, 7 = >165 °C
:Register: 0xBB bits [2:0] (CH1), bits [5:3] (CH2),
0xBC bits [2:0] (CH3), bits [5:3] (CH4)
Load Diagnostics
================

View File

@@ -25377,6 +25377,7 @@ M: Bard Liao <yung-chuan.liao@linux.intel.com>
M: Daniel Baluta <daniel.baluta@nxp.com>
R: Kai Vehmanen <kai.vehmanen@linux.intel.com>
R: Pierre-Louis Bossart <pierre-louis.bossart@linux.dev>
R: Vijendar Mukunda <Vijendar.Mukunda@amd.com>
L: sound-open-firmware@alsa-project.org (moderated for non-subscribers)
S: Supported
W: https://github.com/thesofproject/linux/

View File

@@ -7068,6 +7068,7 @@ static const struct hda_quirk alc269_fixup_tbl[] = {
SND_PCI_QUIRK(0x103c, 0x88d1, "HP Pavilion 15-eh1xxx (mainboard 88D1)", ALC245_FIXUP_HP_MUTE_LED_V1_COEFBIT),
SND_PCI_QUIRK(0x103c, 0x88dd, "HP Pavilion 15z-ec200", ALC285_FIXUP_HP_MUTE_LED),
SND_PCI_QUIRK(0x103c, 0x88eb, "HP Victus 16-e0xxx", ALC245_FIXUP_HP_MUTE_LED_V2_COEFBIT),
SND_PCI_QUIRK(0x103c, 0x88ee, "HP Victus 16-e0xxx (MB 88EE)", ALC245_FIXUP_HP_MUTE_LED_COEFBIT),
SND_PCI_QUIRK(0x103c, 0x8902, "HP OMEN 16", ALC285_FIXUP_HP_MUTE_LED),
SND_PCI_QUIRK(0x103c, 0x890e, "HP 255 G8 Notebook PC", ALC236_FIXUP_HP_MUTE_LED_COEFBIT2),
SND_PCI_QUIRK(0x103c, 0x8919, "HP Pavilion Aero Laptop 13-be0xxx", ALC287_FIXUP_HP_GPIO_LED),

View File

@@ -528,6 +528,13 @@ static const struct dmi_system_id yc_acp_quirk_table[] = {
DMI_MATCH(DMI_PRODUCT_NAME, "Raider A18 HX A9WJG"),
}
},
{
.driver_data = &acp6x_card,
.matches = {
DMI_MATCH(DMI_BOARD_VENDOR, "Alienware"),
DMI_MATCH(DMI_PRODUCT_NAME, "Alienware m15 R7 AMD"),
}
},
{
.driver_data = &acp6x_card,
.matches = {

View File

@@ -244,6 +244,11 @@ static const struct va_macro_data sm8250_va_data = {
.version = LPASS_CODEC_VERSION_1_0,
};
static const struct va_macro_data sc7280_va_data = {
.has_swr_master = false,
.has_npl_clk = false,
};
static const struct va_macro_data sm8450_va_data = {
.has_swr_master = true,
.has_npl_clk = true,
@@ -1755,7 +1760,7 @@ static const struct dev_pm_ops va_macro_pm_ops = {
};
static const struct of_device_id va_macro_dt_match[] = {
{ .compatible = "qcom,sc7280-lpass-va-macro", .data = &sm8250_va_data },
{ .compatible = "qcom,sc7280-lpass-va-macro", .data = &sc7280_va_data },
{ .compatible = "qcom,sm6115-lpass-va-macro", .data = &sm8450_va_data },
{ .compatible = "qcom,sm8250-lpass-va-macro", .data = &sm8250_va_data },
{ .compatible = "qcom,sm8450-lpass-va-macro", .data = &sm8450_va_data },

View File

@@ -954,10 +954,10 @@ static const struct snd_kcontrol_new tas675x_snd_controls[] = {
/* Temperature and Voltage Monitoring */
SOC_SINGLE_RO("PVDD Sense", TAS675X_PVDD_SENSE_REG, 0, 0xFF),
SOC_SINGLE_RO("Global Temperature", TAS675X_TEMP_GLOBAL_REG, 0, 0xFF),
SOC_SINGLE_RO("CH1 Temperature Range", TAS675X_TEMP_CH1_CH2_REG, 6, 3),
SOC_SINGLE_RO("CH2 Temperature Range", TAS675X_TEMP_CH1_CH2_REG, 4, 3),
SOC_SINGLE_RO("CH3 Temperature Range", TAS675X_TEMP_CH3_CH4_REG, 2, 3),
SOC_SINGLE_RO("CH4 Temperature Range", TAS675X_TEMP_CH3_CH4_REG, 0, 3),
SOC_SINGLE_RO("CH1 Temperature Range", TAS675X_TEMP_CH1_CH2_REG, 0, 7),
SOC_SINGLE_RO("CH2 Temperature Range", TAS675X_TEMP_CH1_CH2_REG, 3, 7),
SOC_SINGLE_RO("CH3 Temperature Range", TAS675X_TEMP_CH3_CH4_REG, 0, 7),
SOC_SINGLE_RO("CH4 Temperature Range", TAS675X_TEMP_CH3_CH4_REG, 3, 7),
/* Speaker Protection & Detection */
SOC_SINGLE("Tweeter Detection Switch", TAS675X_TWEETER_DETECT_CTRL_REG, 0, 1, 1),
@@ -1133,7 +1133,7 @@ static int tas675x_hw_params(struct snd_pcm_substream *substream,
* Single clock domain: SDIN and SDOUT share one SCLK/FSYNC pair,
* so all active DAIs must use the same sample rate.
*/
if ((tas->active_playback_dais || tas->active_capture_dais) &&
if ((READ_ONCE(tas->active_playback_dais) || READ_ONCE(tas->active_capture_dais)) &&
tas->rate && tas->rate != rate) {
dev_err(component->dev,
"Rate %u conflicts with active rate %u\n",
@@ -1397,14 +1397,14 @@ static int tas675x_mute_stream(struct snd_soc_dai *dai, int mute, int direction)
set_bit(dai->id, &tas->active_playback_dais);
/* Last playback stream */
if (mute && !tas->active_playback_dais) {
if (mute && !READ_ONCE(tas->active_playback_dais)) {
ret = tas675x_set_state_all(tas, TAS675X_STATE_SLEEP_BOTH);
regmap_read(tas->regmap, TAS675X_CLK_FAULT_LATCHED_REG, &discard);
return ret;
}
return tas675x_set_state_all(tas,
tas->active_playback_dais ?
READ_ONCE(tas->active_playback_dais) ?
TAS675X_STATE_PLAY_BOTH :
TAS675X_STATE_SLEEP_BOTH);
}

View File

@@ -45,6 +45,7 @@ struct rsnd_adg {
struct rsnd_mod mod;
int clkin_rate[CLKINMAX];
bool ssi_clk_prepared;
bool clk_enabled;
int clkin_size;
int clkout_size;
u32 ckr;
@@ -463,6 +464,22 @@ int rsnd_adg_clk_control(struct rsnd_priv *priv, int enable)
struct clk *clk;
int ret = 0, i;
/*
* rsnd_adg_clk_enable() and rsnd_adg_clk_disable() can be called
* redundantly, for example when system suspend follows a resume
* whose enable failed. Make this function idempotent so that the
* "adg" clock, which has no clkin_rate[] style guard, is never
* disabled twice.
*/
if (enable) {
if (adg->clk_enabled)
return 0;
} else {
if (!adg->clk_enabled)
return 0;
adg->clk_enabled = false;
}
if (enable) {
ret = clk_prepare_enable(adg->adg);
if (ret < 0)
@@ -520,12 +537,22 @@ int rsnd_adg_clk_control(struct rsnd_priv *priv, int enable)
* rsnd_adg_clk_enable() might return error (_disable() will not).
* We need to rollback in such case
*/
if (ret < 0)
if (ret < 0) {
/*
* Mark as enabled so that the rollback below is not
* short-circuited by the idempotency guard. It clears
* the flag again on its way through.
*/
adg->clk_enabled = true;
rsnd_adg_clk_disable(priv);
return ret;
}
/* disable adg */
if (!enable)
clk_disable_unprepare(adg->adg);
else
adg->clk_enabled = true;
return ret;
}

View File

@@ -850,6 +850,7 @@ void rsnd_src_suspend(struct rsnd_priv *priv)
clk_disable_unprepare(src_ctrl->scu_x2);
clk_disable_unprepare(src_ctrl->scu);
clk_disable_unprepare(src_ctrl->scu_supply);
}
void rsnd_src_resume(struct rsnd_priv *priv)
@@ -861,6 +862,7 @@ void rsnd_src_resume(struct rsnd_priv *priv)
if (!src_ctrl)
return;
clk_prepare_enable(src_ctrl->scu_supply);
clk_prepare_enable(src_ctrl->scu);
clk_prepare_enable(src_ctrl->scu_x2);

View File

@@ -107,7 +107,7 @@ static int ipc3_probes_info(struct sof_client_dev *cdev, unsigned int cmd,
struct device *dev = &cdev->auxdev.dev;
struct sof_ipc_probe_info_params msg = {{{0}}};
struct sof_ipc_probe_info_params *reply;
size_t bytes;
size_t bytes, elem_size, payload_size;
int ret;
*params = NULL;
@@ -128,14 +128,29 @@ static int ipc3_probes_info(struct sof_client_dev *cdev, unsigned int cmd,
if (ret < 0 || reply->rhdr.error < 0)
goto exit;
payload_size = reply->rhdr.hdr.size;
if (payload_size < offsetof(struct sof_ipc_probe_info_params, dma)) {
ret = -EINVAL;
goto exit;
}
if (!reply->num_elems)
goto exit;
if (cmd == SOF_IPC_PROBE_DMA_INFO)
bytes = sizeof(reply->dma[0]);
elem_size = sizeof(reply->dma[0]);
else
bytes = sizeof(reply->desc[0]);
bytes *= reply->num_elems;
elem_size = sizeof(reply->desc[0]);
payload_size -= offsetof(struct sof_ipc_probe_info_params, dma);
if (reply->num_elems > payload_size / elem_size) {
dev_err(dev, "%s: invalid probe info element count %u\n",
__func__, reply->num_elems);
ret = -EINVAL;
goto exit;
}
bytes = reply->num_elems * elem_size;
*params = kmemdup(&reply->dma[0], bytes, GFP_KERNEL);
if (!*params) {
ret = -ENOMEM;

View File

@@ -248,10 +248,19 @@ static int ipc4_probes_points_info(struct sof_client_dev *cdev,
return ret;
}
info = msg.data_ptr;
if (msg.data_size < sizeof(*info) ||
info->num_elems > (msg.data_size - sizeof(*info)) /
sizeof(info->points[0])) {
dev_err(dev, "%s: invalid probe info element count %u\n",
__func__, info->num_elems);
kfree(msg.data_ptr);
return -EINVAL;
}
*num_desc = info->num_elems;
dev_dbg(dev, "%s: got %zu probe points", __func__, *num_desc);
*desc = kzalloc(*num_desc * sizeof(**desc), GFP_KERNEL);
*desc = kcalloc(*num_desc, sizeof(**desc), GFP_KERNEL);
if (!*desc) {
kfree(msg.data_ptr);
return -ENOMEM;

View File

@@ -585,19 +585,24 @@ static void tascam_disconnect(struct usb_interface *intf)
return;
if (intf->cur_altsetting->desc.bInterfaceNumber == 0) {
/* Ensure all deferred work is complete before freeing resources */
snd_card_disconnect(tascam->card);
cancel_work_sync(&tascam->stop_work);
cancel_work_sync(&tascam->capture_work);
cancel_work_sync(&tascam->midi_in_work);
cancel_work_sync(&tascam->midi_out_work);
cancel_work_sync(&tascam->stop_pcm_work);
/*
* Kill the URBs before cancelling the work, so a late URB
* completion cannot re-arm a work that then runs after
* snd_card_free().
*/
usb_kill_anchored_urbs(&tascam->playback_anchor);
usb_kill_anchored_urbs(&tascam->capture_anchor);
usb_kill_anchored_urbs(&tascam->feedback_anchor);
usb_kill_anchored_urbs(&tascam->midi_in_anchor);
usb_kill_anchored_urbs(&tascam->midi_out_anchor);
cancel_work_sync(&tascam->stop_work);
cancel_work_sync(&tascam->capture_work);
cancel_work_sync(&tascam->midi_in_work);
cancel_work_sync(&tascam->midi_out_work);
cancel_work_sync(&tascam->stop_pcm_work);
timer_delete_sync(&tascam->error_timer);
tascam_free_urbs(tascam);
snd_card_free(tascam->card);

View File

@@ -302,7 +302,6 @@ void capture_urb_complete(struct urb *urb)
}
usb_get_urb(urb);
usb_anchor_urb(urb, &tascam->capture_anchor);
ret = usb_submit_urb(urb, GFP_ATOMIC);
if (ret < 0) {
dev_err_ratelimited(tascam->card->dev,
@@ -312,6 +311,7 @@ void capture_urb_complete(struct urb *urb)
usb_put_urb(urb);
atomic_dec(
&tascam->active_urbs); /* Decrement on failed resubmission */
return;
}
out:
usb_put_urb(urb);