summaryrefslogtreecommitdiff
path: root/sound/pci/hda
diff options
context:
space:
mode:
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>2024-06-12 12:39:59 +0300
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2024-06-12 12:39:59 +0300
commitaaecd681f60fa02c7697198b308336a13b231f30 (patch)
treea6c6535d9553d63c4150dfe40669376e988f980f /sound/pci/hda
parentb84a9523bab4a2483d7b7566b81a7859c2fd9a78 (diff)
parent103a4e4a4351d3d5214c4f54fdf89f0f81b692ef (diff)
downloadlinux-aaecd681f60fa02c7697198b308336a13b231f30.tar.xz
Merge v6.9.4
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'sound/pci/hda')
-rw-r--r--sound/pci/hda/cs35l56_hda.c8
-rw-r--r--sound/pci/hda/hda_component.c16
-rw-r--r--sound/pci/hda/hda_component.h7
-rw-r--r--sound/pci/hda/hda_cs_dsp_ctl.c47
-rw-r--r--sound/pci/hda/patch_realtek.c5
5 files changed, 55 insertions, 28 deletions
diff --git a/sound/pci/hda/cs35l56_hda.c b/sound/pci/hda/cs35l56_hda.c
index 558c1f38fe97..11b0570ff56d 100644
--- a/sound/pci/hda/cs35l56_hda.c
+++ b/sound/pci/hda/cs35l56_hda.c
@@ -732,8 +732,6 @@ static void cs35l56_hda_unbind(struct device *dev, struct device *master, void *
if (cs35l56->base.fw_patched)
cs_dsp_power_down(&cs35l56->cs_dsp);
- cs_dsp_remove(&cs35l56->cs_dsp);
-
if (comps[cs35l56->index].dev == dev)
memset(&comps[cs35l56->index], 0, sizeof(*comps));
@@ -1035,7 +1033,7 @@ int cs35l56_hda_common_probe(struct cs35l56_hda *cs35l56, int hid, int id)
ARRAY_SIZE(cs35l56_hda_dai_config));
ret = cs35l56_force_sync_asp1_registers_from_cache(&cs35l56->base);
if (ret)
- goto err;
+ goto dsp_err;
/*
* By default only enable one ASP1TXn, where n=amplifier index,
@@ -1061,6 +1059,8 @@ int cs35l56_hda_common_probe(struct cs35l56_hda *cs35l56, int hid, int id)
pm_err:
pm_runtime_disable(cs35l56->base.dev);
+dsp_err:
+ cs_dsp_remove(&cs35l56->cs_dsp);
err:
gpiod_set_value_cansleep(cs35l56->base.reset_gpio, 0);
@@ -1078,6 +1078,8 @@ void cs35l56_hda_remove(struct device *dev)
component_del(cs35l56->base.dev, &cs35l56_hda_comp_ops);
+ cs_dsp_remove(&cs35l56->cs_dsp);
+
kfree(cs35l56->system_name);
pm_runtime_put_noidle(cs35l56->base.dev);
diff --git a/sound/pci/hda/hda_component.c b/sound/pci/hda/hda_component.c
index cd299d7d84ba..d02589014a3f 100644
--- a/sound/pci/hda/hda_component.c
+++ b/sound/pci/hda/hda_component.c
@@ -123,6 +123,21 @@ static int hda_comp_match_dev_name(struct device *dev, void *data)
return !strcmp(d + n, tmp);
}
+int hda_component_manager_bind(struct hda_codec *cdc,
+ struct hda_component *comps, int count)
+{
+ int i;
+
+ /* Init shared data */
+ for (i = 0; i < count; ++i) {
+ memset(&comps[i], 0, sizeof(comps[i]));
+ comps[i].codec = cdc;
+ }
+
+ return component_bind_all(hda_codec_dev(cdc), comps);
+}
+EXPORT_SYMBOL_NS_GPL(hda_component_manager_bind, SND_HDA_SCODEC_COMPONENT);
+
int hda_component_manager_init(struct hda_codec *cdc,
struct hda_component *comps, int count,
const char *bus, const char *hid,
@@ -143,7 +158,6 @@ int hda_component_manager_init(struct hda_codec *cdc,
sm->hid = hid;
sm->match_str = match_str;
sm->index = i;
- comps[i].codec = cdc;
component_match_add(dev, &match, hda_comp_match_dev_name, sm);
}
diff --git a/sound/pci/hda/hda_component.h b/sound/pci/hda/hda_component.h
index c80a66691b5d..c70b3de68ab2 100644
--- a/sound/pci/hda/hda_component.h
+++ b/sound/pci/hda/hda_component.h
@@ -75,11 +75,8 @@ int hda_component_manager_init(struct hda_codec *cdc,
void hda_component_manager_free(struct hda_codec *cdc,
const struct component_master_ops *ops);
-static inline int hda_component_manager_bind(struct hda_codec *cdc,
- struct hda_component *comps)
-{
- return component_bind_all(hda_codec_dev(cdc), comps);
-}
+int hda_component_manager_bind(struct hda_codec *cdc,
+ struct hda_component *comps, int count);
static inline void hda_component_manager_unbind(struct hda_codec *cdc,
struct hda_component *comps)
diff --git a/sound/pci/hda/hda_cs_dsp_ctl.c b/sound/pci/hda/hda_cs_dsp_ctl.c
index 463ca06036bf..9db45d7c17e5 100644
--- a/sound/pci/hda/hda_cs_dsp_ctl.c
+++ b/sound/pci/hda/hda_cs_dsp_ctl.c
@@ -8,6 +8,7 @@
#include <linux/module.h>
#include <sound/soc.h>
+#include <linux/cleanup.h>
#include <linux/firmware/cirrus/cs_dsp.h>
#include <linux/firmware/cirrus/wmfw.h>
#include "hda_cs_dsp_ctl.h"
@@ -97,11 +98,23 @@ static unsigned int wmfw_convert_flags(unsigned int in)
return out;
}
-static void hda_cs_dsp_add_kcontrol(struct hda_cs_dsp_coeff_ctl *ctl, const char *name)
+static void hda_cs_dsp_free_kcontrol(struct snd_kcontrol *kctl)
{
+ struct hda_cs_dsp_coeff_ctl *ctl = (struct hda_cs_dsp_coeff_ctl *)snd_kcontrol_chip(kctl);
struct cs_dsp_coeff_ctl *cs_ctl = ctl->cs_ctl;
+
+ /* NULL priv to prevent a double-free in hda_cs_dsp_control_remove() */
+ cs_ctl->priv = NULL;
+ kfree(ctl);
+}
+
+static void hda_cs_dsp_add_kcontrol(struct cs_dsp_coeff_ctl *cs_ctl,
+ const struct hda_cs_dsp_ctl_info *info,
+ const char *name)
+{
struct snd_kcontrol_new kcontrol = {0};
struct snd_kcontrol *kctl;
+ struct hda_cs_dsp_coeff_ctl *ctl __free(kfree) = NULL;
int ret = 0;
if (cs_ctl->len > ADSP_MAX_STD_CTRL_SIZE) {
@@ -110,6 +123,13 @@ static void hda_cs_dsp_add_kcontrol(struct hda_cs_dsp_coeff_ctl *ctl, const char
return;
}
+ ctl = kzalloc(sizeof(*ctl), GFP_KERNEL);
+ if (!ctl)
+ return;
+
+ ctl->cs_ctl = cs_ctl;
+ ctl->card = info->card;
+
kcontrol.name = name;
kcontrol.info = hda_cs_dsp_coeff_info;
kcontrol.iface = SNDRV_CTL_ELEM_IFACE_MIXER;
@@ -117,20 +137,22 @@ static void hda_cs_dsp_add_kcontrol(struct hda_cs_dsp_coeff_ctl *ctl, const char
kcontrol.get = hda_cs_dsp_coeff_get;
kcontrol.put = hda_cs_dsp_coeff_put;
- /* Save ctl inside private_data, ctl is owned by cs_dsp,
- * and will be freed when cs_dsp removes the control */
kctl = snd_ctl_new1(&kcontrol, (void *)ctl);
if (!kctl)
return;
- ret = snd_ctl_add(ctl->card, kctl);
+ kctl->private_free = hda_cs_dsp_free_kcontrol;
+ ctl->kctl = kctl;
+
+ /* snd_ctl_add() calls our private_free on error, which will kfree(ctl) */
+ cs_ctl->priv = no_free_ptr(ctl);
+ ret = snd_ctl_add(info->card, kctl);
if (ret) {
dev_err(cs_ctl->dsp->dev, "Failed to add KControl %s = %d\n", kcontrol.name, ret);
return;
}
dev_dbg(cs_ctl->dsp->dev, "Added KControl: %s\n", kcontrol.name);
- ctl->kctl = kctl;
}
static void hda_cs_dsp_control_add(struct cs_dsp_coeff_ctl *cs_ctl,
@@ -138,7 +160,6 @@ static void hda_cs_dsp_control_add(struct cs_dsp_coeff_ctl *cs_ctl,
{
struct cs_dsp *cs_dsp = cs_ctl->dsp;
char name[SNDRV_CTL_ELEM_ID_NAME_MAXLEN];
- struct hda_cs_dsp_coeff_ctl *ctl;
const char *region_name;
int ret;
@@ -163,15 +184,7 @@ static void hda_cs_dsp_control_add(struct cs_dsp_coeff_ctl *cs_ctl,
" %.*s", cs_ctl->subname_len - skip, cs_ctl->subname + skip);
}
- ctl = kzalloc(sizeof(*ctl), GFP_KERNEL);
- if (!ctl)
- return;
-
- ctl->cs_ctl = cs_ctl;
- ctl->card = info->card;
- cs_ctl->priv = ctl;
-
- hda_cs_dsp_add_kcontrol(ctl, name);
+ hda_cs_dsp_add_kcontrol(cs_ctl, info, name);
}
void hda_cs_dsp_add_controls(struct cs_dsp *dsp, const struct hda_cs_dsp_ctl_info *info)
@@ -203,7 +216,9 @@ void hda_cs_dsp_control_remove(struct cs_dsp_coeff_ctl *cs_ctl)
{
struct hda_cs_dsp_coeff_ctl *ctl = cs_ctl->priv;
- kfree(ctl);
+ /* ctl and kctl may already have been removed by ALSA private_free */
+ if (ctl && ctl->kctl)
+ snd_ctl_remove(ctl->card, ctl->kctl);
}
EXPORT_SYMBOL_NS_GPL(hda_cs_dsp_control_remove, SND_HDA_CS_DSP_CONTROLS);
diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c
index 3b8b4ab488a6..1a1ca7caaff0 100644
--- a/sound/pci/hda/patch_realtek.c
+++ b/sound/pci/hda/patch_realtek.c
@@ -6793,7 +6793,7 @@ static int comp_bind(struct device *dev)
struct alc_spec *spec = cdc->spec;
int ret;
- ret = hda_component_manager_bind(cdc, spec->comps);
+ ret = hda_component_manager_bind(cdc, spec->comps, ARRAY_SIZE(spec->comps));
if (ret)
return ret;
@@ -10103,7 +10103,6 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = {
SND_PCI_QUIRK(0x103c, 0x8a2c, "HP Envy 16", ALC287_FIXUP_CS35L41_I2C_2),
SND_PCI_QUIRK(0x103c, 0x8a2d, "HP Envy 16", ALC287_FIXUP_CS35L41_I2C_2),
SND_PCI_QUIRK(0x103c, 0x8a2e, "HP Envy 16", ALC287_FIXUP_CS35L41_I2C_2),
- SND_PCI_QUIRK(0x103c, 0x8a2e, "HP Envy 17", ALC287_FIXUP_CS35L41_I2C_2),
SND_PCI_QUIRK(0x103c, 0x8a30, "HP Envy 17", ALC287_FIXUP_CS35L41_I2C_2),
SND_PCI_QUIRK(0x103c, 0x8a31, "HP Envy 15", ALC287_FIXUP_CS35L41_I2C_2),
SND_PCI_QUIRK(0x103c, 0x8a6e, "HP EDNA 360", ALC287_FIXUP_CS35L41_I2C_4),
@@ -10295,7 +10294,7 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = {
SND_PCI_QUIRK(0x1043, 0x3030, "ASUS ZN270IE", ALC256_FIXUP_ASUS_AIO_GPIO2),
SND_PCI_QUIRK(0x1043, 0x3a20, "ASUS G614JZR", ALC245_FIXUP_CS35L41_SPI_2),
SND_PCI_QUIRK(0x1043, 0x3a30, "ASUS G814JVR/JIR", ALC245_FIXUP_CS35L41_SPI_2),
- SND_PCI_QUIRK(0x1043, 0x3a40, "ASUS G814JZR", ALC245_FIXUP_CS35L41_SPI_2),
+ SND_PCI_QUIRK(0x1043, 0x3a40, "ASUS G814JZR", ALC285_FIXUP_ASUS_SPI_REAR_SPEAKERS),
SND_PCI_QUIRK(0x1043, 0x3a50, "ASUS G834JYR/JZR", ALC245_FIXUP_CS35L41_SPI_2),
SND_PCI_QUIRK(0x1043, 0x3a60, "ASUS G634JYR/JZR", ALC285_FIXUP_ASUS_SPI_REAR_SPEAKERS),
SND_PCI_QUIRK(0x1043, 0x831a, "ASUS P901", ALC269_FIXUP_STEREO_DMIC),