diff options
Diffstat (limited to 'drivers/soundwire/dmi-quirks.c')
-rw-r--r-- | drivers/soundwire/dmi-quirks.c | 96 |
1 files changed, 96 insertions, 0 deletions
diff --git a/drivers/soundwire/dmi-quirks.c b/drivers/soundwire/dmi-quirks.c new file mode 100644 index 000000000000..82061c1d9835 --- /dev/null +++ b/drivers/soundwire/dmi-quirks.c @@ -0,0 +1,96 @@ +// SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause) +// Copyright(c) 2021 Intel Corporation. + +/* + * Soundwire DMI quirks + */ + +#include <linux/device.h> +#include <linux/dmi.h> +#include <linux/soundwire/sdw.h> +#include "bus.h" + +struct adr_remap { + u64 adr; + u64 remapped_adr; +}; + +/* + * HP Spectre 360 Convertible devices do not expose the correct _ADR + * in the DSDT. + * Remap the bad _ADR values to the ones reported by hardware + */ +static const struct adr_remap hp_spectre_360[] = { + { + 0x000010025D070100, + 0x000020025D071100 + }, + { + 0x000110025d070100, + 0x000120025D130800 + }, + {} +}; + +/* + * The initial version of the Dell SKU 0A3E did not expose the devices + * on the correct links. + */ +static const struct adr_remap dell_sku_0A3E[] = { + /* rt715 on link0 */ + { + 0x00020025d071100, + 0x00021025d071500 + }, + /* rt711 on link1 */ + { + 0x000120025d130800, + 0x000120025d071100, + }, + /* rt1308 on link2 */ + { + 0x000220025d071500, + 0x000220025d130800 + }, + {} +}; + +static const struct dmi_system_id adr_remap_quirk_table[] = { + { + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "HP"), + DMI_MATCH(DMI_PRODUCT_NAME, "HP Spectre x360 Convertible"), + }, + .driver_data = (void *)hp_spectre_360, + }, + { + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"), + DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "0A3E") + }, + .driver_data = (void *)dell_sku_0A3E, + }, + {} +}; + +u64 sdw_dmi_override_adr(struct sdw_bus *bus, u64 addr) +{ + const struct dmi_system_id *dmi_id; + + /* check if any address remap quirk applies */ + dmi_id = dmi_first_match(adr_remap_quirk_table); + if (dmi_id) { + struct adr_remap *map = dmi_id->driver_data; + + for (map = dmi_id->driver_data; map->adr; map++) { + if (map->adr == addr) { + dev_dbg(bus->dev, "remapped _ADR 0x%llx as 0x%llx\n", + addr, map->remapped_adr); + addr = map->remapped_adr; + break; + } + } + } + + return addr; +} |