mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2026-07-21 22:47:51 -04:00
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:
@@ -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 = 80–100 °C, 2 = 100–120 °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 = 95–110 °C, 2 = 110–125 °C, 3 = 125–135 °C,
|
||||
4 = 135–145 °C, 5 = 145–155 °C, 6 = 155–165 °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
|
||||
================
|
||||
|
||||
@@ -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/
|
||||
|
||||
@@ -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),
|
||||
|
||||
@@ -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 = {
|
||||
|
||||
@@ -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 },
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user