ALSA: hda: cs35l41: Support reading subsystem id from ACPI

On some laptop models, the ACPI contains the unique
Subsystem ID, and this value should be preferred
over the value from the HDA driver.

Signed-off-by: Stefan Binding <sbinding@opensource.cirrus.com>
Signed-off-by: Vitaly Rodionov <vitalyr@opensource.cirrus.com>
Link: https://lore.kernel.org/r/20220630002335.366545-7-vitalyr@opensource.cirrus.com
Signed-off-by: Takashi Iwai <tiwai@suse.de>
This commit is contained in:
Stefan Binding 2022-06-30 01:23:27 +01:00 коммит произвёл Takashi Iwai
Родитель e99f3c7e32
Коммит eef3759602
1 изменённых файлов: 36 добавлений и 0 удалений

Просмотреть файл

@ -544,6 +544,36 @@ static int cs35l41_hda_apply_properties(struct cs35l41_hda *cs35l41)
return cs35l41_hda_channel_map(cs35l41->dev, 0, NULL, 1, &hw_cfg->spk_pos);
}
static int cs35l41_get_acpi_sub_string(struct device *dev, struct acpi_device *adev,
const char **subsysid)
{
struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
union acpi_object *obj;
acpi_status status;
int ret = 0;
status = acpi_evaluate_object(adev->handle, "_SUB", NULL, &buffer);
if (ACPI_SUCCESS(status)) {
obj = buffer.pointer;
if (obj->type == ACPI_TYPE_STRING) {
*subsysid = devm_kstrdup(dev, obj->string.pointer, GFP_KERNEL);
if (*subsysid == NULL) {
dev_err(dev, "Cannot allocate Subsystem ID");
ret = -ENOMEM;
}
} else {
dev_warn(dev, "Warning ACPI _SUB did not return a string\n");
ret = -ENODEV;
}
acpi_os_free(buffer.pointer);
} else {
dev_dbg(dev, "Warning ACPI _SUB failed: %#x\n", status);
ret = -ENODEV;
}
return ret;
}
static int cs35l41_hda_read_acpi(struct cs35l41_hda *cs35l41, const char *hid, int id)
{
struct cs35l41_hw_cfg *hw_cfg = &cs35l41->hw_cfg;
@ -563,6 +593,12 @@ static int cs35l41_hda_read_acpi(struct cs35l41_hda *cs35l41, const char *hid, i
physdev = get_device(acpi_get_first_physical_node(adev));
acpi_dev_put(adev);
ret = cs35l41_get_acpi_sub_string(cs35l41->dev, adev, &cs35l41->acpi_subsystem_id);
if (ret)
dev_info(cs35l41->dev, "No Subsystem ID found in ACPI: %d", ret);
else
dev_dbg(cs35l41->dev, "Subsystem ID %s found", cs35l41->acpi_subsystem_id);
property = "cirrus,dev-index";
ret = device_property_count_u32(physdev, property);
if (ret <= 0)