Skip to content

Commit 4e7035a

Browse files
jimxbj-dottiwai
authored andcommitted
ALSA: hda/tas2781: Add speaker id check for ASUS projects
Add speaker id check by gpio in ACPI for ASUS projects. In other vendors, speaker id was checked by BIOS, and was applied in last bit of subsys id, so we can load corresponding firmware binary file for its speaker by subsys id. But in ASUS project, the firmware binary name will be appended an extra number to tell the speakers from different vendors. And this single digit come from gpio level of speaker id in BIOS. Signed-off-by: Baojun Xu <[email protected]> Link: https://patch.msgid.link/[email protected] Signed-off-by: Takashi Iwai <[email protected]>
1 parent 1fd5050 commit 4e7035a

File tree

2 files changed

+60
-4
lines changed

2 files changed

+60
-4
lines changed

include/sound/tas2781.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -156,6 +156,7 @@ struct tasdevice_priv {
156156
struct tasdevice_rca rcabin;
157157
struct calidata cali_data;
158158
struct tasdevice_fw *fmw;
159+
struct gpio_desc *speaker_id;
159160
struct gpio_desc *reset;
160161
struct mutex codec_lock;
161162
struct regmap *regmap;

sound/pci/hda/tas2781_hda_i2c.c

Lines changed: 59 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
#include <linux/i2c.h>
1717
#include <linux/mod_devicetable.h>
1818
#include <linux/module.h>
19+
#include <linux/pci_ids.h>
1920
#include <linux/pm_runtime.h>
2021
#include <linux/regmap.h>
2122
#include <sound/hda_codec.h>
@@ -110,10 +111,20 @@ static int tas2781_get_i2c_res(struct acpi_resource *ares, void *data)
110111
return 1;
111112
}
112113

114+
static const struct acpi_gpio_params speakerid_gpios = { 0, 0, false };
115+
116+
static const struct acpi_gpio_mapping tas2781_speaker_id_gpios[] = {
117+
{ "speakerid-gpios", &speakerid_gpios, 1 },
118+
{ }
119+
};
120+
113121
static int tas2781_read_acpi(struct tasdevice_priv *p, const char *hid)
114122
{
115123
struct acpi_device *adev;
124+
struct device *physdev;
116125
LIST_HEAD(resources);
126+
const char *sub;
127+
uint32_t subid;
117128
int ret;
118129

119130
adev = acpi_dev_get_first_match_dev(hid, NULL, -1);
@@ -123,18 +134,45 @@ static int tas2781_read_acpi(struct tasdevice_priv *p, const char *hid)
123134
return -ENODEV;
124135
}
125136

137+
physdev = get_device(acpi_get_first_physical_node(adev));
126138
ret = acpi_dev_get_resources(adev, &resources, tas2781_get_i2c_res, p);
127-
if (ret < 0)
139+
if (ret < 0) {
140+
dev_err(p->dev, "Failed to get ACPI resource.\n");
141+
goto err;
142+
}
143+
sub = acpi_get_subsystem_id(ACPI_HANDLE(physdev));
144+
if (IS_ERR(sub)) {
145+
dev_err(p->dev, "Failed to get SUBSYS ID.\n");
128146
goto err;
147+
}
148+
/* Speaker id was needed for ASUS projects. */
149+
ret = kstrtou32(sub, 16, &subid);
150+
if (!ret && upper_16_bits(subid) == PCI_VENDOR_ID_ASUSTEK) {
151+
ret = devm_acpi_dev_add_driver_gpios(p->dev,
152+
tas2781_speaker_id_gpios);
153+
if (ret < 0)
154+
dev_err(p->dev, "Failed to add driver gpio %d.\n",
155+
ret);
156+
p->speaker_id = devm_gpiod_get(p->dev, "speakerid", GPIOD_IN);
157+
if (IS_ERR(p->speaker_id)) {
158+
dev_err(p->dev, "Failed to get Speaker id.\n");
159+
ret = PTR_ERR(p->speaker_id);
160+
goto err;
161+
}
162+
} else {
163+
p->speaker_id = NULL;
164+
}
129165

130166
acpi_dev_free_resource_list(&resources);
131167
strscpy(p->dev_name, hid, sizeof(p->dev_name));
168+
put_device(physdev);
132169
acpi_dev_put(adev);
133170

134171
return 0;
135172

136173
err:
137174
dev_err(p->dev, "read acpi error, ret: %d\n", ret);
175+
put_device(physdev);
138176
acpi_dev_put(adev);
139177

140178
return ret;
@@ -615,7 +653,7 @@ static void tasdev_fw_ready(const struct firmware *fmw, void *context)
615653
struct tasdevice_priv *tas_priv = context;
616654
struct tas2781_hda *tas_hda = dev_get_drvdata(tas_priv->dev);
617655
struct hda_codec *codec = tas_priv->codec;
618-
int i, ret;
656+
int i, ret, spk_id;
619657

620658
pm_runtime_get_sync(tas_priv->dev);
621659
mutex_lock(&tas_priv->codec_lock);
@@ -648,8 +686,25 @@ static void tasdev_fw_ready(const struct firmware *fmw, void *context)
648686
tasdevice_dsp_remove(tas_priv);
649687

650688
tas_priv->fw_state = TASDEVICE_DSP_FW_PENDING;
651-
scnprintf(tas_priv->coef_binaryname, 64, "TAS2XXX%04X.bin",
652-
codec->core.subsystem_id & 0xffff);
689+
if (tas_priv->speaker_id != NULL) {
690+
// Speaker id need to be checked for ASUS only.
691+
spk_id = gpiod_get_value(tas_priv->speaker_id);
692+
if (spk_id < 0) {
693+
// Speaker id is not valid, use default.
694+
dev_dbg(tas_priv->dev, "Wrong spk_id = %d\n", spk_id);
695+
spk_id = 0;
696+
}
697+
snprintf(tas_priv->coef_binaryname,
698+
sizeof(tas_priv->coef_binaryname),
699+
"TAS2XXX%04X%d.bin",
700+
lower_16_bits(codec->core.subsystem_id),
701+
spk_id);
702+
} else {
703+
snprintf(tas_priv->coef_binaryname,
704+
sizeof(tas_priv->coef_binaryname),
705+
"TAS2XXX%04X.bin",
706+
lower_16_bits(codec->core.subsystem_id));
707+
}
653708
ret = tasdevice_dsp_parser(tas_priv);
654709
if (ret) {
655710
dev_err(tas_priv->dev, "dspfw load %s error\n",

0 commit comments

Comments
 (0)