ASoC: SOF: Intel: hda: fixup HDaudio topology name with DMIC number

The SOF project maintains 6 topologies for HDaudio (iDisp or
HDaudio+iDisp, no DMIC, 2 DMICs, 4 DMICs). The user is currently
required to manually rename the topology file used in
/lib/firmware/intel/sof-tplg. We can do better to avoid such
renames and use logic to select the relevant file.

The NHLT information can be used to figure out which topology file
should be used.

Alternatively, when NHLT is not present in ACPI tables or is possibly
incorrect, a module parameter can provide that information, e.g. on
Up^2 board with the test DMIC kit.

Tested on Up^2 board and Acer Swift-SF314-55

Signed-off-by: Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>
Link: https://lore.kernel.org/r/20190812160623.20821-1-pierre-louis.bossart@linux.intel.com
Signed-off-by: Mark Brown <broonie@kernel.org>
This commit is contained in:
Pierre-Louis Bossart 2019-08-12 11:06:23 -05:00 коммит произвёл Mark Brown
Родитель 6fa4e0cae6
Коммит 68b953aeb5
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: 24D68B725D5487D0
2 изменённых файлов: 64 добавлений и 12 удалений

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

@ -254,6 +254,7 @@ config SND_SOC_SOF_HDA
tristate tristate
select SND_HDA_EXT_CORE if SND_SOC_SOF_HDA_LINK select SND_HDA_EXT_CORE if SND_SOC_SOF_HDA_LINK
select SND_SOC_HDAC_HDA if SND_SOC_SOF_HDA_AUDIO_CODEC select SND_SOC_HDAC_HDA if SND_SOC_SOF_HDA_AUDIO_CODEC
select SND_INTEL_NHLT
help help
This option is not user-selectable but automagically handled by This option is not user-selectable but automagically handled by
'select' statements at a higher level 'select' statements at a higher level

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

@ -19,6 +19,7 @@
#include <sound/hda_register.h> #include <sound/hda_register.h>
#include <linux/module.h> #include <linux/module.h>
#include <sound/intel-nhlt.h>
#include <sound/sof.h> #include <sound/sof.h>
#include <sound/sof/xtensa.h> #include <sound/sof/xtensa.h>
#include "../ops.h" #include "../ops.h"
@ -49,6 +50,12 @@ module_param_named(use_msi, hda_use_msi, bool, 0444);
MODULE_PARM_DESC(use_msi, "SOF HDA use PCI MSI mode"); MODULE_PARM_DESC(use_msi, "SOF HDA use PCI MSI mode");
#endif #endif
#if IS_ENABLED(CONFIG_SND_SOC_SOF_HDA)
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
static const struct hda_dsp_msg_code hda_dsp_rom_msg[] = { static const struct hda_dsp_msg_code hda_dsp_rom_msg[] = {
{HDA_DSP_ROM_FW_MANIFEST_LOADED, "status: manifest loaded"}, {HDA_DSP_ROM_FW_MANIFEST_LOADED, "status: manifest loaded"},
{HDA_DSP_ROM_FW_FW_LOADED, "status: fw loaded"}, {HDA_DSP_ROM_FW_FW_LOADED, "status: fw loaded"},
@ -283,8 +290,26 @@ static int hda_init(struct snd_sof_dev *sdev)
#if IS_ENABLED(CONFIG_SND_SOC_SOF_HDA) #if IS_ENABLED(CONFIG_SND_SOC_SOF_HDA)
static int check_nhlt_dmic(struct snd_sof_dev *sdev)
{
struct nhlt_acpi_table *nhlt;
int dmic_num;
nhlt = intel_nhlt_init(sdev->dev);
if (nhlt) {
dmic_num = intel_nhlt_get_dmic_geo(sdev->dev, nhlt);
intel_nhlt_free(nhlt);
if (dmic_num == 2 || dmic_num == 4)
return dmic_num;
}
return 0;
}
static const char *fixup_tplg_name(struct snd_sof_dev *sdev, static const char *fixup_tplg_name(struct snd_sof_dev *sdev,
const char *sof_tplg_filename) const char *sof_tplg_filename,
const char *idisp_str,
const char *dmic_str)
{ {
const char *tplg_filename = NULL; const char *tplg_filename = NULL;
char *filename; char *filename;
@ -298,7 +323,8 @@ static const char *fixup_tplg_name(struct snd_sof_dev *sdev,
split_ext = strsep(&filename, "."); split_ext = strsep(&filename, ".");
if (split_ext) { if (split_ext) {
tplg_filename = devm_kasprintf(sdev->dev, GFP_KERNEL, tplg_filename = devm_kasprintf(sdev->dev, GFP_KERNEL,
"%s-idisp.tplg", split_ext); "%s%s%s.tplg",
split_ext, idisp_str, dmic_str);
if (!tplg_filename) if (!tplg_filename)
return NULL; return NULL;
} }
@ -317,6 +343,9 @@ static int hda_init_caps(struct snd_sof_dev *sdev)
struct snd_sof_pdata *pdata = sdev->pdata; struct snd_sof_pdata *pdata = sdev->pdata;
struct snd_soc_acpi_mach *mach; struct snd_soc_acpi_mach *mach;
const char *tplg_filename; const char *tplg_filename;
const char *idisp_str;
const char *dmic_str;
int dmic_num;
int codec_num = 0; int codec_num = 0;
int i; int i;
#endif #endif
@ -381,17 +410,39 @@ static int hda_init_caps(struct snd_sof_dev *sdev)
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);
/* fixup topology file for HDMI only platforms */ if (codec_num == 1)
if (codec_num == 1) { idisp_str = "-idisp";
/* use local variable for readability */ else
tplg_filename = pdata->tplg_filename; idisp_str = "";
tplg_filename = fixup_tplg_name(sdev, tplg_filename);
if (!tplg_filename) { /* first check NHLT for DMICs */
hda_codec_i915_exit(sdev); dmic_num = check_nhlt_dmic(sdev);
return ret;
} /* allow for module parameter override */
pdata->tplg_filename = tplg_filename; if (hda_dmic_num != -1)
dmic_num = hda_dmic_num;
switch (dmic_num) {
case 2:
dmic_str = "-2ch";
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) {
hda_codec_i915_exit(sdev);
return ret;
}
pdata->tplg_filename = tplg_filename;
} }
} }