Commit 7aecf597 authored by Pierre-Louis Bossart's avatar Pierre-Louis Bossart Committed by Mark Brown

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: default avatarPierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>
Reviewed-by: default avatarGuennadi Liakhovetski <guennadi.liakhovetski@intel.com>
Reviewed-by: default avatarKai Vehmanen <kai.vehmanen@linux.intel.com>
Link: https://lore.kernel.org/r/20210208233336.59449-10-pierre-louis.bossart@linux.intel.comSigned-off-by: default avatarMark Brown <broonie@kernel.org>
parent 6f5d506d
...@@ -285,11 +285,13 @@ static char *hda_model; ...@@ -285,11 +285,13 @@ static char *hda_model;
module_param(hda_model, charp, 0444); module_param(hda_model, charp, 0444);
MODULE_PARM_DESC(hda_model, "Use the given HDA board model."); 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; static int hda_dmic_num = -1;
module_param_named(dmic_num, hda_dmic_num, int, 0444); module_param_named(dmic_num, hda_dmic_num, int, 0444);
MODULE_PARM_DESC(dmic_num, "SOF HDA DMIC number"); 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); 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_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"); 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) ...@@ -555,7 +557,7 @@ static int hda_init(struct snd_sof_dev *sdev)
return ret; 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) 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, ...@@ -598,6 +600,53 @@ static const char *fixup_tplg_name(struct snd_sof_dev *sdev,
return tplg_filename; 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 #endif
static int hda_init_caps(struct snd_sof_dev *sdev) 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) ...@@ -963,9 +1012,9 @@ static int hda_generic_machine_select(struct snd_sof_dev *sdev)
struct snd_sof_pdata *pdata = sdev->pdata; struct snd_sof_pdata *pdata = sdev->pdata;
const char *tplg_filename; const char *tplg_filename;
const char *idisp_str; const char *idisp_str;
const char *dmic_str;
int dmic_num = 0; int dmic_num = 0;
int codec_num = 0; int codec_num = 0;
int ret;
int i; int i;
/* codec detection */ /* codec detection */
...@@ -990,10 +1039,6 @@ static int hda_generic_machine_select(struct snd_sof_dev *sdev) ...@@ -990,10 +1039,6 @@ static int hda_generic_machine_select(struct snd_sof_dev *sdev)
if (!pdata->machine && codec_num <= 2) { if (!pdata->machine && codec_num <= 2) {
hda_mach = snd_soc_acpi_intel_hda_machines; 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", dev_info(bus->dev, "using HDA machine driver %s now\n",
hda_mach->drv_name); hda_mach->drv_name);
...@@ -1002,42 +1047,13 @@ static int hda_generic_machine_select(struct snd_sof_dev *sdev) ...@@ -1002,42 +1047,13 @@ static int hda_generic_machine_select(struct snd_sof_dev *sdev)
else else
idisp_str = ""; idisp_str = "";
/* first check NHLT for DMICs */ /* topology: use the info from hda_machines */
dmic_num = check_nhlt_dmic(sdev); tplg_filename = hda_mach->sof_tplg_filename;
ret = dmic_topology_fixup(sdev, &tplg_filename, idisp_str, &dmic_num);
/* allow for module parameter override */ if (ret < 0)
if (hda_dmic_num != -1) return ret;
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);
hda_mach->mach_params.dmic_num = dmic_num;
pdata->machine = hda_mach; pdata->machine = hda_mach;
pdata->tplg_filename = tplg_filename; pdata->tplg_filename = tplg_filename;
} }
...@@ -1049,7 +1065,6 @@ static int hda_generic_machine_select(struct snd_sof_dev *sdev) ...@@ -1049,7 +1065,6 @@ static int hda_generic_machine_select(struct snd_sof_dev *sdev)
&pdata->machine->mach_params; &pdata->machine->mach_params;
mach_params->codec_mask = bus->codec_mask; mach_params->codec_mask = bus->codec_mask;
mach_params->common_hdmi_codec_drv = hda_codec_use_common_hdmi; mach_params->common_hdmi_codec_drv = hda_codec_use_common_hdmi;
mach_params->dmic_num = dmic_num;
} }
return 0; return 0;
...@@ -1144,7 +1159,6 @@ static int hda_sdw_machine_select(struct snd_sof_dev *sdev) ...@@ -1144,7 +1159,6 @@ static int hda_sdw_machine_select(struct snd_sof_dev *sdev)
{ {
struct snd_sof_pdata *pdata = sdev->pdata; struct snd_sof_pdata *pdata = sdev->pdata;
const struct snd_soc_acpi_link_adr *link; const struct snd_soc_acpi_link_adr *link;
struct hdac_bus *bus = sof_to_bus(sdev);
struct snd_soc_acpi_mach *mach; struct snd_soc_acpi_mach *mach;
struct sof_intel_hda_dev *hdev; struct sof_intel_hda_dev *hdev;
u32 link_mask; u32 link_mask;
...@@ -1192,10 +1206,8 @@ static int hda_sdw_machine_select(struct snd_sof_dev *sdev) ...@@ -1192,10 +1206,8 @@ static int hda_sdw_machine_select(struct snd_sof_dev *sdev)
break; break;
} }
if (mach && mach->link_mask) { if (mach && mach->link_mask) {
dev_dbg(bus->dev, int dmic_num = 0;
"SoundWire machine driver %s topology %s\n",
mach->drv_name,
mach->sof_tplg_filename);
pdata->machine = mach; pdata->machine = mach;
mach->mach_params.links = mach->links; mach->mach_params.links = mach->links;
mach->mach_params.link_mask = mach->link_mask; mach->mach_params.link_mask = mach->link_mask;
...@@ -1205,6 +1217,31 @@ static int hda_sdw_machine_select(struct snd_sof_dev *sdev) ...@@ -1205,6 +1217,31 @@ static int hda_sdw_machine_select(struct snd_sof_dev *sdev)
else else
pdata->fw_filename = pdata->desc->default_fw_filename; pdata->fw_filename = pdata->desc->default_fw_filename;
pdata->tplg_filename = mach->sof_tplg_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 { } else {
dev_info(sdev->dev, dev_info(sdev->dev,
"No SoundWire machine driver found\n"); "No SoundWire machine driver found\n");
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment