From 7aecf59770920cce5ff6e94b3809574364178126 Mon Sep 17 00:00:00 2001 From: Pierre-Louis Bossart Date: Mon, 8 Feb 2021 17:33:34 -0600 Subject: 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 NHLT 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 Reviewed-by: Guennadi Liakhovetski Reviewed-by: Kai Vehmanen Link: https://lore.kernel.org/r/20210208233336.59449-10-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/intel/hda.c | 133 +++++++++++++++++++++++++++++----------------- 1 file changed, 85 insertions(+), 48 deletions(-) (limited to 'sound') diff --git a/sound/soc/sof/intel/hda.c b/sound/soc/sof/intel/hda.c index db868376039a..7ae2c2c451ef 100644 --- a/sound/soc/sof/intel/hda.c +++ b/sound/soc/sof/intel/hda.c @@ -285,11 +285,13 @@ static char *hda_model; module_param(hda_model, charp, 0444); MODULE_PARM_DESC(hda_model, "Use the given HDA board model."); -#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 hda_dmic_num = -1; module_param_named(dmic_num, hda_dmic_num, int, 0444); MODULE_PARM_DESC(dmic_num, "SOF HDA DMIC number"); +#endif +#if IS_ENABLED(CONFIG_SND_SOC_SOF_HDA) static bool hda_codec_use_common_hdmi = IS_ENABLED(CONFIG_SND_HDA_CODEC_HDMI); module_param_named(use_common_hdmi, hda_codec_use_common_hdmi, bool, 0444); MODULE_PARM_DESC(use_common_hdmi, "SOF HDA use common HDMI codec driver"); @@ -555,7 +557,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) { @@ -598,6 +600,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 *default_tplg_filename = *tplg_filename; + const char *fixed_tplg_filename; + const char *dmic_str; + 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 -ENOMEM; + + 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) @@ -963,9 +1012,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 */ @@ -990,10 +1039,6 @@ static int hda_generic_machine_select(struct snd_sof_dev *sdev) if (!pdata->machine && codec_num <= 2) { hda_mach = snd_soc_acpi_intel_hda_machines; - /* topology: use the info from hda_machines */ - pdata->tplg_filename = - hda_mach->sof_tplg_filename; - dev_info(bus->dev, "using HDA machine driver %s now\n", hda_mach->drv_name); @@ -1002,42 +1047,13 @@ 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); + /* topology: use the info from hda_machines */ + 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; } @@ -1049,7 +1065,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; @@ -1144,7 +1159,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; @@ -1192,10 +1206,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; @@ -1205,6 +1217,31 @@ 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; + + /* + * DMICs use up to 4 pins and are typically pin-muxed with SoundWire + * link 2 and 3, thus we only try to enable dmics if all conditions + * are true: + * a) link 2 and 3 are not used by SoundWire + * b) the NHLT table reports the presence of microphones + */ + 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"); -- cgit v1.2.3-70-g09d2