From 2c35ddeb4a4c528c704915031e8deaa481f9ca63 Mon Sep 17 00:00:00 2001 From: Peter Ujfalusi Date: Fri, 6 Oct 2023 13:24:18 +0300 Subject: [PATCH 1/2] ALSA: hda/hdmi: Add helper function to check if a device is HDMI codec The snd_hda_device_is_hdmi() can be used in drivers to check if the hdev belongs to a display audio device. Signed-off-by: Peter Ujfalusi --- include/sound/hdaudio.h | 10 ++++++++++ sound/pci/hda/patch_hdmi.c | 13 +++++++++++++ 2 files changed, 23 insertions(+) diff --git a/include/sound/hdaudio.h b/include/sound/hdaudio.h index dd7c87bbc61361..7cb920d107cbe4 100644 --- a/include/sound/hdaudio.h +++ b/include/sound/hdaudio.h @@ -158,6 +158,16 @@ bool snd_hdac_check_power_state(struct hdac_device *hdac, hda_nid_t nid, unsigned int target_state); unsigned int snd_hdac_sync_power_state(struct hdac_device *hdac, hda_nid_t nid, unsigned int target_state); + +#if IS_ENABLED(CONFIG_SND_SOC_SOF_HDA_AUDIO_CODEC) +bool snd_hda_device_is_hdmi(struct hdac_device *hdev); +#else +static inline bool snd_hda_device_is_hdmi(struct hdac_device *hdev) +{ + return false; +} +#endif + /** * snd_hdac_read_parm - read a codec parameter * @codec: the codec object diff --git a/sound/pci/hda/patch_hdmi.c b/sound/pci/hda/patch_hdmi.c index 1cde2a69bdb4ba..d6943575c8c724 100644 --- a/sound/pci/hda/patch_hdmi.c +++ b/sound/pci/hda/patch_hdmi.c @@ -4645,6 +4645,19 @@ HDA_CODEC_ENTRY(HDA_CODEC_ID_GENERIC_HDMI, "Generic HDMI", patch_generic_hdmi), }; MODULE_DEVICE_TABLE(hdaudio, snd_hda_id_hdmi); +bool snd_hda_device_is_hdmi(struct hdac_device *hdev) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(snd_hda_id_hdmi); i++) { + if (snd_hda_id_hdmi[i].vendor_id == hdev->vendor_id) + return true; + } + + return false; +} +EXPORT_SYMBOL_GPL(snd_hda_device_is_hdmi); + MODULE_LICENSE("GPL"); MODULE_DESCRIPTION("HDMI HD-audio codec"); MODULE_ALIAS("snd-hda-codec-intelhdmi"); From ae295f06bfa3a953ea94f0d45d8f1ca88c2f610b Mon Sep 17 00:00:00 2001 From: Peter Ujfalusi Date: Fri, 6 Oct 2023 13:30:56 +0300 Subject: [PATCH 2/2] ASoC: hdac_hda: Conditionally register dais for HDMI and Analog The current driver is registering the same dais for each hdev found in the system which results duplicated widgets to be registered and the kernel log contains similar prints: snd_hda_codec_realtek ehdaudio0D0: ASoC: sink widget AIF1TX overwritten snd_hda_codec_realtek ehdaudio0D0: ASoC: source widget AIF1RX overwritten skl_hda_dsp_generic skl_hda_dsp_generic: ASoC: sink widget hifi3 overwritten skl_hda_dsp_generic skl_hda_dsp_generic: ASoC: sink widget hifi2 overwritten skl_hda_dsp_generic skl_hda_dsp_generic: ASoC: sink widget hifi1 overwritten skl_hda_dsp_generic skl_hda_dsp_generic: ASoC: source widget Codec Output Pin1 overwritten skl_hda_dsp_generic skl_hda_dsp_generic: ASoC: sink widget Codec Input Pin1 overwritten skl_hda_dsp_generic skl_hda_dsp_generic: ASoC: sink widget Analog Codec Playback overwritten skl_hda_dsp_generic skl_hda_dsp_generic: ASoC: sink widget Digital Codec Playback overwritten skl_hda_dsp_generic skl_hda_dsp_generic: ASoC: sink widget Alt Analog Codec Playback overwritten skl_hda_dsp_generic skl_hda_dsp_generic: ASoC: source widget Analog Codec Capture overwritten skl_hda_dsp_generic skl_hda_dsp_generic: ASoC: source widget Digital Codec Capture overwritten skl_hda_dsp_generic skl_hda_dsp_generic: ASoC: source widget Alt Analog Codec Capture overwritten To avoid such issue, split the dai array into HDMI and non HDMI array and register them conditionally: for HDMI hdev only register the dais needed for HDMI for non HDMI hdev do not register the HDMI dais. Link: https://github.com/thesofproject/linux/issues/4509 Signed-off-by: Peter Ujfalusi --- sound/soc/codecs/hdac_hda.c | 22 +++++++++++++++++++--- 1 file changed, 19 insertions(+), 3 deletions(-) diff --git a/sound/soc/codecs/hdac_hda.c b/sound/soc/codecs/hdac_hda.c index 355f30779a3487..72916a387ad6d9 100644 --- a/sound/soc/codecs/hdac_hda.c +++ b/sound/soc/codecs/hdac_hda.c @@ -132,6 +132,9 @@ static struct snd_soc_dai_driver hdac_hda_dais[] = { .sig_bits = 24, }, }, +}; + +static struct snd_soc_dai_driver hdac_hda_hdmi_dais[] = { { .id = HDAC_HDMI_0_DAI_ID, .name = "intel-hdmi-hifi1", @@ -607,6 +610,13 @@ static const struct snd_soc_component_driver hdac_hda_codec = { .endianness = 1, }; +static const struct snd_soc_component_driver hdac_hda_hdmi_codec = { + .probe = hdac_hda_codec_probe, + .remove = hdac_hda_codec_remove, + .idle_bias_on = false, + .endianness = 1, +}; + static int hdac_hda_dev_probe(struct hdac_device *hdev) { struct hdac_ext_link *hlink; @@ -621,9 +631,15 @@ static int hdac_hda_dev_probe(struct hdac_device *hdev) snd_hdac_ext_bus_link_get(hdev->bus, hlink); /* ASoC specific initialization */ - ret = devm_snd_soc_register_component(&hdev->dev, - &hdac_hda_codec, hdac_hda_dais, - ARRAY_SIZE(hdac_hda_dais)); + if (snd_hda_device_is_hdmi(hdev)) + ret = devm_snd_soc_register_component(&hdev->dev, + &hdac_hda_hdmi_codec, hdac_hda_hdmi_dais, + ARRAY_SIZE(hdac_hda_hdmi_dais)); + else + ret = devm_snd_soc_register_component(&hdev->dev, + &hdac_hda_codec, hdac_hda_dais, + ARRAY_SIZE(hdac_hda_dais)); + if (ret < 0) { dev_err(&hdev->dev, "failed to register HDA codec %d\n", ret); return ret;