Commit 02eb3906 authored by Mark Brown's avatar Mark Brown

Merge series "ASoC: SOF/Intel/SoundWire: add missing quirks and DMIC support"...

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
parents 271d9373 026370cb
...@@ -48,37 +48,14 @@ static int sof_sdw_quirk_cb(const struct dmi_system_id *id) ...@@ -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[] = { static const struct dmi_system_id sof_sdw_quirk_table[] = {
/* CometLake devices */
{ {
.callback = sof_sdw_quirk_cb, .callback = sof_sdw_quirk_cb,
.matches = { .matches = {
DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"), DMI_MATCH(DMI_SYS_VENDOR, "Intel Corporation"),
DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "0A32") 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 | .driver_data = (void *)SOF_SDW_PCH_DMIC,
SOF_RT711_JD_SRC_JD2 |
SOF_RT715_DAI_ID_FIX |
SOF_SDW_FOUR_SPK),
}, },
{ {
.callback = sof_sdw_quirk_cb, .callback = sof_sdw_quirk_cb,
...@@ -109,7 +86,7 @@ static const struct dmi_system_id sof_sdw_quirk_table[] = { ...@@ -109,7 +86,7 @@ static const struct dmi_system_id sof_sdw_quirk_table[] = {
SOF_RT715_DAI_ID_FIX | SOF_RT715_DAI_ID_FIX |
SOF_SDW_FOUR_SPK), SOF_SDW_FOUR_SPK),
}, },
{ {
.callback = sof_sdw_quirk_cb, .callback = sof_sdw_quirk_cb,
.matches = { .matches = {
DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"), DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"),
...@@ -119,6 +96,16 @@ static const struct dmi_system_id sof_sdw_quirk_table[] = { ...@@ -119,6 +96,16 @@ static const struct dmi_system_id sof_sdw_quirk_table[] = {
SOF_RT715_DAI_ID_FIX | SOF_RT715_DAI_ID_FIX |
SOF_SDW_FOUR_SPK), SOF_SDW_FOUR_SPK),
}, },
/* IceLake devices */
{
.callback = sof_sdw_quirk_cb,
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "Intel Corporation"),
DMI_MATCH(DMI_PRODUCT_NAME, "Ice Lake Client"),
},
.driver_data = (void *)SOF_SDW_PCH_DMIC,
},
/* TigerLake devices */
{ {
.callback = sof_sdw_quirk_cb, .callback = sof_sdw_quirk_cb,
.matches = { .matches = {
...@@ -126,25 +113,31 @@ static const struct dmi_system_id sof_sdw_quirk_table[] = { ...@@ -126,25 +113,31 @@ static const struct dmi_system_id sof_sdw_quirk_table[] = {
DMI_MATCH(DMI_PRODUCT_NAME, DMI_MATCH(DMI_PRODUCT_NAME,
"Tiger Lake Client Platform"), "Tiger Lake Client Platform"),
}, },
.driver_data = (void *)(SOF_RT711_JD_SRC_JD1 | .driver_data = (void *)(SOF_SDW_TGL_HDMI |
SOF_SDW_TGL_HDMI | SOF_SDW_PCH_DMIC | SOF_RT711_JD_SRC_JD1 |
SOF_SSP_PORT(SOF_I2S_SSP2)), SOF_SDW_PCH_DMIC |
SOF_SSP_PORT(SOF_I2S_SSP2)),
}, },
{ {
.callback = sof_sdw_quirk_cb, .callback = sof_sdw_quirk_cb,
.matches = { .matches = {
DMI_MATCH(DMI_SYS_VENDOR, "Intel Corporation"), DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"),
DMI_MATCH(DMI_PRODUCT_NAME, "Ice Lake Client"), DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "0A3E")
}, },
.driver_data = (void *)SOF_SDW_PCH_DMIC, .driver_data = (void *)(SOF_SDW_TGL_HDMI |
SOF_RT711_JD_SRC_JD2 |
SOF_RT715_DAI_ID_FIX),
}, },
{ {
.callback = sof_sdw_quirk_cb, .callback = sof_sdw_quirk_cb,
.matches = { .matches = {
DMI_MATCH(DMI_SYS_VENDOR, "Intel Corporation"), DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"),
DMI_MATCH(DMI_PRODUCT_NAME, "CometLake Client"), DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "0A5E")
}, },
.driver_data = (void *)SOF_SDW_PCH_DMIC, .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, .callback = sof_sdw_quirk_cb,
...@@ -152,7 +145,8 @@ static const struct dmi_system_id sof_sdw_quirk_table[] = { ...@@ -152,7 +145,8 @@ static const struct dmi_system_id sof_sdw_quirk_table[] = {
DMI_MATCH(DMI_SYS_VENDOR, "Google"), DMI_MATCH(DMI_SYS_VENDOR, "Google"),
DMI_MATCH(DMI_PRODUCT_NAME, "Volteer"), 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), SOF_SDW_FOUR_SPK),
}, },
{ {
...@@ -161,10 +155,38 @@ static const struct dmi_system_id sof_sdw_quirk_table[] = { ...@@ -161,10 +155,38 @@ static const struct dmi_system_id sof_sdw_quirk_table[] = {
DMI_MATCH(DMI_SYS_VENDOR, "Google"), DMI_MATCH(DMI_SYS_VENDOR, "Google"),
DMI_MATCH(DMI_PRODUCT_NAME, "Ripto"), 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), SOF_SDW_FOUR_SPK),
}, },
{} {}
}; };
...@@ -454,15 +476,14 @@ static int get_sdw_dailink_info(const struct snd_soc_acpi_link_adr *links, ...@@ -454,15 +476,14 @@ static int get_sdw_dailink_info(const struct snd_soc_acpi_link_adr *links,
return 0; return 0;
} }
static void init_dai_link(struct snd_soc_dai_link *dai_links, int be_id, static void init_dai_link(struct device *dev, struct snd_soc_dai_link *dai_links,
char *name, int playback, int capture, int be_id, char *name, int playback, int capture,
struct snd_soc_dai_link_component *cpus, struct snd_soc_dai_link_component *cpus, int cpus_num,
int cpus_num, struct snd_soc_dai_link_component *codecs, int codecs_num,
struct snd_soc_dai_link_component *codecs,
int codecs_num,
int (*init)(struct snd_soc_pcm_runtime *rtd), int (*init)(struct snd_soc_pcm_runtime *rtd),
const struct snd_soc_ops *ops) 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->id = be_id;
dai_links->name = name; dai_links->name = name;
dai_links->platforms = platform_component; dai_links->platforms = platform_component;
...@@ -800,7 +821,7 @@ static int create_sdw_dailink(struct device *dev, int *be_index, ...@@ -800,7 +821,7 @@ static int create_sdw_dailink(struct device *dev, int *be_index,
playback = (stream == SNDRV_PCM_STREAM_PLAYBACK); playback = (stream == SNDRV_PCM_STREAM_PLAYBACK);
capture = (stream == SNDRV_PCM_STREAM_CAPTURE); 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, playback, capture,
cpus + *cpu_id, cpu_dai_num, cpus + *cpu_id, cpu_dai_num,
codecs, codec_num, codecs, codec_num,
...@@ -933,7 +954,7 @@ static int sof_card_dai_links_create(struct device *dev, ...@@ -933,7 +954,7 @@ static int sof_card_dai_links_create(struct device *dev,
ctx->idisp_codec = true; ctx->idisp_codec = true;
/* enable dmic01 & dmic16k */ /* 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; comp_num += dmic_num;
dev_dbg(dev, "sdw %d, ssp %d, dmic %d, hdmi %d", sdw_be_num, ssp_num, dev_dbg(dev, "sdw %d, ssp %d, dmic %d, hdmi %d", sdw_be_num, ssp_num,
...@@ -1039,7 +1060,7 @@ static int sof_card_dai_links_create(struct device *dev, ...@@ -1039,7 +1060,7 @@ static int sof_card_dai_links_create(struct device *dev,
playback = info->direction[SNDRV_PCM_STREAM_PLAYBACK]; playback = info->direction[SNDRV_PCM_STREAM_PLAYBACK];
capture = info->direction[SNDRV_PCM_STREAM_CAPTURE]; 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, playback, capture,
cpus + cpu_id, 1, cpus + cpu_id, 1,
ssp_components, 1, ssp_components, 1,
...@@ -1056,7 +1077,7 @@ static int sof_card_dai_links_create(struct device *dev, ...@@ -1056,7 +1077,7 @@ static int sof_card_dai_links_create(struct device *dev,
/* dmic */ /* dmic */
if (dmic_num > 0) { if (dmic_num > 0) {
cpus[cpu_id].dai_name = "DMIC01 Pin"; 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 0, 1, // DMIC only supports capture
cpus + cpu_id, 1, cpus + cpu_id, 1,
dmic_component, 1, dmic_component, 1,
...@@ -1064,7 +1085,7 @@ static int sof_card_dai_links_create(struct device *dev, ...@@ -1064,7 +1085,7 @@ static int sof_card_dai_links_create(struct device *dev,
INC_ID(be_id, cpu_id, link_id); INC_ID(be_id, cpu_id, link_id);
cpus[cpu_id].dai_name = "DMIC16k Pin"; 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 0, 1, // DMIC only supports capture
cpus + cpu_id, 1, cpus + cpu_id, 1,
dmic_component, 1, dmic_component, 1,
...@@ -1107,7 +1128,7 @@ static int sof_card_dai_links_create(struct device *dev, ...@@ -1107,7 +1128,7 @@ static int sof_card_dai_links_create(struct device *dev,
return -ENOMEM; return -ENOMEM;
cpus[cpu_id].dai_name = cpu_name; 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 1, 0, // HDMI only supports playback
cpus + cpu_id, 1, cpus + cpu_id, 1,
idisp_components + i, 1, idisp_components + i, 1,
...@@ -1200,6 +1221,15 @@ static int mc_probe(struct platform_device *pdev) ...@@ -1200,6 +1221,15 @@ static int mc_probe(struct platform_device *pdev)
if (!card->components) if (!card->components)
return -ENOMEM; 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; card->long_name = sdw_card_long_name;
/* Register the card */ /* Register the card */
......
...@@ -205,6 +205,20 @@ static const struct snd_soc_acpi_link_adr tgl_rvp[] = { ...@@ -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[] = { static const struct snd_soc_acpi_link_adr tgl_chromebook_base[] = {
{ {
.mask = BIT(0), .mask = BIT(0),
...@@ -383,6 +397,12 @@ struct snd_soc_acpi_mach snd_soc_acpi_intel_tgl_sdw_machines[] = { ...@@ -383,6 +397,12 @@ struct snd_soc_acpi_mach snd_soc_acpi_intel_tgl_sdw_machines[] = {
.drv_name = "sof_sdw", .drv_name = "sof_sdw",
.sof_tplg_filename = "sof-tgl-rt711-rt1316-rt714.tplg", .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 */ .link_mask = 0x3, /* rt711 on link 0 and 2 rt1308s on link 1 */
.links = tgl_rvp, .links = tgl_rvp,
......
...@@ -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)
{ {
...@@ -579,25 +581,76 @@ static const char *fixup_tplg_name(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 *dmic_str)
{ {
const char *tplg_filename = NULL; const char *tplg_filename = NULL;
char *filename; char *filename, *tmp;
char *split_ext; const char *split_ext;
filename = devm_kstrdup(sdev->dev, sof_tplg_filename, GFP_KERNEL); filename = kstrdup(sof_tplg_filename, GFP_KERNEL);
if (!filename) if (!filename)
return NULL; return NULL;
/* this assumes a .tplg extension */ /* this assumes a .tplg extension */
split_ext = strsep(&filename, "."); tmp = filename;
if (split_ext) { split_ext = strsep(&tmp, ".");
if (split_ext)
tplg_filename = devm_kasprintf(sdev->dev, GFP_KERNEL, tplg_filename = devm_kasprintf(sdev->dev, GFP_KERNEL,
"%s%s%s.tplg", "%s%s%s.tplg",
split_ext, idisp_str, dmic_str); split_ext, idisp_str, dmic_str);
if (!tplg_filename) kfree(filename);
return NULL;
}
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) {
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 #endif
static int hda_init_caps(struct snd_sof_dev *sdev) 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) ...@@ -963,9 +1016,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 +1043,6 @@ static int hda_generic_machine_select(struct snd_sof_dev *sdev) ...@@ -990,10 +1043,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 +1051,13 @@ static int hda_generic_machine_select(struct snd_sof_dev *sdev) ...@@ -1002,42 +1051,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 +1069,6 @@ static int hda_generic_machine_select(struct snd_sof_dev *sdev) ...@@ -1049,7 +1069,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;
...@@ -1071,32 +1090,63 @@ static bool link_slaves_found(struct snd_sof_dev *sdev, ...@@ -1071,32 +1090,63 @@ static bool link_slaves_found(struct snd_sof_dev *sdev,
struct sdw_intel_slave_id *ids = sdw->ids; struct sdw_intel_slave_id *ids = sdw->ids;
int num_slaves = sdw->num_slaves; int num_slaves = sdw->num_slaves;
unsigned int part_id, link_id, unique_id, mfg_id; 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++) { for (i = 0; i < link->num_adr; i++) {
u64 adr = link->adr_d[i].adr; u64 adr = link->adr_d[i].adr;
int reported_part_count = 0;
mfg_id = SDW_MFG_ID(adr); mfg_id = SDW_MFG_ID(adr);
part_id = SDW_PART_ID(adr); part_id = SDW_PART_ID(adr);
link_id = SDW_DISCO_LINK_ID(adr); link_id = SDW_DISCO_LINK_ID(adr);
for (j = 0; j < num_slaves; j++) { 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 || if (ids[j].link_id != link_id ||
ids[j].id.part_id != part_id || ids[j].id.part_id != part_id ||
ids[j].id.mfg_id != mfg_id) ids[j].id.mfg_id != mfg_id)
continue; continue;
/*
* we have to check unique id /* find out how many identical parts are expected */
* if there is more than one for (k = 0; k < link->num_adr; k++) {
* Slave on the link u64 adr2 = link->adr_d[i].adr;
*/ unsigned int part_id2, link_id2, mfg_id2;
unique_id = SDW_UNIQUE_ID(adr);
if (link->num_adr == 1 || mfg_id2 = SDW_MFG_ID(adr2);
ids[j].id.unique_id == SDW_IGNORED_UNIQUE_ID || part_id2 = SDW_PART_ID(adr2);
ids[j].id.unique_id == unique_id) { link_id2 = SDW_DISCO_LINK_ID(adr2);
dev_dbg(bus->dev,
"found %x at link %d\n", if (link_id2 == link_id &&
part_id, link_id); part_id2 == part_id &&
break; 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) { if (j == num_slaves) {
...@@ -1113,7 +1163,6 @@ static int hda_sdw_machine_select(struct snd_sof_dev *sdev) ...@@ -1113,7 +1163,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;
...@@ -1161,10 +1210,8 @@ static int hda_sdw_machine_select(struct snd_sof_dev *sdev) ...@@ -1161,10 +1210,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;
...@@ -1174,6 +1221,31 @@ static int hda_sdw_machine_select(struct snd_sof_dev *sdev) ...@@ -1174,6 +1221,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