From 738b570d869b11ce54930ce4cf4b04382e50e89f Mon Sep 17 00:00:00 2001 From: Pierre-Louis Bossart Date: Tue, 14 Dec 2021 11:16:25 -0600 Subject: [PATCH 1/7] ASoC: soc-acpi: fix kernel-doc descriptor Add missing dmic_num mention and clarify that 'links' mean 'SoundWire links', not to be used for other links. Signed-off-by: Pierre-Louis Bossart --- include/sound/soc-acpi.h | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/include/sound/soc-acpi.h b/include/sound/soc-acpi.h index ac0893df9c76d4..f37849516483ff 100644 --- a/include/sound/soc-acpi.h +++ b/include/sound/soc-acpi.h @@ -60,9 +60,10 @@ static inline struct snd_soc_acpi_mach *snd_soc_acpi_codec_list(void *arg) * @acpi_ipc_irq_index: used for BYT-CR detection * @platform: string used for HDAudio codec support * @codec_mask: used for HDAudio support + * @dmic_num: number of SoC- or chipset-attached PDM digital microphones * @common_hdmi_codec_drv: use commom HDAudio HDMI codec driver - * @link_mask: links enabled on the board - * @links: array of link _ADR descriptors, null terminated + * @link_mask: SoundWire links enabled on the board + * @links: array of SoundWire link _ADR descriptors, null terminated * @num_dai_drivers: number of elements in @dai_drivers * @dai_drivers: pointer to dai_drivers, used e.g. in nocodec mode */ From 9c235769fa8d92b497fedb7eb01fe351519b29e4 Mon Sep 17 00:00:00 2001 From: Pierre-Louis Bossart Date: Tue, 14 Dec 2021 11:21:01 -0600 Subject: [PATCH 2/7] ASoC: soc-acpi: add information on I2S/TDM link mask The platform driver may have information on which I2S/TDM link(s) to enable in the machine driver. In the case of Intel devices, this may be extracted from NHLT tables in platform firmware. This link information is necessary to make sure machine driver and topology are aligned. Signed-off-by: Pierre-Louis Bossart --- include/sound/soc-acpi.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/include/sound/soc-acpi.h b/include/sound/soc-acpi.h index f37849516483ff..d13b34e69392e0 100644 --- a/include/sound/soc-acpi.h +++ b/include/sound/soc-acpi.h @@ -64,6 +64,7 @@ static inline struct snd_soc_acpi_mach *snd_soc_acpi_codec_list(void *arg) * @common_hdmi_codec_drv: use commom HDAudio HDMI codec driver * @link_mask: SoundWire links enabled on the board * @links: array of SoundWire link _ADR descriptors, null terminated + * @i2s_link_mask: I2S/TDM links enabled on the board * @num_dai_drivers: number of elements in @dai_drivers * @dai_drivers: pointer to dai_drivers, used e.g. in nocodec mode */ @@ -75,6 +76,7 @@ struct snd_soc_acpi_mach_params { bool common_hdmi_codec_drv; u32 link_mask; const struct snd_soc_acpi_link_adr *links; + u32 i2s_link_mask; u32 num_dai_drivers; struct snd_soc_dai_driver *dai_drivers; }; From 179b8259f3589f0eb799f14bf3b2651e77b9dda6 Mon Sep 17 00:00:00 2001 From: Pierre-Louis Bossart Date: Tue, 14 Dec 2021 13:10:25 -0600 Subject: [PATCH 3/7] ASoC: SOF: Intel: hda: retrieve DMIC number for I2S boards We currently extract the DMIC number only for HDaudio or SoundWire platforms. For I2S/TDM platforms, this wasn't necessary until now, but with devices with ES8336 we need to find a solution to detect dmics more reliably than with a DMI quirk. Signed-off-by: Pierre-Louis Bossart --- sound/soc/sof/intel/hda.c | 40 +++++++++++++++++++++------------------ 1 file changed, 22 insertions(+), 18 deletions(-) diff --git a/sound/soc/sof/intel/hda.c b/sound/soc/sof/intel/hda.c index 7c75feae4cbf33..b3956582938954 100644 --- a/sound/soc/sof/intel/hda.c +++ b/sound/soc/sof/intel/hda.c @@ -453,11 +453,9 @@ 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) || IS_ENABLED(CONFIG_SND_SOC_SOF_INTEL_SOUNDWIRE) -static int hda_dmic_num = -1; -module_param_named(dmic_num, hda_dmic_num, int, 0444); +static int dmic_num_override = -1; +module_param_named(dmic_num, dmic_num_override, 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); @@ -665,24 +663,35 @@ static int hda_init(struct snd_sof_dev *sdev) return ret; } -#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) { struct nhlt_acpi_table *nhlt; - int dmic_num; + int dmic_num = 0; 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 >= 1 && dmic_num <= 4) - return dmic_num; } - return 0; + /* allow for module parameter override */ + if (dmic_num_override != -1) { + dev_dbg(sdev->dev, + "overriding DMICs detected in NHLT tables %d by kernel param %d\n", + dmic_num, dmic_num_override); + dmic_num = dmic_num_override; + } + + if (dmic_num < 0 || dmic_num > 4) { + dev_dbg(sdev->dev, "invalid dmic_number %d\n", dmic_num); + dmic_num = 0; + } + + return dmic_num; } +#if IS_ENABLED(CONFIG_SND_SOC_SOF_HDA) || IS_ENABLED(CONFIG_SND_SOC_SOF_INTEL_SOUNDWIRE) + static const char *fixup_tplg_name(struct snd_sof_dev *sdev, const char *sof_tplg_filename, const char *idisp_str, @@ -721,14 +730,6 @@ static int dmic_topology_fixup(struct snd_sof_dev *sdev, /* 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"; @@ -1407,6 +1408,9 @@ struct snd_soc_acpi_mach *hda_machine_select(struct snd_sof_dev *sdev) if (!sof_pdata->tplg_filename) sof_pdata->tplg_filename = mach->sof_tplg_filename; + /* report to machine driver if any DMICs are found */ + mach->mach_params.dmic_num = check_nhlt_dmic(sdev); + if (mach->link_mask) { mach->mach_params.links = mach->links; mach->mach_params.link_mask = mach->link_mask; From d027e90c656c6365e502384f3744f10137db9b31 Mon Sep 17 00:00:00 2001 From: Pierre-Louis Bossart Date: Tue, 14 Dec 2021 14:46:13 -0600 Subject: [PATCH 4/7] ALSA: intel-nhlt: add helper to detect SSP link mask The NHLT information can be used to figure out which SSPs are enabled in a platform. The 'SSP' link type is too broad for machine drivers, since it can cover the Bluetooth sideband and the analog audio codec connections, so this helper exposes a parameter to filter with the device type (DEVICE_I2S refers to analog audio codec in NHLT parlance). The helper returns a mask, since more than one SSP may be used for analog audio, e.g. the NHLT spec describes the use of SSP0 for amplifiers and SSP1 for headset codec. Note that if more than one bit is set, it's impossible to determine which SSP is connected to what external component. Additional platform-specific information based on e.g. DMI quirks would still be required in the machine driver to configure the relevant dailinks. Signed-off-by: Pierre-Louis Bossart --- include/sound/intel-nhlt.h | 8 ++++++++ sound/hda/intel-nhlt.c | 22 ++++++++++++++++++++++ 2 files changed, 30 insertions(+) diff --git a/include/sound/intel-nhlt.h b/include/sound/intel-nhlt.h index 089a760d36eb71..88eb2ec158073c 100644 --- a/include/sound/intel-nhlt.h +++ b/include/sound/intel-nhlt.h @@ -133,6 +133,9 @@ void intel_nhlt_free(struct nhlt_acpi_table *addr); int intel_nhlt_get_dmic_geo(struct device *dev, struct nhlt_acpi_table *nhlt); bool intel_nhlt_has_endpoint_type(struct nhlt_acpi_table *nhlt, u8 link_type); + +int intel_nhlt_ssp_endpoint_mask(struct nhlt_acpi_table *nhlt, u8 device_type); + struct nhlt_specific_cfg * intel_nhlt_get_endpoint_blob(struct device *dev, struct nhlt_acpi_table *nhlt, u32 bus_id, u8 link_type, u8 vbps, u8 bps, @@ -163,6 +166,11 @@ static inline bool intel_nhlt_has_endpoint_type(struct nhlt_acpi_table *nhlt, return false; } +static inline int intel_nhlt_ssp_endpoint_mask(struct nhlt_acpi_table *nhlt, u8 device_type) +{ + return 0; +} + static inline struct nhlt_specific_cfg * intel_nhlt_get_endpoint_blob(struct device *dev, struct nhlt_acpi_table *nhlt, u32 bus_id, u8 link_type, u8 vbps, u8 bps, diff --git a/sound/hda/intel-nhlt.c b/sound/hda/intel-nhlt.c index 128476aa7c61df..4063da37828338 100644 --- a/sound/hda/intel-nhlt.c +++ b/sound/hda/intel-nhlt.c @@ -130,6 +130,28 @@ bool intel_nhlt_has_endpoint_type(struct nhlt_acpi_table *nhlt, u8 link_type) } EXPORT_SYMBOL(intel_nhlt_has_endpoint_type); +int intel_nhlt_ssp_endpoint_mask(struct nhlt_acpi_table *nhlt, u8 device_type) +{ + struct nhlt_endpoint *epnt; + int ssp_mask = 0; + int i; + + if (!nhlt || (device_type != NHLT_DEVICE_BT && device_type != NHLT_DEVICE_I2S)) + return 0; + + epnt = (struct nhlt_endpoint *)nhlt->desc; + for (i = 0; i < nhlt->endpoint_count; i++) { + if (epnt->linktype == NHLT_LINK_SSP && epnt->device_type == device_type) { + /* for SSP the virtual bus id is the SSP port */ + ssp_mask |= BIT(epnt->virtual_bus_id); + } + epnt = (struct nhlt_endpoint *)((u8 *)epnt + epnt->length); + } + + return ssp_mask; +} +EXPORT_SYMBOL(intel_nhlt_ssp_endpoint_mask); + static struct nhlt_specific_cfg * nhlt_get_specific_cfg(struct device *dev, struct nhlt_fmt *fmt, u8 num_ch, u32 rate, u8 vbps, u8 bps) From fbe88e003e372b39ff2ee89ce5596a29a3f644b5 Mon Sep 17 00:00:00 2001 From: Pierre-Louis Bossart Date: Tue, 14 Dec 2021 13:21:20 -0600 Subject: [PATCH 5/7] ASoC: SOF: Intel: hda: report SSP link mask to machine driver For devices designed for Windows, the SSP information should be listed in the NHLT, and when present can be used to set quirks automatically in the machine driver. The NHLT information exposes BT and analog audio connections separately, for now we are only interested in the analog audio parts. The use of dev_info() for the SSP mask is intentional so that we can immediately flag devices with an ES8336 codec. Since NHLT is not used for recent Chromebooks these messages should be rare. Signed-off-by: Pierre-Louis Bossart --- sound/soc/sof/intel/hda.c | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/sound/soc/sof/intel/hda.c b/sound/soc/sof/intel/hda.c index b3956582938954..65d542697c6f95 100644 --- a/sound/soc/sof/intel/hda.c +++ b/sound/soc/sof/intel/hda.c @@ -690,6 +690,25 @@ static int check_nhlt_dmic(struct snd_sof_dev *sdev) return dmic_num; } +static int check_nhlt_ssp_mask(struct snd_sof_dev *sdev) +{ + struct nhlt_acpi_table *nhlt; + int ssp_mask = 0; + + nhlt = intel_nhlt_init(sdev->dev); + if (nhlt && intel_nhlt_has_endpoint_type(nhlt, NHLT_LINK_SSP)) { + + ssp_mask = intel_nhlt_ssp_endpoint_mask(nhlt, NHLT_DEVICE_I2S); + + if (ssp_mask) + dev_info(sdev->dev, "NHLT_DEVICE_I2S detected, ssp_mask %#x\n", ssp_mask); + + intel_nhlt_free(nhlt); + } + + return ssp_mask; +} + #if IS_ENABLED(CONFIG_SND_SOC_SOF_HDA) || IS_ENABLED(CONFIG_SND_SOC_SOF_INTEL_SOUNDWIRE) static const char *fixup_tplg_name(struct snd_sof_dev *sdev, @@ -1415,6 +1434,9 @@ struct snd_soc_acpi_mach *hda_machine_select(struct snd_sof_dev *sdev) mach->mach_params.links = mach->links; mach->mach_params.link_mask = mach->link_mask; } + + /* report SSP link mask to machine driver */ + mach->mach_params.i2s_link_mask = check_nhlt_ssp_mask(sdev); } /* From eef6c90c4e4d7b07b40a39f06948017f10578b7f Mon Sep 17 00:00:00 2001 From: Pierre-Louis Bossart Date: Tue, 14 Dec 2021 13:29:25 -0600 Subject: [PATCH 6/7] ASoC: Intel: sof_es8336: use NHLT information to set dmic and SSP This should help remove the need for additional quirks to determine DMIC and SSP connections. However we have no means to determine which GPIO might be used, in that case a DMI quirk or kernel parameter quirk_override will be required. Signed-off-by: Pierre-Louis Bossart --- sound/soc/intel/boards/sof_es8336.c | 23 +++++++++++++++++++---- 1 file changed, 19 insertions(+), 4 deletions(-) diff --git a/sound/soc/intel/boards/sof_es8336.c b/sound/soc/intel/boards/sof_es8336.c index 20d577eaab6d7d..e5ba6f56e4019b 100644 --- a/sound/soc/intel/boards/sof_es8336.c +++ b/sound/soc/intel/boards/sof_es8336.c @@ -470,11 +470,23 @@ static int sof_es8336_probe(struct platform_device *pdev) card = &sof_es8336_card; card->dev = dev; - if (!dmi_check_system(sof_es8336_quirk_table)) + if (!dmi_check_system(sof_es8336_quirk_table)) { quirk = SOF_ES8336_SSP_CODEC(2); - - if (quirk & SOF_ES8336_ENABLE_DMIC) - dmic_be_num = 2; + } else { + /* + * Set configuration based on platform NHLT. + * In this machine driver, we can only support one SSP for the + * ES8336 link, the else-if below are intentional + */ + if (mach->mach_params.i2s_link_mask & BIT(0)) + quirk = SOF_ES8336_SSP_CODEC(0); + else if (mach->mach_params.i2s_link_mask & BIT(1)) + quirk = SOF_ES8336_SSP_CODEC(1); + else if (mach->mach_params.i2s_link_mask & BIT(2)) + quirk = SOF_ES8336_SSP_CODEC(2); + if (mach->mach_params.dmic_num) + quirk |= SOF_ES8336_ENABLE_DMIC; + } if (quirk_override != -1) { dev_info(dev, "Overriding quirk 0x%lx => 0x%x\n", @@ -483,6 +495,9 @@ static int sof_es8336_probe(struct platform_device *pdev) } log_quirks(dev); + if (quirk & SOF_ES8336_ENABLE_DMIC) + dmic_be_num = 2; + sof_es8336_card.num_links += dmic_be_num + hdmi_num; dai_links = sof_card_dai_links_create(dev, SOF_ES8336_SSP_CODEC(quirk), From 0f230ace0357e973955705eeba344d7742839454 Mon Sep 17 00:00:00 2001 From: yangxiaohua2009 Date: Wed, 12 Jan 2022 11:23:39 +0800 Subject: [PATCH 7/7] Update sof_es8336.c Fix the issue that quirk always use SSP2 --- sound/soc/intel/boards/sof_es8336.c | 26 +++++++++----------------- 1 file changed, 9 insertions(+), 17 deletions(-) diff --git a/sound/soc/intel/boards/sof_es8336.c b/sound/soc/intel/boards/sof_es8336.c index e5ba6f56e4019b..6d2deba6f4d991 100644 --- a/sound/soc/intel/boards/sof_es8336.c +++ b/sound/soc/intel/boards/sof_es8336.c @@ -469,24 +469,16 @@ static int sof_es8336_probe(struct platform_device *pdev) card = &sof_es8336_card; card->dev = dev; - - if (!dmi_check_system(sof_es8336_quirk_table)) { + + if (mach->mach_params.i2s_link_mask & BIT(2)) quirk = SOF_ES8336_SSP_CODEC(2); - } else { - /* - * Set configuration based on platform NHLT. - * In this machine driver, we can only support one SSP for the - * ES8336 link, the else-if below are intentional - */ - if (mach->mach_params.i2s_link_mask & BIT(0)) - quirk = SOF_ES8336_SSP_CODEC(0); - else if (mach->mach_params.i2s_link_mask & BIT(1)) - quirk = SOF_ES8336_SSP_CODEC(1); - else if (mach->mach_params.i2s_link_mask & BIT(2)) - quirk = SOF_ES8336_SSP_CODEC(2); - if (mach->mach_params.dmic_num) - quirk |= SOF_ES8336_ENABLE_DMIC; - } + else if (mach->mach_params.i2s_link_mask & BIT(1)) + quirk = SOF_ES8336_SSP_CODEC(1); + else + quirk = SOF_ES8336_SSP_CODEC(0); + if (mach->mach_params.dmic_num) + quirk |= SOF_ES8336_ENABLE_DMIC; + if (quirk_override != -1) { dev_info(dev, "Overriding quirk 0x%lx => 0x%x\n",