From 8aa7d21a6b550c05a9e64345b52969201bfefab0 Mon Sep 17 00:00:00 2001 From: Pierre-Louis Bossart Date: Tue, 19 Jan 2021 17:53:28 -0600 Subject: [PATCH 01/10] soundwire: bus: use correct driver name in error messages None of the existing codec drivers set the sdw_driver.name, but instead set sdw_driver.driver.name. This leads to error messages such as [ 23.935355] rt700 sdw:2:25d:700:0: Probe of (null) failed: -19 We could remove this sdw_driver.name if it doesn't have any purpose. This patch only suggests using the proper indirection. Signed-off-by: Pierre-Louis Bossart --- drivers/soundwire/bus_type.c | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/drivers/soundwire/bus_type.c b/drivers/soundwire/bus_type.c index 575b9bad99d510..893296f3fe395e 100644 --- a/drivers/soundwire/bus_type.c +++ b/drivers/soundwire/bus_type.c @@ -82,6 +82,7 @@ static int sdw_drv_probe(struct device *dev) struct sdw_slave *slave = dev_to_sdw_dev(dev); struct sdw_driver *drv = drv_to_sdw_driver(dev->driver); const struct sdw_device_id *id; + const char *name; int ret; /* @@ -108,7 +109,10 @@ static int sdw_drv_probe(struct device *dev) ret = drv->probe(slave, id); if (ret) { - dev_err(dev, "Probe of %s failed: %d\n", drv->name, ret); + name = drv->name; + if (!name) + name = drv->driver.name; + dev_err(dev, "Probe of %s failed: %d\n", name, ret); dev_pm_domain_detach(dev, false); return ret; } @@ -174,11 +178,16 @@ static void sdw_drv_shutdown(struct device *dev) */ int __sdw_register_driver(struct sdw_driver *drv, struct module *owner) { + const char *name; + drv->driver.bus = &sdw_bus_type; if (!drv->probe) { - pr_err("driver %s didn't provide SDW probe routine\n", - drv->name); + name = drv->name; + if (!name) + name = drv->driver.name; + + pr_err("driver %s didn't provide SDW probe routine\n", name); return -EINVAL; } From a0f08082edd14c2ac94b4c0432d0549ec1a6e803 Mon Sep 17 00:00:00 2001 From: Pierre-Louis Bossart Date: Wed, 20 Jan 2021 12:25:32 -0600 Subject: [PATCH 02/10] ASoC: codecs: rt1308-sdw: add _ADR to work-around broken DSDT On some HP devices, the DSDT does not advertise the presence of RT1308 on link1. This has been a known issue on reference platforms, but this problem was not expected to spill into commercial devices. Unfortunately the DSDT remained broken and we can't reasonably expect every Linux user to override the DSDT. This patch suggests the use of a workaround. Broken BIOS expose the part 0x701 on all links, which does not correspond to a real device or configurations. We can however use this information to make existing codec drivers probe on this device instead. A DMI-based quirk is introduce to avoid using this workaround on existing devices. BugLink: https://github.com/thesofproject/linux/issues/2700 Signed-off-by: Pierre-Louis Bossart --- sound/soc/codecs/rt1308-sdw.c | 35 +++++++++++++++++++++++++++++++++++ 1 file changed, 35 insertions(+) diff --git a/sound/soc/codecs/rt1308-sdw.c b/sound/soc/codecs/rt1308-sdw.c index afd2c3b687ccb0..25d2c0f036483e 100644 --- a/sound/soc/codecs/rt1308-sdw.c +++ b/sound/soc/codecs/rt1308-sdw.c @@ -7,6 +7,7 @@ // #include #include +#include #include #include #include @@ -668,16 +669,48 @@ static int rt1308_sdw_init(struct device *dev, struct regmap *regmap, return ret; } +#define RT701_WORKAROUND_LINK1 1 + +/* DMI quirks */ +static const struct dmi_system_id rt701_quirk_table[] = { + { + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "HP"), + DMI_MATCH(DMI_PRODUCT_NAME, "HP Spectre x360 Convertible 13-aw2xxx"), + }, + .driver_data = (void *)(RT701_WORKAROUND_LINK1), + }, + {} +}; + static int rt1308_sdw_probe(struct sdw_slave *slave, const struct sdw_device_id *id) { struct regmap *regmap; + const struct dmi_system_id *dmi_id; + unsigned long link_id; + + /* only allow BIOS work-around in specific configurations */ + if (id->part_id == 0x701) { + dmi_id = dmi_first_match(rt701_quirk_table); + if (!dmi_id) { + dev_dbg(&slave->dev, "%s: probe workaround requires DMI quirk\n", __func__); + return -ENODEV; + } + link_id = (unsigned long)dmi_id->driver_data; + if (link_id != slave->bus->link_id) { + dev_dbg(&slave->dev, "%s: probe workaround on link %d not supported\n", + __func__, slave->bus->link_id); + return -ENODEV; + } + } /* Regmap Initialization */ regmap = devm_regmap_init_sdw(slave, &rt1308_sdw_regmap); if (IS_ERR(regmap)) return PTR_ERR(regmap); + slave->id.part_id = 0x1308; rt1308_sdw_init(&slave->dev, regmap, slave); return 0; @@ -685,6 +718,8 @@ static int rt1308_sdw_probe(struct sdw_slave *slave, static const struct sdw_device_id rt1308_id[] = { SDW_SLAVE_ENTRY_EXT(0x025d, 0x1308, 0x2, 0, 0), + /* fake part_id to work-around incorrect _ADR in DSDT */ + SDW_SLAVE_ENTRY_EXT(0x025d, 0x701, 0x1, 0, 0), {}, }; MODULE_DEVICE_TABLE(sdw, rt1308_id); From 135bac8aeee1edfe4a0b91172ab719afba7c5cb3 Mon Sep 17 00:00:00 2001 From: Pierre-Louis Bossart Date: Wed, 20 Jan 2021 12:29:06 -0600 Subject: [PATCH 03/10] ASoC: codecs: rt711-sdw: add _ADR to work-around broken DSDT On some HP devices, the DSDT does not advertise the presence of RT711 on link0. This has been a known issue on reference platforms, but this problem was not expected to spill into commercial devices. Unfortunately the DSDT remained broken and we can't reasonably expect every Linux user to override the DSDT. This patch suggests the use of a workaround. Broken BIOS expose the part 0x701 on all links, which does not correspond to a real device or configurations. We can however use this information to make existing codec drivers probe on this device instead. A DMI-based quirk is introduce to avoid using this workaround on existing devices. BugLink: https://github.com/thesofproject/linux/issues/2700 Signed-off-by: Pierre-Louis Bossart --- sound/soc/codecs/rt711-sdw.c | 36 ++++++++++++++++++++++++++++++++++++ 1 file changed, 36 insertions(+) diff --git a/sound/soc/codecs/rt711-sdw.c b/sound/soc/codecs/rt711-sdw.c index 2beb4286d997bf..41ece32ee9bb8f 100644 --- a/sound/soc/codecs/rt711-sdw.c +++ b/sound/soc/codecs/rt711-sdw.c @@ -8,6 +8,7 @@ #include #include +#include #include #include #include @@ -438,10 +439,42 @@ static struct sdw_slave_ops rt711_slave_ops = { .bus_config = rt711_bus_config, }; +#define RT701_WORKAROUND_LINK0 0 + +/* DMI quirks */ +static const struct dmi_system_id rt701_quirk_table[] = { + { + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "HP"), + DMI_MATCH(DMI_PRODUCT_NAME, "HP Spectre x360 Convertible 13-aw2xxx"), + }, + .driver_data = (void *)(RT701_WORKAROUND_LINK0), + + }, + {} +}; + static int rt711_sdw_probe(struct sdw_slave *slave, const struct sdw_device_id *id) { struct regmap *sdw_regmap, *regmap; + const struct dmi_system_id *dmi_id; + unsigned long link_id; + + /* only allow BIOS work-around in specific configurations */ + if (id->part_id == 0x701) { + dmi_id = dmi_first_match(rt701_quirk_table); + if (!dmi_id) { + dev_dbg(&slave->dev, "%s: probe workaround requires DMI quirk\n", __func__); + return -ENODEV; + } + link_id = (unsigned long)dmi_id->driver_data; + if (link_id != slave->bus->link_id) { + dev_dbg(&slave->dev, "%s: probe workaround on link %d not supported\n", + __func__, slave->bus->link_id); + return -ENODEV; + } + } /* Regmap Initialization */ sdw_regmap = devm_regmap_init_sdw(slave, &rt711_sdw_regmap); @@ -453,6 +486,7 @@ static int rt711_sdw_probe(struct sdw_slave *slave, if (IS_ERR(regmap)) return PTR_ERR(regmap); + slave->id.part_id = 0x711; rt711_init(&slave->dev, sdw_regmap, regmap, slave); return 0; @@ -473,6 +507,8 @@ static int rt711_sdw_remove(struct sdw_slave *slave) static const struct sdw_device_id rt711_id[] = { SDW_SLAVE_ENTRY_EXT(0x025d, 0x711, 0x2, 0, 0), + /* fake part_id to work-around incorrect _ADR in DSDT */ + SDW_SLAVE_ENTRY_EXT(0x025d, 0x701, 0x1, 0, 0), {}, }; MODULE_DEVICE_TABLE(sdw, rt711_id); From fde3d442130cdc47e38621e01b81d9eb87443bb8 Mon Sep 17 00:00:00 2001 From: Pierre-Louis Bossart Date: Wed, 20 Jan 2021 12:07:34 -0600 Subject: [PATCH 04/10] ASoC: soc-acpi: add new field to override bad _ADR In some platforms, we need to alias the _ADR provided by the DSDT tables to one that is expected and handled by machine drivers. The 'adr_override' field will replace the information from BIOS. BugLink: https://github.com/thesofproject/linux/issues/2700 Signed-off-by: Pierre-Louis Bossart --- include/sound/soc-acpi.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/include/sound/soc-acpi.h b/include/sound/soc-acpi.h index 9a43c44dcbbbaa..ed92ff2573dee4 100644 --- a/include/sound/soc-acpi.h +++ b/include/sound/soc-acpi.h @@ -91,12 +91,14 @@ struct snd_soc_acpi_endpoint { /** * snd_soc_acpi_adr_device - descriptor for _ADR-enumerated device * @adr: 64 bit ACPI _ADR value + * @adr_override: used when @adr is not correct in platform firmware * @num_endpoints: number of endpoints for this device * @endpoints: array of endpoints * @name_prefix: string used for codec controls */ struct snd_soc_acpi_adr_device { const u64 adr; + const u64 adr_override; const u8 num_endpoints; const struct snd_soc_acpi_endpoint *endpoints; const char *name_prefix; From f89f655bbf184adb1310da758c80b72548d40ad6 Mon Sep 17 00:00:00 2001 From: Pierre-Louis Bossart Date: Wed, 20 Jan 2021 12:30:33 -0600 Subject: [PATCH 05/10] ASoC: Intel: soc-acpi-match: add workaround for TGL platform Add alias for HP platform, the DSDT exposes RT701 devices that are not physically present and can be aliased into what RT711 (link0) and RT1308 (link1). Unfortunately we have existing platforms where the workaround appliesd, so at this point we have no choice but limit this workaround with a DMI quirk. BugLink: https://github.com/thesofproject/linux/issues/2700 Signed-off-by: Pierre-Louis Bossart --- .../intel/common/soc-acpi-intel-tgl-match.c | 66 +++++++++++++++++++ 1 file changed, 66 insertions(+) diff --git a/sound/soc/intel/common/soc-acpi-intel-tgl-match.c b/sound/soc/intel/common/soc-acpi-intel-tgl-match.c index e3ddbf05bf7296..fd438638dd3aeb 100644 --- a/sound/soc/intel/common/soc-acpi-intel-tgl-match.c +++ b/sound/soc/intel/common/soc-acpi-intel-tgl-match.c @@ -6,6 +6,7 @@ * */ +#include #include #include @@ -44,6 +45,16 @@ static const struct snd_soc_acpi_adr_device rt711_0_adr[] = { } }; +static const struct snd_soc_acpi_adr_device workaround_rt711_0_adr[] = { + { + .adr = 0x000010025D070100, + .adr_override = 0x000020025D071100, /* same as rt711_0_adr */ + .num_endpoints = 1, + .endpoints = &single_endpoint, + .name_prefix = "rt711" + } +}; + static const struct snd_soc_acpi_adr_device rt711_1_adr[] = { { .adr = 0x000120025D071100, @@ -77,6 +88,16 @@ static const struct snd_soc_acpi_adr_device rt1308_1_single_adr[] = { } }; +static const struct snd_soc_acpi_adr_device workaround_rt1308_1_single_adr[] = { + { + .adr = 0x000110025d070100, + .adr_override = 0x000120025D130800, /* same as rt1308_1_single_adr */ + .num_endpoints = 1, + .endpoints = &single_endpoint, + .name_prefix = "rt1308-1" + } +}; + static const struct snd_soc_acpi_adr_device rt1308_2_single_adr[] = { { .adr = 0x000220025D130800, @@ -281,6 +302,20 @@ static const struct snd_soc_acpi_link_adr tgl_sdw_rt711_link1_rt1308_link2_rt715 {} }; +static const struct snd_soc_acpi_link_adr workaround_tgl_hp[] = { + { + .mask = BIT(0), + .num_adr = ARRAY_SIZE(workaround_rt711_0_adr), + .adr_d = workaround_rt711_0_adr, + }, + { + .mask = BIT(1), + .num_adr = ARRAY_SIZE(workaround_rt1308_1_single_adr), + .adr_d = workaround_rt1308_1_single_adr, + }, + {} +}; + static const struct snd_soc_acpi_link_adr tgl_3_in_1_sdca[] = { { .mask = BIT(0), @@ -352,6 +387,29 @@ struct snd_soc_acpi_mach snd_soc_acpi_intel_tgl_machines[] = { }; EXPORT_SYMBOL_GPL(snd_soc_acpi_intel_tgl_machines); +/* DMI quirks */ +static const struct dmi_system_id tgl_quirk_table[] = { + { + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "HP"), + DMI_MATCH(DMI_PRODUCT_NAME, "HP Spectre x360 Convertible 13-aw2xxx"), + }, + }, + {} +}; + +static struct snd_soc_acpi_mach *tgl_quirk(void *arg) +{ + struct snd_soc_acpi_mach *mach = arg; + const struct dmi_system_id *dmi_id; + + dmi_id = dmi_first_match(tgl_quirk_table); + if (!dmi_id) + return NULL; + + return mach; +} + /* this table is used when there is no I2S codec present */ struct snd_soc_acpi_mach snd_soc_acpi_intel_tgl_sdw_machines[] = { { @@ -401,6 +459,14 @@ struct snd_soc_acpi_mach snd_soc_acpi_intel_tgl_sdw_machines[] = { .drv_name = "sof_sdw", .sof_tplg_filename = "sof-tgl-rt5682.tplg", }, + /* workaround, this shall remain last to avoid matching on the wrong platforms */ + { + .link_mask = 0x3, /* rt711 on link 0 and rt1308 on link 1 */ + .links = workaround_tgl_hp, + .machine_quirk = tgl_quirk, + .drv_name = "sof_sdw", + .sof_tplg_filename = "sof-tgl-rt711-rt1308.tplg", + }, {}, }; EXPORT_SYMBOL_GPL(snd_soc_acpi_intel_tgl_sdw_machines); From b9ad42375d1e4383a4073aac856d782d254edc7c Mon Sep 17 00:00:00 2001 From: Pierre-Louis Bossart Date: Wed, 20 Jan 2021 12:21:05 -0600 Subject: [PATCH 06/10] ASoC: Intel: sof_sdw: add support for _ADR override Make sure we use the information needed by the machine driver, after the _ADR override. BugLink: https://github.com/thesofproject/linux/issues/2700 Signed-off-by: Pierre-Louis Bossart --- sound/soc/intel/boards/sof_sdw.c | 31 ++++++++++++++++++++++++++++--- 1 file changed, 28 insertions(+), 3 deletions(-) diff --git a/sound/soc/intel/boards/sof_sdw.c b/sound/soc/intel/boards/sof_sdw.c index 6daee89bb19da2..6f229a2875a79f 100644 --- a/sound/soc/intel/boards/sof_sdw.c +++ b/sound/soc/intel/boards/sof_sdw.c @@ -424,7 +424,11 @@ static int get_sdw_dailink_info(const struct snd_soc_acpi_link_adr *links, int stream; u64 adr; - adr = link->adr_d->adr; + if (link->adr_d->adr_override) + adr = link->adr_d->adr_override; + else + adr = link->adr_d->adr; + codec_index = find_codec_info_part(adr); if (codec_index < 0) return codec_index; @@ -562,6 +566,15 @@ static int create_codec_dai_name(struct device *dev, if (!codec[comp_index].name) return -ENOMEM; + /* + * special case: we override the _ADR only here since + * the codec component name above needs to use a name + * made after the firmware _ADR. All other case + * override the _ADR directly. + */ + if (link->adr_d[i].adr_override) + adr = link->adr_d[i].adr_override; + codec_index = find_codec_info_part(adr); if (codec_index < 0) return codec_index; @@ -592,8 +605,14 @@ static int set_codec_init_func(const struct snd_soc_acpi_link_adr *link, */ for (i = 0; i < link->num_adr; i++) { int codec_index; + u64 adr; - codec_index = find_codec_info_part(link->adr_d[i].adr); + if (link->adr_d[i].adr_override) + adr = link->adr_d[i].adr_override; + else + adr = link->adr_d[i].adr; + + codec_index = find_codec_info_part(adr); if (codec_index < 0) return codec_index; @@ -707,6 +726,7 @@ static int create_sdw_dailink(struct device *dev, int *be_index, int codec_num; int stream; int ret; + u64 adr; int k; ret = get_slave_info(link, dev, cpu_dai_id, &cpu_dai_num, &codec_num, @@ -743,7 +763,12 @@ static int create_sdw_dailink(struct device *dev, int *be_index, } /* find codec info to create BE DAI */ - codec_index = find_codec_info_part(link->adr_d[0].adr); + if (link->adr_d[0].adr_override) + adr = link->adr_d[0].adr_override; + else + adr = link->adr_d[0].adr; + + codec_index = find_codec_info_part(adr); if (codec_index < 0) return codec_index; From cb037ab0e4d0bb5492a231ea011592b79f9bdf94 Mon Sep 17 00:00:00 2001 From: Pierre-Louis Bossart Date: Thu, 21 Jan 2021 09:19:40 -0600 Subject: [PATCH 07/10] ASoC: Intel: sof_sdw: add quirk for HP Spectre x360 This device has SoundWire support along with DMICs. Signed-off-by: Pierre-Louis Bossart --- sound/soc/intel/boards/sof_sdw.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/sound/soc/intel/boards/sof_sdw.c b/sound/soc/intel/boards/sof_sdw.c index 6f229a2875a79f..6c684cc5ac2a21 100644 --- a/sound/soc/intel/boards/sof_sdw.c +++ b/sound/soc/intel/boards/sof_sdw.c @@ -161,7 +161,15 @@ static const struct dmi_system_id sof_sdw_quirk_table[] = { .driver_data = (void *)(SOF_SDW_TGL_HDMI | SOF_SDW_PCH_DMIC | SOF_SDW_FOUR_SPK), }, - + { + .callback = sof_sdw_quirk_cb, + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "HP"), + DMI_MATCH(DMI_PRODUCT_NAME, "HP Spectre x360 Convertible 13-aw2xxx"), + }, + .driver_data = (void *)(SOF_SDW_TGL_HDMI | SOF_SDW_PCH_DMIC | + SOF_RT711_JD_SRC_JD2), + }, {} }; From 46e8619dbf305c00c7c05435b8cc56bc9a9471a8 Mon Sep 17 00:00:00 2001 From: Pierre-Louis Bossart Date: Wed, 20 Jan 2021 18:36:19 -0600 Subject: [PATCH 08/10] ASoC: SOF: Intel: detect DMIC number in SoundWire mixed config The pinmux allows for 2 SoundWire links to be enabled along with DMICs. This was the default configuration on the TGL-RVP. One issue with this configuration is that we don't have a means to automatically detect how many DMICs are used, which in turn requires the user to manually rename the topology file required on a platform. This was borderline acceptable for Intel RVPs, but now that this configuration is present in HP devices we need to automate the process. This patch makes use of the NHTL information and will pass the DMIC number to the machine driver as a parameter. A follow-up patch will expose the DMIC number to userspace/UCM with the configuration strings. The Google devices do make use of DMICs instead of SoundWire link 2 and 3, but their topology is unique enough that they do not need any NHTL support or topology renaming. Signed-off-by: Pierre-Louis Bossart --- sound/soc/sof/intel/hda.c | 121 ++++++++++++++++++++++++-------------- 1 file changed, 76 insertions(+), 45 deletions(-) diff --git a/sound/soc/sof/intel/hda.c b/sound/soc/sof/intel/hda.c index 14ce0f731c688c..5b0f2117e06865 100644 --- a/sound/soc/sof/intel/hda.c +++ b/sound/soc/sof/intel/hda.c @@ -505,7 +505,7 @@ static int hda_init(struct snd_sof_dev *sdev) return ret; } -#if IS_ENABLED(CONFIG_SND_SOC_SOF_HDA) +#if IS_ENABLED(CONFIG_SND_SOC_SOF_HDA) || IS_ENABLED(CONFIG_SND_SOC_SOF_INTEL_SOUNDWIRE) static int check_nhlt_dmic(struct snd_sof_dev *sdev) { @@ -548,6 +548,53 @@ static const char *fixup_tplg_name(struct snd_sof_dev *sdev, return tplg_filename; } +static int dmic_topology_fixup(struct snd_sof_dev *sdev, + const char **tplg_filename, + const char *idisp_str, + int *dmic_found) +{ + const char *dmic_str; + const char *default_tplg_filename = *tplg_filename; + const char *fixed_tplg_filename; + int dmic_num; + + /* first check NHLT for DMICs */ + dmic_num = check_nhlt_dmic(sdev); + + /* allow for module parameter override */ + if (hda_dmic_num != -1) + dmic_num = hda_dmic_num; + + switch (dmic_num) { + case 1: + dmic_str = "-1ch"; + break; + case 2: + dmic_str = "-2ch"; + break; + case 3: + dmic_str = "-3ch"; + break; + case 4: + dmic_str = "-4ch"; + break; + default: + dmic_num = 0; + dmic_str = ""; + break; + } + + fixed_tplg_filename = fixup_tplg_name(sdev, default_tplg_filename, + idisp_str, dmic_str); + if (!fixed_tplg_filename) + return -EINVAL; + + dev_info(sdev->dev, "DMICs detected in NHLT tables: %d\n", dmic_num); + *dmic_found = dmic_num; + *tplg_filename = fixed_tplg_filename; + + return 0; +} #endif static int hda_init_caps(struct snd_sof_dev *sdev) @@ -917,9 +964,9 @@ static int hda_generic_machine_select(struct snd_sof_dev *sdev) struct snd_sof_pdata *pdata = sdev->pdata; const char *tplg_filename; const char *idisp_str; - const char *dmic_str; int dmic_num = 0; int codec_num = 0; + int ret; int i; /* codec detection */ @@ -945,8 +992,7 @@ static int hda_generic_machine_select(struct snd_sof_dev *sdev) hda_mach = snd_soc_acpi_intel_hda_machines; /* topology: use the info from hda_machines */ - pdata->tplg_filename = - hda_mach->sof_tplg_filename; + pdata->tplg_filename = hda_mach->sof_tplg_filename; dev_info(bus->dev, "using HDA machine driver %s now\n", hda_mach->drv_name); @@ -956,42 +1002,12 @@ static int hda_generic_machine_select(struct snd_sof_dev *sdev) else idisp_str = ""; - /* first check NHLT for DMICs */ - dmic_num = check_nhlt_dmic(sdev); - - /* allow for module parameter override */ - if (hda_dmic_num != -1) - dmic_num = hda_dmic_num; - - switch (dmic_num) { - case 1: - dmic_str = "-1ch"; - break; - case 2: - dmic_str = "-2ch"; - break; - case 3: - dmic_str = "-3ch"; - break; - case 4: - dmic_str = "-4ch"; - break; - default: - dmic_num = 0; - dmic_str = ""; - break; - } - - tplg_filename = pdata->tplg_filename; - tplg_filename = fixup_tplg_name(sdev, tplg_filename, - idisp_str, dmic_str); - if (!tplg_filename) - return -EINVAL; - - dev_info(bus->dev, - "DMICs detected in NHLT tables: %d\n", - dmic_num); + tplg_filename = hda_mach->sof_tplg_filename; + ret = dmic_topology_fixup(sdev, &tplg_filename, idisp_str, &dmic_num); + if (ret < 0) + return ret; + hda_mach->mach_params.dmic_num = dmic_num; pdata->machine = hda_mach; pdata->tplg_filename = tplg_filename; } @@ -1003,7 +1019,6 @@ static int hda_generic_machine_select(struct snd_sof_dev *sdev) &pdata->machine->mach_params; mach_params->codec_mask = bus->codec_mask; mach_params->common_hdmi_codec_drv = hda_codec_use_common_hdmi; - mach_params->dmic_num = dmic_num; } return 0; @@ -1067,7 +1082,6 @@ static int hda_sdw_machine_select(struct snd_sof_dev *sdev) { struct snd_sof_pdata *pdata = sdev->pdata; const struct snd_soc_acpi_link_adr *link; - struct hdac_bus *bus = sof_to_bus(sdev); struct snd_soc_acpi_mach *mach; struct sof_intel_hda_dev *hdev; u32 link_mask; @@ -1115,10 +1129,8 @@ static int hda_sdw_machine_select(struct snd_sof_dev *sdev) break; } if (mach && mach->link_mask) { - dev_dbg(bus->dev, - "SoundWire machine driver %s topology %s\n", - mach->drv_name, - mach->sof_tplg_filename); + int dmic_num = 0; + pdata->machine = mach; mach->mach_params.links = mach->links; mach->mach_params.link_mask = mach->link_mask; @@ -1128,6 +1140,25 @@ static int hda_sdw_machine_select(struct snd_sof_dev *sdev) else pdata->fw_filename = pdata->desc->default_fw_filename; pdata->tplg_filename = mach->sof_tplg_filename; + + /* see if DMICs are pin-muxed with SoundWire link 2 and 3 */ + if (!(mach->link_mask & GENMASK(3, 2))) { + const char *tplg_filename = mach->sof_tplg_filename; + int ret; + + ret = dmic_topology_fixup(sdev, &tplg_filename, "", &dmic_num); + + if (ret < 0) + return ret; + + pdata->tplg_filename = tplg_filename; + } + mach->mach_params.dmic_num = dmic_num; + + dev_dbg(sdev->dev, + "SoundWire machine driver %s topology %s\n", + mach->drv_name, + pdata->tplg_filename); } else { dev_info(sdev->dev, "No SoundWire machine driver found\n"); From 226d5d00a8d2a9dafa2bb19ed5cd81f820592ef8 Mon Sep 17 00:00:00 2001 From: Pierre-Louis Bossart Date: Thu, 21 Jan 2021 10:22:30 -0600 Subject: [PATCH 09/10] ASoC: SOF: Intel: add machine_quirk checks for SoundWire machines We've used the machine_quirk field for I2C/I2S-based devices in the past to work-around bad information in the DSDT. Unfortunately we have now bad information in the DSDT for SoundWire devices, and we need to apply the same tricks Signed-off-by: Pierre-Louis Bossart --- sound/soc/sof/intel/hda.c | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/sound/soc/sof/intel/hda.c b/sound/soc/sof/intel/hda.c index 5b0f2117e06865..c000a01d8a7a18 100644 --- a/sound/soc/sof/intel/hda.c +++ b/sound/soc/sof/intel/hda.c @@ -1125,8 +1125,18 @@ static int hda_sdw_machine_select(struct snd_sof_dev *sdev) break; } /* Found if all Slaves are checked */ - if (i == hdev->info.count || !link->num_adr) + if (i == hdev->info.count || !link->num_adr) { + /* last paranoia check on machine_quirk */ + if (mach->machine_quirk) { + struct snd_soc_acpi_mach *mach_alt; + + mach_alt = mach->machine_quirk(mach); + if (!mach_alt) + continue; /* not full match, ignore */ + mach = mach_alt; + } break; + } } if (mach && mach->link_mask) { int dmic_num = 0; From c3c75fc65a1ea1ec3c1bdff5ac1728f9054d077b Mon Sep 17 00:00:00 2001 From: Pierre-Louis Bossart Date: Thu, 21 Jan 2021 10:50:58 -0600 Subject: [PATCH 10/10] ASoC: Intel: sof_sdw: add mic:dmic and cfg-mics component strings UCM needs to know which microphone is used (dmic or RT715-based), let's add the information in the component string. Note the slight change from HDAudio platforms, 'cfg-mics' is used here with the intent that this component string describes either PCH-attached microphones or RT715-attached ones. Signed-off-by: Pierre-Louis Bossart --- sound/soc/intel/boards/sof_sdw.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/sound/soc/intel/boards/sof_sdw.c b/sound/soc/intel/boards/sof_sdw.c index 6c684cc5ac2a21..6b5c227cec6353 100644 --- a/sound/soc/intel/boards/sof_sdw.c +++ b/sound/soc/intel/boards/sof_sdw.c @@ -1230,6 +1230,15 @@ static int mc_probe(struct platform_device *pdev) if (!card->components) return -ENOMEM; + if (mach->mach_params.dmic_num) { + card->components = devm_kasprintf(card->dev, GFP_KERNEL, + "%s mic:dmic cfg-mics:%d", + card->components, + mach->mach_params.dmic_num); + if (!card->components) + return -ENOMEM; + } + card->long_name = sdw_card_long_name; /* Register the card */