Merge series "ASoC: SOF/Intel/SoundWire: add missing quirks and DMIC support" from Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>:
HP Spectre x360 convertible devices rely on a mixed SoundWire+DMIC configuration which wasn't well supported. This lead to the discovery that we missed the TGL_HDMI quirk on a number of Dell devices, the addition of DMIC autodetection (based on NHLT tables), the addition of new component strings needed by UCM, and work-arounds due to problematic DSDT tables. Changes since v1: Rebase to remove first three patches already merged. Fix allmodconfig issues (undeclared kernel parameter) Bard Liao (1): ASoC: intel: sof_sdw: add trace for dai links Guennadi Liakhovetski (1): ASoC: SOF: Intel: HDA: don't keep a temporary variable Pierre-Louis Bossart (8): ASoC: Intel: sof_sdw: reorganize quirks by generation ASoC: Intel: sof-sdw: indent and add quirks consistently ASoC: Intel: sof_sdw: add quirk for HP Spectre x360 convertible ASoC: Intel: sof_sdw: add mic:dmic and cfg-mics component strings ASoC: Intel: soc-acpi: add ACPI matching table for HP Spectre x360 ASoC: SOF: Intel: SoundWire: refine ACPI match ASoC: SOF: Intel: detect DMIC number in SoundWire mixed config ASoC: SOF: Intel: hda: add dev_dbg() when DMIC number is overridden Rander Wang (1): ASoC: Intel: sof_sdw: detect DMIC number based on mach params sound/soc/intel/boards/sof_sdw.c | 134 ++++++----- .../intel/common/soc-acpi-intel-tgl-match.c | 20 ++ sound/soc/sof/intel/hda.c | 212 ++++++++++++------ 3 files changed, 244 insertions(+), 122 deletions(-) -- 2.25.1
This commit is contained in:
Коммит
02eb390685
|
@ -48,37 +48,14 @@ static int sof_sdw_quirk_cb(const struct dmi_system_id *id)
|
|||
}
|
||||
|
||||
static const struct dmi_system_id sof_sdw_quirk_table[] = {
|
||||
/* CometLake devices */
|
||||
{
|
||||
.callback = sof_sdw_quirk_cb,
|
||||
.matches = {
|
||||
DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"),
|
||||
DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "0A32")
|
||||
DMI_MATCH(DMI_SYS_VENDOR, "Intel Corporation"),
|
||||
DMI_MATCH(DMI_PRODUCT_NAME, "CometLake Client"),
|
||||
},
|
||||
.driver_data = (void *)(SOF_SDW_TGL_HDMI |
|
||||
SOF_RT711_JD_SRC_JD2 |
|
||||
SOF_RT715_DAI_ID_FIX |
|
||||
SOF_SDW_FOUR_SPK),
|
||||
},
|
||||
{
|
||||
.callback = sof_sdw_quirk_cb,
|
||||
.matches = {
|
||||
DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"),
|
||||
DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "0A3E")
|
||||
},
|
||||
.driver_data = (void *)(SOF_SDW_TGL_HDMI |
|
||||
SOF_RT711_JD_SRC_JD2 |
|
||||
SOF_RT715_DAI_ID_FIX),
|
||||
},
|
||||
{
|
||||
.callback = sof_sdw_quirk_cb,
|
||||
.matches = {
|
||||
DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"),
|
||||
DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "0A5E")
|
||||
},
|
||||
.driver_data = (void *)(SOF_SDW_TGL_HDMI |
|
||||
SOF_RT711_JD_SRC_JD2 |
|
||||
SOF_RT715_DAI_ID_FIX |
|
||||
SOF_SDW_FOUR_SPK),
|
||||
.driver_data = (void *)SOF_SDW_PCH_DMIC,
|
||||
},
|
||||
{
|
||||
.callback = sof_sdw_quirk_cb,
|
||||
|
@ -109,7 +86,7 @@ static const struct dmi_system_id sof_sdw_quirk_table[] = {
|
|||
SOF_RT715_DAI_ID_FIX |
|
||||
SOF_SDW_FOUR_SPK),
|
||||
},
|
||||
{
|
||||
{
|
||||
.callback = sof_sdw_quirk_cb,
|
||||
.matches = {
|
||||
DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"),
|
||||
|
@ -119,17 +96,7 @@ static const struct dmi_system_id sof_sdw_quirk_table[] = {
|
|||
SOF_RT715_DAI_ID_FIX |
|
||||
SOF_SDW_FOUR_SPK),
|
||||
},
|
||||
{
|
||||
.callback = sof_sdw_quirk_cb,
|
||||
.matches = {
|
||||
DMI_MATCH(DMI_SYS_VENDOR, "Intel Corporation"),
|
||||
DMI_MATCH(DMI_PRODUCT_NAME,
|
||||
"Tiger Lake Client Platform"),
|
||||
},
|
||||
.driver_data = (void *)(SOF_RT711_JD_SRC_JD1 |
|
||||
SOF_SDW_TGL_HDMI | SOF_SDW_PCH_DMIC |
|
||||
SOF_SSP_PORT(SOF_I2S_SSP2)),
|
||||
},
|
||||
/* IceLake devices */
|
||||
{
|
||||
.callback = sof_sdw_quirk_cb,
|
||||
.matches = {
|
||||
|
@ -138,13 +105,39 @@ static const struct dmi_system_id sof_sdw_quirk_table[] = {
|
|||
},
|
||||
.driver_data = (void *)SOF_SDW_PCH_DMIC,
|
||||
},
|
||||
/* TigerLake devices */
|
||||
{
|
||||
.callback = sof_sdw_quirk_cb,
|
||||
.matches = {
|
||||
DMI_MATCH(DMI_SYS_VENDOR, "Intel Corporation"),
|
||||
DMI_MATCH(DMI_PRODUCT_NAME, "CometLake Client"),
|
||||
DMI_MATCH(DMI_PRODUCT_NAME,
|
||||
"Tiger Lake Client Platform"),
|
||||
},
|
||||
.driver_data = (void *)SOF_SDW_PCH_DMIC,
|
||||
.driver_data = (void *)(SOF_SDW_TGL_HDMI |
|
||||
SOF_RT711_JD_SRC_JD1 |
|
||||
SOF_SDW_PCH_DMIC |
|
||||
SOF_SSP_PORT(SOF_I2S_SSP2)),
|
||||
},
|
||||
{
|
||||
.callback = sof_sdw_quirk_cb,
|
||||
.matches = {
|
||||
DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"),
|
||||
DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "0A3E")
|
||||
},
|
||||
.driver_data = (void *)(SOF_SDW_TGL_HDMI |
|
||||
SOF_RT711_JD_SRC_JD2 |
|
||||
SOF_RT715_DAI_ID_FIX),
|
||||
},
|
||||
{
|
||||
.callback = sof_sdw_quirk_cb,
|
||||
.matches = {
|
||||
DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"),
|
||||
DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "0A5E")
|
||||
},
|
||||
.driver_data = (void *)(SOF_SDW_TGL_HDMI |
|
||||
SOF_RT711_JD_SRC_JD2 |
|
||||
SOF_RT715_DAI_ID_FIX |
|
||||
SOF_SDW_FOUR_SPK),
|
||||
},
|
||||
{
|
||||
.callback = sof_sdw_quirk_cb,
|
||||
|
@ -152,7 +145,8 @@ static const struct dmi_system_id sof_sdw_quirk_table[] = {
|
|||
DMI_MATCH(DMI_SYS_VENDOR, "Google"),
|
||||
DMI_MATCH(DMI_PRODUCT_NAME, "Volteer"),
|
||||
},
|
||||
.driver_data = (void *)(SOF_SDW_TGL_HDMI | SOF_SDW_PCH_DMIC |
|
||||
.driver_data = (void *)(SOF_SDW_TGL_HDMI |
|
||||
SOF_SDW_PCH_DMIC |
|
||||
SOF_SDW_FOUR_SPK),
|
||||
},
|
||||
{
|
||||
|
@ -161,10 +155,38 @@ static const struct dmi_system_id sof_sdw_quirk_table[] = {
|
|||
DMI_MATCH(DMI_SYS_VENDOR, "Google"),
|
||||
DMI_MATCH(DMI_PRODUCT_NAME, "Ripto"),
|
||||
},
|
||||
.driver_data = (void *)(SOF_SDW_TGL_HDMI | SOF_SDW_PCH_DMIC |
|
||||
.driver_data = (void *)(SOF_SDW_TGL_HDMI |
|
||||
SOF_SDW_PCH_DMIC |
|
||||
SOF_SDW_FOUR_SPK),
|
||||
},
|
||||
{
|
||||
/*
|
||||
* this entry covers multiple HP SKUs. The family name
|
||||
* does not seem robust enough, so we use a partial
|
||||
* match that ignores the product name suffix
|
||||
* (e.g. 15-eb1xxx, 14t-ea000 or 13-aw2xxx)
|
||||
*/
|
||||
.callback = sof_sdw_quirk_cb,
|
||||
.matches = {
|
||||
DMI_MATCH(DMI_SYS_VENDOR, "HP"),
|
||||
DMI_MATCH(DMI_PRODUCT_NAME, "HP Spectre x360 Convertible"),
|
||||
},
|
||||
.driver_data = (void *)(SOF_SDW_TGL_HDMI |
|
||||
SOF_SDW_PCH_DMIC |
|
||||
SOF_RT711_JD_SRC_JD2),
|
||||
},
|
||||
/* TigerLake-SDCA devices */
|
||||
{
|
||||
.callback = sof_sdw_quirk_cb,
|
||||
.matches = {
|
||||
DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"),
|
||||
DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "0A32")
|
||||
},
|
||||
.driver_data = (void *)(SOF_SDW_TGL_HDMI |
|
||||
SOF_RT711_JD_SRC_JD2 |
|
||||
SOF_RT715_DAI_ID_FIX |
|
||||
SOF_SDW_FOUR_SPK),
|
||||
},
|
||||
|
||||
{}
|
||||
};
|
||||
|
||||
|
@ -454,15 +476,14 @@ static int get_sdw_dailink_info(const struct snd_soc_acpi_link_adr *links,
|
|||
return 0;
|
||||
}
|
||||
|
||||
static void init_dai_link(struct snd_soc_dai_link *dai_links, int be_id,
|
||||
char *name, int playback, int capture,
|
||||
struct snd_soc_dai_link_component *cpus,
|
||||
int cpus_num,
|
||||
struct snd_soc_dai_link_component *codecs,
|
||||
int codecs_num,
|
||||
static void init_dai_link(struct device *dev, struct snd_soc_dai_link *dai_links,
|
||||
int be_id, char *name, int playback, int capture,
|
||||
struct snd_soc_dai_link_component *cpus, int cpus_num,
|
||||
struct snd_soc_dai_link_component *codecs, int codecs_num,
|
||||
int (*init)(struct snd_soc_pcm_runtime *rtd),
|
||||
const struct snd_soc_ops *ops)
|
||||
{
|
||||
dev_dbg(dev, "create dai link %s, id %d\n", name, be_id);
|
||||
dai_links->id = be_id;
|
||||
dai_links->name = name;
|
||||
dai_links->platforms = platform_component;
|
||||
|
@ -800,7 +821,7 @@ static int create_sdw_dailink(struct device *dev, int *be_index,
|
|||
|
||||
playback = (stream == SNDRV_PCM_STREAM_PLAYBACK);
|
||||
capture = (stream == SNDRV_PCM_STREAM_CAPTURE);
|
||||
init_dai_link(dai_links + *be_index, *be_index, name,
|
||||
init_dai_link(dev, dai_links + *be_index, *be_index, name,
|
||||
playback, capture,
|
||||
cpus + *cpu_id, cpu_dai_num,
|
||||
codecs, codec_num,
|
||||
|
@ -933,7 +954,7 @@ static int sof_card_dai_links_create(struct device *dev,
|
|||
ctx->idisp_codec = true;
|
||||
|
||||
/* enable dmic01 & dmic16k */
|
||||
dmic_num = (sof_sdw_quirk & SOF_SDW_PCH_DMIC) ? 2 : 0;
|
||||
dmic_num = (sof_sdw_quirk & SOF_SDW_PCH_DMIC || mach_params->dmic_num) ? 2 : 0;
|
||||
comp_num += dmic_num;
|
||||
|
||||
dev_dbg(dev, "sdw %d, ssp %d, dmic %d, hdmi %d", sdw_be_num, ssp_num,
|
||||
|
@ -1039,7 +1060,7 @@ SSP:
|
|||
|
||||
playback = info->direction[SNDRV_PCM_STREAM_PLAYBACK];
|
||||
capture = info->direction[SNDRV_PCM_STREAM_CAPTURE];
|
||||
init_dai_link(links + link_id, be_id, name,
|
||||
init_dai_link(dev, links + link_id, be_id, name,
|
||||
playback, capture,
|
||||
cpus + cpu_id, 1,
|
||||
ssp_components, 1,
|
||||
|
@ -1056,7 +1077,7 @@ DMIC:
|
|||
/* dmic */
|
||||
if (dmic_num > 0) {
|
||||
cpus[cpu_id].dai_name = "DMIC01 Pin";
|
||||
init_dai_link(links + link_id, be_id, "dmic01",
|
||||
init_dai_link(dev, links + link_id, be_id, "dmic01",
|
||||
0, 1, // DMIC only supports capture
|
||||
cpus + cpu_id, 1,
|
||||
dmic_component, 1,
|
||||
|
@ -1064,7 +1085,7 @@ DMIC:
|
|||
INC_ID(be_id, cpu_id, link_id);
|
||||
|
||||
cpus[cpu_id].dai_name = "DMIC16k Pin";
|
||||
init_dai_link(links + link_id, be_id, "dmic16k",
|
||||
init_dai_link(dev, links + link_id, be_id, "dmic16k",
|
||||
0, 1, // DMIC only supports capture
|
||||
cpus + cpu_id, 1,
|
||||
dmic_component, 1,
|
||||
|
@ -1107,7 +1128,7 @@ DMIC:
|
|||
return -ENOMEM;
|
||||
|
||||
cpus[cpu_id].dai_name = cpu_name;
|
||||
init_dai_link(links + link_id, be_id, name,
|
||||
init_dai_link(dev, links + link_id, be_id, name,
|
||||
1, 0, // HDMI only supports playback
|
||||
cpus + cpu_id, 1,
|
||||
idisp_components + i, 1,
|
||||
|
@ -1200,6 +1221,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 */
|
||||
|
|
|
@ -205,6 +205,20 @@ static const struct snd_soc_acpi_link_adr tgl_rvp[] = {
|
|||
{}
|
||||
};
|
||||
|
||||
static const struct snd_soc_acpi_link_adr tgl_hp[] = {
|
||||
{
|
||||
.mask = BIT(0),
|
||||
.num_adr = ARRAY_SIZE(rt711_0_adr),
|
||||
.adr_d = rt711_0_adr,
|
||||
},
|
||||
{
|
||||
.mask = BIT(1),
|
||||
.num_adr = ARRAY_SIZE(rt1308_1_single_adr),
|
||||
.adr_d = rt1308_1_single_adr,
|
||||
},
|
||||
{}
|
||||
};
|
||||
|
||||
static const struct snd_soc_acpi_link_adr tgl_chromebook_base[] = {
|
||||
{
|
||||
.mask = BIT(0),
|
||||
|
@ -383,6 +397,12 @@ struct snd_soc_acpi_mach snd_soc_acpi_intel_tgl_sdw_machines[] = {
|
|||
.drv_name = "sof_sdw",
|
||||
.sof_tplg_filename = "sof-tgl-rt711-rt1316-rt714.tplg",
|
||||
},
|
||||
{
|
||||
.link_mask = 0x3, /* rt711 on link 0 and 1 rt1308 on link 1 */
|
||||
.links = tgl_hp,
|
||||
.drv_name = "sof_sdw",
|
||||
.sof_tplg_filename = "sof-tgl-rt711-rt1308.tplg",
|
||||
},
|
||||
{
|
||||
.link_mask = 0x3, /* rt711 on link 0 and 2 rt1308s on link 1 */
|
||||
.links = tgl_rvp,
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
|
@ -579,25 +581,76 @@ static const char *fixup_tplg_name(struct snd_sof_dev *sdev,
|
|||
const char *dmic_str)
|
||||
{
|
||||
const char *tplg_filename = NULL;
|
||||
char *filename;
|
||||
char *split_ext;
|
||||
char *filename, *tmp;
|
||||
const char *split_ext;
|
||||
|
||||
filename = devm_kstrdup(sdev->dev, sof_tplg_filename, GFP_KERNEL);
|
||||
filename = kstrdup(sof_tplg_filename, GFP_KERNEL);
|
||||
if (!filename)
|
||||
return NULL;
|
||||
|
||||
/* this assumes a .tplg extension */
|
||||
split_ext = strsep(&filename, ".");
|
||||
if (split_ext) {
|
||||
tmp = filename;
|
||||
split_ext = strsep(&tmp, ".");
|
||||
if (split_ext)
|
||||
tplg_filename = devm_kasprintf(sdev->dev, GFP_KERNEL,
|
||||
"%s%s%s.tplg",
|
||||
split_ext, idisp_str, dmic_str);
|
||||
if (!tplg_filename)
|
||||
return NULL;
|
||||
}
|
||||
kfree(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) {
|
||||
dev_dbg(sdev->dev,
|
||||
"overriding DMICs detected in NHLT tables %d by kernel param %d\n",
|
||||
dmic_num, hda_dmic_num);
|
||||
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 +1016,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 +1043,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 +1051,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 +1069,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;
|
||||
|
@ -1071,32 +1090,63 @@ static bool link_slaves_found(struct snd_sof_dev *sdev,
|
|||
struct sdw_intel_slave_id *ids = sdw->ids;
|
||||
int num_slaves = sdw->num_slaves;
|
||||
unsigned int part_id, link_id, unique_id, mfg_id;
|
||||
int i, j;
|
||||
int i, j, k;
|
||||
|
||||
for (i = 0; i < link->num_adr; i++) {
|
||||
u64 adr = link->adr_d[i].adr;
|
||||
int reported_part_count = 0;
|
||||
|
||||
mfg_id = SDW_MFG_ID(adr);
|
||||
part_id = SDW_PART_ID(adr);
|
||||
link_id = SDW_DISCO_LINK_ID(adr);
|
||||
|
||||
for (j = 0; j < num_slaves; j++) {
|
||||
/* find out how many identical parts were reported on that link */
|
||||
if (ids[j].link_id == link_id &&
|
||||
ids[j].id.part_id == part_id &&
|
||||
ids[j].id.mfg_id == mfg_id)
|
||||
reported_part_count++;
|
||||
}
|
||||
|
||||
for (j = 0; j < num_slaves; j++) {
|
||||
int expected_part_count = 0;
|
||||
|
||||
if (ids[j].link_id != link_id ||
|
||||
ids[j].id.part_id != part_id ||
|
||||
ids[j].id.mfg_id != mfg_id)
|
||||
continue;
|
||||
/*
|
||||
* we have to check unique id
|
||||
* if there is more than one
|
||||
* Slave on the link
|
||||
*/
|
||||
unique_id = SDW_UNIQUE_ID(adr);
|
||||
if (link->num_adr == 1 ||
|
||||
ids[j].id.unique_id == SDW_IGNORED_UNIQUE_ID ||
|
||||
ids[j].id.unique_id == unique_id) {
|
||||
dev_dbg(bus->dev,
|
||||
"found %x at link %d\n",
|
||||
part_id, link_id);
|
||||
break;
|
||||
|
||||
/* find out how many identical parts are expected */
|
||||
for (k = 0; k < link->num_adr; k++) {
|
||||
u64 adr2 = link->adr_d[i].adr;
|
||||
unsigned int part_id2, link_id2, mfg_id2;
|
||||
|
||||
mfg_id2 = SDW_MFG_ID(adr2);
|
||||
part_id2 = SDW_PART_ID(adr2);
|
||||
link_id2 = SDW_DISCO_LINK_ID(adr2);
|
||||
|
||||
if (link_id2 == link_id &&
|
||||
part_id2 == part_id &&
|
||||
mfg_id2 == mfg_id)
|
||||
expected_part_count++;
|
||||
}
|
||||
|
||||
if (reported_part_count == expected_part_count) {
|
||||
/*
|
||||
* we have to check unique id
|
||||
* if there is more than one
|
||||
* Slave on the link
|
||||
*/
|
||||
unique_id = SDW_UNIQUE_ID(adr);
|
||||
if (reported_part_count == 1 ||
|
||||
ids[j].id.unique_id == unique_id) {
|
||||
dev_dbg(bus->dev, "found %x at link %d\n",
|
||||
part_id, link_id);
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
dev_dbg(bus->dev, "part %x reported %d expected %d on link %d, skipping\n",
|
||||
part_id, reported_part_count, expected_part_count, link_id);
|
||||
}
|
||||
}
|
||||
if (j == num_slaves) {
|
||||
|
@ -1113,7 +1163,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;
|
||||
|
@ -1161,10 +1210,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;
|
||||
|
@ -1174,6 +1221,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");
|
||||
|
|
Загрузка…
Ссылка в новой задаче