diff options
Diffstat (limited to 'sound/soc/intel/boards')
27 files changed, 1016 insertions, 87 deletions
diff --git a/sound/soc/intel/boards/Kconfig b/sound/soc/intel/boards/Kconfig index 34ccefcc30c7..f3873b5bea87 100644 --- a/sound/soc/intel/boards/Kconfig +++ b/sound/soc/intel/boards/Kconfig @@ -32,6 +32,12 @@ config SND_SOC_INTEL_HDA_DSP_COMMON config SND_SOC_INTEL_SOF_MAXIM_COMMON tristate +config SND_SOC_INTEL_SOF_REALTEK_COMMON + tristate + +config SND_SOC_INTEL_SOF_CIRRUS_COMMON + tristate + if SND_SOC_INTEL_CATPT config SND_SOC_INTEL_HASWELL_MACH @@ -97,6 +103,7 @@ config SND_SOC_INTEL_BYTCR_RT5640_MACH tristate "Baytrail and Baytrail-CR with RT5640 codec" depends on I2C && ACPI depends on X86_INTEL_LPSS || COMPILE_TEST + depends on GPIOLIB || COMPILE_TEST select SND_SOC_ACPI select SND_SOC_RT5640 help @@ -109,6 +116,7 @@ config SND_SOC_INTEL_BYTCR_RT5651_MACH tristate "Baytrail and Baytrail-CR with RT5651 codec" depends on I2C && ACPI depends on X86_INTEL_LPSS || COMPILE_TEST + depends on GPIOLIB || COMPILE_TEST select SND_SOC_ACPI select SND_SOC_RT5651 help @@ -121,6 +129,7 @@ config SND_SOC_INTEL_BYTCR_WM5102_MACH tristate "Baytrail and Baytrail-CR with WM5102 codec" depends on MFD_ARIZONA && MFD_WM5102 && SPI_MASTER && ACPI depends on X86_INTEL_LPSS || COMPILE_TEST + depends on GPIOLIB || COMPILE_TEST select SND_SOC_ACPI select SND_SOC_WM5102 help @@ -133,6 +142,7 @@ config SND_SOC_INTEL_CHT_BSW_RT5672_MACH tristate "Cherrytrail & Braswell with RT5672 codec" depends on I2C && ACPI depends on X86_INTEL_LPSS || COMPILE_TEST + depends on GPIOLIB || COMPILE_TEST select SND_SOC_ACPI select SND_SOC_RT5670 help @@ -157,6 +167,7 @@ config SND_SOC_INTEL_CHT_BSW_MAX98090_TI_MACH tristate "Cherrytrail & Braswell with MAX98090 & TI codec" depends on I2C && ACPI depends on X86_INTEL_LPSS || COMPILE_TEST + depends on GPIOLIB || COMPILE_TEST select SND_SOC_MAX98090 select SND_SOC_TS3A227E help @@ -181,6 +192,7 @@ config SND_SOC_INTEL_BYT_CHT_CX2072X_MACH tristate "Baytrail & Cherrytrail with CX2072X codec" depends on I2C && ACPI depends on X86_INTEL_LPSS || COMPILE_TEST + depends on GPIOLIB || COMPILE_TEST select SND_SOC_ACPI select SND_SOC_CX2072X help @@ -205,6 +217,7 @@ config SND_SOC_INTEL_BYT_CHT_ES8316_MACH tristate "Baytrail & Cherrytrail with ES8316 codec" depends on I2C && ACPI depends on X86_INTEL_LPSS || COMPILE_TEST + depends on GPIOLIB || COMPILE_TEST select SND_SOC_ACPI select SND_SOC_ES8316 help @@ -236,7 +249,7 @@ if SND_SOC_INTEL_SKL config SND_SOC_INTEL_SKL_RT286_MACH tristate "SKL with RT286 I2S mode" - depends on I2C && ACPI && GPIOLIB + depends on I2C && ACPI depends on MFD_INTEL_LPSS || COMPILE_TEST select SND_SOC_RT286 select SND_SOC_DMIC @@ -249,7 +262,7 @@ config SND_SOC_INTEL_SKL_RT286_MACH config SND_SOC_INTEL_SKL_NAU88L25_SSM4567_MACH tristate "SKL with NAU88L25 and SSM4567 in I2S Mode" - depends on I2C && ACPI && GPIOLIB + depends on I2C && ACPI depends on MFD_INTEL_LPSS || COMPILE_TEST select SND_SOC_NAU8825 select SND_SOC_SSM4567 @@ -263,7 +276,7 @@ config SND_SOC_INTEL_SKL_NAU88L25_SSM4567_MACH config SND_SOC_INTEL_SKL_NAU88L25_MAX98357A_MACH tristate "SKL with NAU88L25 and MAX98357A in I2S Mode" - depends on I2C && ACPI && GPIOLIB + depends on I2C && ACPI depends on MFD_INTEL_LPSS || COMPILE_TEST select SND_SOC_NAU8825 select SND_SOC_MAX98357A @@ -294,7 +307,7 @@ if SND_SOC_INTEL_APL config SND_SOC_INTEL_BXT_DA7219_MAX98357A_MACH tristate "Broxton with DA7219 and MAX98357A/MAX98390 in I2S Mode" - depends on I2C && ACPI && GPIOLIB + depends on I2C && ACPI depends on MFD_INTEL_LPSS || COMPILE_TEST depends on SND_HDA_CODEC_HDMI select SND_SOC_INTEL_BXT_DA7219_MAX98357A_COMMON @@ -306,7 +319,7 @@ config SND_SOC_INTEL_BXT_DA7219_MAX98357A_MACH config SND_SOC_INTEL_BXT_RT298_MACH tristate "Broxton with RT298 I2S mode" - depends on I2C && ACPI && GPIOLIB + depends on I2C && ACPI depends on MFD_INTEL_LPSS || COMPILE_TEST select SND_SOC_RT298 select SND_SOC_DMIC @@ -326,6 +339,7 @@ config SND_SOC_INTEL_SOF_WM8804_MACH tristate "SOF with Wolfson/Cirrus WM8804 codec" depends on I2C && ACPI depends on MFD_INTEL_LPSS || COMPILE_TEST + depends on GPIOLIB || COMPILE_TEST select SND_SOC_WM8804_I2C help This adds support for ASoC machine driver for Intel platforms @@ -339,7 +353,7 @@ if SND_SOC_INTEL_KBL config SND_SOC_INTEL_KBL_RT5663_MAX98927_MACH tristate "KBL with RT5663 and MAX98927 in I2S Mode" - depends on I2C && ACPI && GPIOLIB + depends on I2C && ACPI depends on MFD_INTEL_LPSS || COMPILE_TEST select SND_SOC_RT5663 select SND_SOC_MAX98927 @@ -371,7 +385,7 @@ config SND_SOC_INTEL_KBL_RT5663_RT5514_MAX98927_MACH config SND_SOC_INTEL_KBL_DA7219_MAX98357A_MACH tristate "KBL with DA7219 and MAX98357A in I2S Mode" - depends on I2C && ACPI && GPIOLIB + depends on I2C && ACPI depends on MFD_INTEL_LPSS || COMPILE_TEST select SND_SOC_INTEL_DA7219_MAX98357A_GENERIC help @@ -381,7 +395,7 @@ config SND_SOC_INTEL_KBL_DA7219_MAX98357A_MACH config SND_SOC_INTEL_KBL_DA7219_MAX98927_MACH tristate "KBL with DA7219 and MAX98927 in I2S Mode" - depends on I2C && ACPI && GPIOLIB + depends on I2C && ACPI depends on MFD_INTEL_LPSS || COMPILE_TEST select SND_SOC_DA7219 select SND_SOC_MAX98927 @@ -398,6 +412,7 @@ config SND_SOC_INTEL_KBL_RT5660_MACH tristate "KBL with RT5660 in I2S Mode" depends on I2C && ACPI depends on MFD_INTEL_LPSS || COMPILE_TEST + depends on GPIOLIB || COMPILE_TEST select SND_SOC_RT5660 select SND_SOC_HDAC_HDMI help @@ -411,7 +426,7 @@ if SND_SOC_SOF_GEMINILAKE config SND_SOC_INTEL_GLK_DA7219_MAX98357A_MACH tristate "GLK with DA7219 and MAX98357A in I2S Mode" - depends on I2C && ACPI && GPIOLIB + depends on I2C && ACPI depends on MFD_INTEL_LPSS || COMPILE_TEST depends on SND_HDA_CODEC_HDMI && SND_SOC_SOF_HDA_AUDIO_CODEC select SND_SOC_INTEL_BXT_DA7219_MAX98357A_COMMON @@ -423,7 +438,7 @@ config SND_SOC_INTEL_GLK_DA7219_MAX98357A_MACH config SND_SOC_INTEL_GLK_RT5682_MAX98357A_MACH tristate "GLK with RT5682 and MAX98357A in I2S Mode" - depends on I2C && ACPI && GPIOLIB + depends on I2C && ACPI depends on MFD_INTEL_LPSS || COMPILE_TEST depends on SND_HDA_CODEC_HDMI && SND_SOC_SOF_HDA_AUDIO_CODEC select SND_SOC_RT5682_I2C @@ -445,7 +460,6 @@ if SND_SOC_INTEL_SKYLAKE_HDAUDIO_CODEC || SND_SOC_SOF_HDA_AUDIO_CODEC config SND_SOC_INTEL_SKL_HDA_DSP_GENERIC_MACH tristate "Skylake+ with HDA Codecs" depends on SND_HDA_CODEC_HDMI - depends on GPIOLIB select SND_SOC_HDAC_HDMI select SND_SOC_INTEL_HDA_DSP_COMMON select SND_SOC_DMIC @@ -462,7 +476,7 @@ endif ## SND_SOC_INTEL_SKYLAKE_HDAUDIO_CODEC || SND_SOC_SOF_HDA_AUDIO_CODEC if SND_SOC_SOF_HDA_LINK || SND_SOC_SOF_BAYTRAIL config SND_SOC_INTEL_SOF_RT5682_MACH tristate "SOF with rt5682 codec in I2S Mode" - depends on I2C && ACPI && GPIOLIB + depends on I2C && ACPI depends on ((SND_HDA_CODEC_HDMI && SND_SOC_SOF_HDA_AUDIO_CODEC) &&\ (MFD_INTEL_LPSS || COMPILE_TEST)) ||\ (SND_SOC_SOF_BAYTRAIL && (X86_INTEL_LPSS || COMPILE_TEST)) @@ -477,6 +491,7 @@ config SND_SOC_INTEL_SOF_RT5682_MACH select SND_SOC_HDAC_HDMI select SND_SOC_INTEL_HDA_DSP_COMMON select SND_SOC_INTEL_SOF_MAXIM_COMMON + select SND_SOC_INTEL_SOF_REALTEK_COMMON help This adds support for ASoC machine driver for SOF platforms with rt5682 codec. @@ -515,11 +530,13 @@ config SND_SOC_INTEL_SOF_PCM512x_MACH If unsure select "N". config SND_SOC_INTEL_SOF_ES8336_MACH - tristate "SOF with ES8336 codec in I2S mode" - depends on I2C && ACPI && GPIOLIB + tristate "SOF with ES8336 or ES8326 codec in I2S mode" + depends on I2C && ACPI depends on MFD_INTEL_LPSS || COMPILE_TEST + depends on GPIOLIB || COMPILE_TEST depends on SND_HDA_CODEC_HDMI && SND_SOC_SOF_HDA_AUDIO_CODEC select SND_SOC_ES8316 + select SND_SOC_ES8326 select SND_SOC_DMIC select SND_SOC_INTEL_HDA_DSP_COMMON help @@ -530,7 +547,7 @@ config SND_SOC_INTEL_SOF_ES8336_MACH config SND_SOC_INTEL_SOF_NAU8825_MACH tristate "SOF with nau8825 codec in I2S Mode" - depends on I2C && ACPI && GPIOLIB + depends on I2C && ACPI depends on ((SND_HDA_CODEC_HDMI && SND_SOC_SOF_HDA_AUDIO_CODEC) &&\ (MFD_INTEL_LPSS || COMPILE_TEST)) select SND_SOC_NAU8825 @@ -553,7 +570,7 @@ if (SND_SOC_SOF_COMETLAKE && SND_SOC_SOF_HDA_LINK) config SND_SOC_INTEL_CML_LP_DA7219_MAX98357A_MACH tristate "CML_LP with DA7219 and MAX98357A in I2S Mode" - depends on I2C && ACPI && GPIOLIB + depends on I2C && ACPI depends on MFD_INTEL_LPSS || COMPILE_TEST select SND_SOC_INTEL_BXT_DA7219_MAX98357A_COMMON help @@ -564,7 +581,7 @@ config SND_SOC_INTEL_CML_LP_DA7219_MAX98357A_MACH config SND_SOC_INTEL_SOF_CML_RT1011_RT5682_MACH tristate "CML with RT1011 and RT5682 in I2S Mode" - depends on I2C && ACPI && GPIOLIB + depends on I2C && ACPI depends on MFD_INTEL_LPSS || COMPILE_TEST depends on SND_HDA_CODEC_HDMI && SND_SOC_SOF_HDA_AUDIO_CODEC select SND_SOC_RT1011 @@ -584,7 +601,7 @@ if SND_SOC_SOF_JASPERLAKE config SND_SOC_INTEL_SOF_DA7219_MAX98373_MACH tristate "SOF with DA7219 and MAX98373/MAX98360A in I2S Mode" - depends on I2C && ACPI && GPIOLIB + depends on I2C && ACPI depends on MFD_INTEL_LPSS || COMPILE_TEST depends on SND_HDA_CODEC_HDMI && SND_SOC_SOF_HDA_AUDIO_CODEC select SND_SOC_INTEL_HDA_DSP_COMMON @@ -599,11 +616,31 @@ config SND_SOC_INTEL_SOF_DA7219_MAX98373_MACH endif ## SND_SOC_SOF_JASPERLAKE +if SND_SOC_SOF_HDA_LINK + +config SND_SOC_INTEL_SOF_SSP_AMP_MACH + tristate "SOF with amplifiers in I2S Mode" + depends on I2C && ACPI + depends on MFD_INTEL_LPSS || COMPILE_TEST + select SND_SOC_RT1308 + select SND_SOC_CS35L41_I2C + select SND_SOC_DMIC + select SND_SOC_HDAC_HDMI + select SND_SOC_INTEL_HDA_DSP_COMMON + select SND_SOC_INTEL_SOF_REALTEK_COMMON + select SND_SOC_INTEL_SOF_CIRRUS_COMMON + help + This adds support for ASoC machine driver for SOF platforms + with RT1308/CS35L41 I2S audio codec. + Say Y if you have such a device. + If unsure select "N". +endif ## SND_SOC_SOF_HDA_LINK + if SND_SOC_SOF_ELKHARTLAKE config SND_SOC_INTEL_EHL_RT5660_MACH tristate "EHL with RT5660 in I2S mode" - depends on I2C && ACPI && GPIOLIB + depends on I2C && ACPI depends on MFD_INTEL_LPSS || COMPILE_TEST depends on SND_HDA_CODEC_HDMI && SND_SOC_SOF_HDA_AUDIO_CODEC select SND_SOC_RT5660 @@ -619,7 +656,7 @@ if SND_SOC_SOF_INTEL_SOUNDWIRE config SND_SOC_INTEL_SOUNDWIRE_SOF_MACH tristate "SoundWire generic machine driver" - depends on I2C && ACPI && GPIOLIB + depends on I2C && ACPI depends on MFD_INTEL_LPSS || COMPILE_TEST depends on SND_SOC_INTEL_USER_FRIENDLY_LONG_NAMES || COMPILE_TEST depends on SOUNDWIRE diff --git a/sound/soc/intel/boards/Makefile b/sound/soc/intel/boards/Makefile index 3ea273d27168..40c0c3d1c500 100644 --- a/sound/soc/intel/boards/Makefile +++ b/sound/soc/intel/boards/Makefile @@ -19,10 +19,10 @@ snd-soc-sst-byt-cht-cx2072x-objs := bytcht_cx2072x.o snd-soc-sst-byt-cht-da7213-objs := bytcht_da7213.o snd-soc-sst-byt-cht-es8316-objs := bytcht_es8316.o snd-soc-sst-byt-cht-nocodec-objs := bytcht_nocodec.o -snd-soc-sof_rt5682-objs := sof_rt5682.o sof_realtek_common.o +snd-soc-sof_rt5682-objs := sof_rt5682.o snd-soc-sof_cs42l42-objs := sof_cs42l42.o snd-soc-sof_es8336-objs := sof_es8336.o -snd-soc-sof_nau8825-objs := sof_nau8825.o sof_realtek_common.o +snd-soc-sof_nau8825-objs := sof_nau8825.o snd-soc-cml_rt1011_rt5682-objs := cml_rt1011_rt5682.o snd-soc-kbl_da7219_max98357a-objs := kbl_da7219_max98357a.o snd-soc-kbl_da7219_max98927-objs := kbl_da7219_max98927.o @@ -35,6 +35,7 @@ snd-skl_nau88l25_max98357a-objs := skl_nau88l25_max98357a.o snd-soc-skl_nau88l25_ssm4567-objs := skl_nau88l25_ssm4567.o snd-soc-sof_da7219_max98373-objs := sof_da7219_max98373.o snd-soc-ehl-rt5660-objs := ehl_rt5660.o +snd-soc-sof-ssp-amp-objs := sof_ssp_amp.o snd-soc-sof-sdw-objs += sof_sdw.o \ sof_sdw_max98373.o \ sof_sdw_rt1308.o sof_sdw_rt1316.o \ @@ -79,6 +80,7 @@ obj-$(CONFIG_SND_SOC_INTEL_SKL_HDA_DSP_GENERIC_MACH) += snd-soc-skl_hda_dsp.o obj-$(CONFIG_SND_SOC_INTEL_SOF_DA7219_MAX98373_MACH) += snd-soc-sof_da7219_max98373.o obj-$(CONFIG_SND_SOC_INTEL_EHL_RT5660_MACH) += snd-soc-ehl-rt5660.o obj-$(CONFIG_SND_SOC_INTEL_SOUNDWIRE_SOF_MACH) += snd-soc-sof-sdw.o +obj-$(CONFIG_SND_SOC_INTEL_SOF_SSP_AMP_MACH) += snd-soc-sof-ssp-amp.o # common modules snd-soc-intel-hda-dsp-common-objs := hda_dsp_common.o @@ -86,3 +88,9 @@ obj-$(CONFIG_SND_SOC_INTEL_HDA_DSP_COMMON) += snd-soc-intel-hda-dsp-common.o snd-soc-intel-sof-maxim-common-objs += sof_maxim_common.o obj-$(CONFIG_SND_SOC_INTEL_SOF_MAXIM_COMMON) += snd-soc-intel-sof-maxim-common.o + +snd-soc-intel-sof-realtek-common-objs += sof_realtek_common.o +obj-$(CONFIG_SND_SOC_INTEL_SOF_REALTEK_COMMON) += snd-soc-intel-sof-realtek-common.o + +snd-soc-intel-sof-cirrus-common-objs += sof_cirrus_common.o +obj-$(CONFIG_SND_SOC_INTEL_SOF_CIRRUS_COMMON) += snd-soc-intel-sof-cirrus-common.o diff --git a/sound/soc/intel/boards/bdw-rt5650.c b/sound/soc/intel/boards/bdw-rt5650.c index 6cba5552f7a2..bc0eab1c304a 100644 --- a/sound/soc/intel/boards/bdw-rt5650.c +++ b/sound/soc/intel/boards/bdw-rt5650.c @@ -299,7 +299,7 @@ static int bdw_rt5650_probe(struct platform_device *pdev) if (!bdw_rt5650) return -ENOMEM; - /* override plaform name, if required */ + /* override platform name, if required */ mach = pdev->dev.platform_data; ret = snd_soc_fixup_dai_links_platform_name(&bdw_rt5650_card, mach->mach_params.platform); diff --git a/sound/soc/intel/boards/bdw-rt5677.c b/sound/soc/intel/boards/bdw-rt5677.c index 119c441f4c10..071557fada29 100644 --- a/sound/soc/intel/boards/bdw-rt5677.c +++ b/sound/soc/intel/boards/bdw-rt5677.c @@ -426,7 +426,7 @@ static int bdw_rt5677_probe(struct platform_device *pdev) if (!bdw_rt5677) return -ENOMEM; - /* override plaform name, if required */ + /* override platform name, if required */ mach = pdev->dev.platform_data; ret = snd_soc_fixup_dai_links_platform_name(&bdw_rt5677_card, mach->mach_params.platform); diff --git a/sound/soc/intel/boards/broadwell.c b/sound/soc/intel/boards/broadwell.c index 618d0645ed8d..d37c74fd1a3c 100644 --- a/sound/soc/intel/boards/broadwell.c +++ b/sound/soc/intel/boards/broadwell.c @@ -292,7 +292,7 @@ static int broadwell_audio_probe(struct platform_device *pdev) broadwell_rt286.dev = &pdev->dev; - /* override plaform name, if required */ + /* override platform name, if required */ mach = pdev->dev.platform_data; ret = snd_soc_fixup_dai_links_platform_name(&broadwell_rt286, mach->mach_params.platform); diff --git a/sound/soc/intel/boards/bxt_da7219_max98357a.c b/sound/soc/intel/boards/bxt_da7219_max98357a.c index b768d9b8ec02..9bc7b88e346b 100644 --- a/sound/soc/intel/boards/bxt_da7219_max98357a.c +++ b/sound/soc/intel/boards/bxt_da7219_max98357a.c @@ -825,7 +825,7 @@ static int broxton_audio_probe(struct platform_device *pdev) } } - /* override plaform name, if required */ + /* override platform name, if required */ mach = pdev->dev.platform_data; platform_name = mach->mach_params.platform; diff --git a/sound/soc/intel/boards/bxt_rt298.c b/sound/soc/intel/boards/bxt_rt298.c index 920e575b4314..05e833076499 100644 --- a/sound/soc/intel/boards/bxt_rt298.c +++ b/sound/soc/intel/boards/bxt_rt298.c @@ -628,7 +628,7 @@ static int broxton_audio_probe(struct platform_device *pdev) card->dev = &pdev->dev; snd_soc_card_set_drvdata(card, ctx); - /* override plaform name, if required */ + /* override platform name, if required */ mach = pdev->dev.platform_data; platform_name = mach->mach_params.platform; diff --git a/sound/soc/intel/boards/bytcht_cx2072x.c b/sound/soc/intel/boards/bytcht_cx2072x.c index ffd497a5b5a5..96d3201efbbd 100644 --- a/sound/soc/intel/boards/bytcht_cx2072x.c +++ b/sound/soc/intel/boards/bytcht_cx2072x.c @@ -257,7 +257,7 @@ static int snd_byt_cht_cx2072x_probe(struct platform_device *pdev) byt_cht_cx2072x_dais[dai_index].codecs->name = codec_name; } - /* override plaform name, if required */ + /* override platform name, if required */ ret = snd_soc_fixup_dai_links_platform_name(&byt_cht_cx2072x_card, mach->mach_params.platform); if (ret) diff --git a/sound/soc/intel/boards/bytcht_da7213.c b/sound/soc/intel/boards/bytcht_da7213.c index fae1e7e785b0..eb19bf16afad 100644 --- a/sound/soc/intel/boards/bytcht_da7213.c +++ b/sound/soc/intel/boards/bytcht_da7213.c @@ -260,7 +260,7 @@ static int bytcht_da7213_probe(struct platform_device *pdev) dailink[dai_index].codecs->name = codec_name; } - /* override plaform name, if required */ + /* override platform name, if required */ platform_name = mach->mach_params.platform; ret_val = snd_soc_fixup_dai_links_platform_name(card, platform_name); diff --git a/sound/soc/intel/boards/bytcht_es8316.c b/sound/soc/intel/boards/bytcht_es8316.c index 9d86fea51a7d..e18371b5a771 100644 --- a/sound/soc/intel/boards/bytcht_es8316.c +++ b/sound/soc/intel/boards/bytcht_es8316.c @@ -497,7 +497,7 @@ static int snd_byt_cht_es8316_mc_probe(struct platform_device *pdev) return -ENXIO; } - /* override plaform name, if required */ + /* override platform name, if required */ byt_cht_es8316_card.dev = dev; platform_name = mach->mach_params.platform; @@ -535,7 +535,6 @@ static int snd_byt_cht_es8316_mc_probe(struct platform_device *pdev) if (IS_ERR(priv->mclk)) return dev_err_probe(dev, PTR_ERR(priv->mclk), "clk_get pmc_plt_clk_3 failed\n"); - /* get speaker enable GPIO */ codec_dev = acpi_get_first_physical_node(adev); if (!codec_dev) return -EPROBE_DEFER; @@ -561,6 +560,7 @@ static int snd_byt_cht_es8316_mc_probe(struct platform_device *pdev) } } + /* get speaker enable GPIO */ devm_acpi_dev_add_driver_gpios(codec_dev, byt_cht_es8316_gpios); priv->speaker_en_gpio = gpiod_get_optional(codec_dev, "speaker-enable", diff --git a/sound/soc/intel/boards/bytcr_rt5640.c b/sound/soc/intel/boards/bytcr_rt5640.c index 2ace32c03ec9..d76a505052fb 100644 --- a/sound/soc/intel/boards/bytcr_rt5640.c +++ b/sound/soc/intel/boards/bytcr_rt5640.c @@ -1764,7 +1764,7 @@ static int snd_byt_rt5640_mc_probe(struct platform_device *pdev) byt_rt5640_card.long_name = byt_rt5640_long_name; #endif - /* override plaform name, if required */ + /* override platform name, if required */ platform_name = mach->mach_params.platform; ret_val = snd_soc_fixup_dai_links_platform_name(&byt_rt5640_card, diff --git a/sound/soc/intel/boards/bytcr_rt5651.c b/sound/soc/intel/boards/bytcr_rt5651.c index 5e9c53dadbc7..39348d2b242f 100644 --- a/sound/soc/intel/boards/bytcr_rt5651.c +++ b/sound/soc/intel/boards/bytcr_rt5651.c @@ -1088,7 +1088,7 @@ static int snd_byt_rt5651_mc_probe(struct platform_device *pdev) byt_rt5651_card.long_name = byt_rt5651_long_name; #endif - /* override plaform name, if required */ + /* override platform name, if required */ platform_name = mach->mach_params.platform; ret_val = snd_soc_fixup_dai_links_platform_name(&byt_rt5651_card, diff --git a/sound/soc/intel/boards/bytcr_wm5102.c b/sound/soc/intel/boards/bytcr_wm5102.c index 504ef4cab111..8d8e96e3cd2d 100644 --- a/sound/soc/intel/boards/bytcr_wm5102.c +++ b/sound/soc/intel/boards/bytcr_wm5102.c @@ -389,7 +389,7 @@ static int snd_byt_wm5102_mc_probe(struct platform_device *pdev) bool sof_parent; int ret; - priv = devm_kzalloc(dev, sizeof(*priv), GFP_ATOMIC); + priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); if (!priv) return -ENOMEM; diff --git a/sound/soc/intel/boards/cht_bsw_max98090_ti.c b/sound/soc/intel/boards/cht_bsw_max98090_ti.c index 1bc21434c9de..b3d7a0725ef2 100644 --- a/sound/soc/intel/boards/cht_bsw_max98090_ti.c +++ b/sound/soc/intel/boards/cht_bsw_max98090_ti.c @@ -296,7 +296,7 @@ static int cht_max98090_headset_init(struct snd_soc_component *component) int ret; /* - * TI supports 4 butons headset detection + * TI supports 4 buttons headset detection * KEY_MEDIA * KEY_VOICECOMMAND * KEY_VOLUMEUP @@ -558,7 +558,7 @@ static int snd_cht_mc_probe(struct platform_device *pdev) dev_dbg(dev, "Unable to add GPIO mapping table\n"); } - /* override plaform name, if required */ + /* override platform name, if required */ snd_soc_card_cht.dev = &pdev->dev; mach = pdev->dev.platform_data; platform_name = mach->mach_params.platform; diff --git a/sound/soc/intel/boards/cht_bsw_nau8824.c b/sound/soc/intel/boards/cht_bsw_nau8824.c index bad32d2bdf89..da6c659de266 100644 --- a/sound/soc/intel/boards/cht_bsw_nau8824.c +++ b/sound/soc/intel/boards/cht_bsw_nau8824.c @@ -100,7 +100,7 @@ static int cht_codec_init(struct snd_soc_pcm_runtime *runtime) struct snd_soc_component *component = codec_dai->component; int ret, jack_type; - /* NAU88L24 supports 4 butons headset detection + /* NAU88L24 supports 4 buttons headset detection * KEY_PLAYPAUSE * KEY_VOICECOMMAND * KEY_VOLUMEUP @@ -257,7 +257,7 @@ static int snd_cht_mc_probe(struct platform_device *pdev) return -ENOMEM; snd_soc_card_set_drvdata(&snd_soc_card_cht, drv); - /* override plaform name, if required */ + /* override platform name, if required */ snd_soc_card_cht.dev = &pdev->dev; mach = pdev->dev.platform_data; platform_name = mach->mach_params.platform; diff --git a/sound/soc/intel/boards/cht_bsw_rt5645.c b/sound/soc/intel/boards/cht_bsw_rt5645.c index e182012d0c60..c21561c6a464 100644 --- a/sound/soc/intel/boards/cht_bsw_rt5645.c +++ b/sound/soc/intel/boards/cht_bsw_rt5645.c @@ -653,7 +653,7 @@ static int snd_cht_mc_probe(struct platform_device *pdev) (cht_rt5645_quirk & CHT_RT5645_SSP0_AIF2)) cht_dailink[dai_index].cpus->dai_name = "ssp0-port"; - /* override plaform name, if required */ + /* override platform name, if required */ platform_name = mach->mach_params.platform; ret_val = snd_soc_fixup_dai_links_platform_name(card, diff --git a/sound/soc/intel/boards/cht_bsw_rt5672.c b/sound/soc/intel/boards/cht_bsw_rt5672.c index 26eb8ad0d262..9882aeb24d33 100644 --- a/sound/soc/intel/boards/cht_bsw_rt5672.c +++ b/sound/soc/intel/boards/cht_bsw_rt5672.c @@ -483,7 +483,7 @@ static int snd_cht_mc_probe(struct platform_device *pdev) drv->use_ssp0 = true; } - /* override plaform name, if required */ + /* override platform name, if required */ snd_soc_card_cht.dev = &pdev->dev; platform_name = mach->mach_params.platform; diff --git a/sound/soc/intel/boards/glk_rt5682_max98357a.c b/sound/soc/intel/boards/glk_rt5682_max98357a.c index bad3829e52ca..e4bfb0fe5f12 100644 --- a/sound/soc/intel/boards/glk_rt5682_max98357a.c +++ b/sound/soc/intel/boards/glk_rt5682_max98357a.c @@ -638,7 +638,7 @@ static int geminilake_audio_probe(struct platform_device *pdev) card->dev = &pdev->dev; snd_soc_card_set_drvdata(card, ctx); - /* override plaform name, if required */ + /* override platform name, if required */ mach = pdev->dev.platform_data; platform_name = mach->mach_params.platform; diff --git a/sound/soc/intel/boards/haswell.c b/sound/soc/intel/boards/haswell.c index 36e136acbef5..aa61e101f793 100644 --- a/sound/soc/intel/boards/haswell.c +++ b/sound/soc/intel/boards/haswell.c @@ -175,7 +175,7 @@ static int haswell_audio_probe(struct platform_device *pdev) haswell_rt5640.dev = &pdev->dev; - /* override plaform name, if required */ + /* override platform name, if required */ mach = pdev->dev.platform_data; ret = snd_soc_fixup_dai_links_platform_name(&haswell_rt5640, mach->mach_params.platform); diff --git a/sound/soc/intel/boards/sof_cirrus_common.c b/sound/soc/intel/boards/sof_cirrus_common.c new file mode 100644 index 000000000000..e71d74ec1b0b --- /dev/null +++ b/sound/soc/intel/boards/sof_cirrus_common.c @@ -0,0 +1,163 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * This file defines data structures and functions used in Machine + * Driver for Intel platforms with Cirrus Logic Codecs. + * + * Copyright 2022 Intel Corporation. + */ +#include <linux/module.h> +#include <sound/sof.h> +#include "../../codecs/cs35l41.h" +#include "sof_cirrus_common.h" + +/* + * Cirrus Logic CS35L41/CS35L53 + */ +static const struct snd_kcontrol_new cs35l41_kcontrols[] = { + SOC_DAPM_PIN_SWITCH("WL Spk"), + SOC_DAPM_PIN_SWITCH("WR Spk"), + SOC_DAPM_PIN_SWITCH("TL Spk"), + SOC_DAPM_PIN_SWITCH("TR Spk"), +}; + +static const struct snd_soc_dapm_widget cs35l41_dapm_widgets[] = { + SND_SOC_DAPM_SPK("WL Spk", NULL), + SND_SOC_DAPM_SPK("WR Spk", NULL), + SND_SOC_DAPM_SPK("TL Spk", NULL), + SND_SOC_DAPM_SPK("TR Spk", NULL), +}; + +static const struct snd_soc_dapm_route cs35l41_dapm_routes[] = { + /* speaker */ + {"WL Spk", NULL, "WL SPK"}, + {"WR Spk", NULL, "WR SPK"}, + {"TL Spk", NULL, "TL SPK"}, + {"TR Spk", NULL, "TR SPK"}, +}; + +static struct snd_soc_dai_link_component cs35l41_components[] = { + { + .name = CS35L41_DEV0_NAME, + .dai_name = CS35L41_CODEC_DAI, + }, + { + .name = CS35L41_DEV1_NAME, + .dai_name = CS35L41_CODEC_DAI, + }, + { + .name = CS35L41_DEV2_NAME, + .dai_name = CS35L41_CODEC_DAI, + }, + { + .name = CS35L41_DEV3_NAME, + .dai_name = CS35L41_CODEC_DAI, + }, +}; + +static struct snd_soc_codec_conf cs35l41_codec_conf[] = { + { + .dlc = COMP_CODEC_CONF(CS35L41_DEV0_NAME), + .name_prefix = "WL", + }, + { + .dlc = COMP_CODEC_CONF(CS35L41_DEV1_NAME), + .name_prefix = "WR", + }, + { + .dlc = COMP_CODEC_CONF(CS35L41_DEV2_NAME), + .name_prefix = "TL", + }, + { + .dlc = COMP_CODEC_CONF(CS35L41_DEV3_NAME), + .name_prefix = "TR", + }, +}; + +static int cs35l41_init(struct snd_soc_pcm_runtime *rtd) +{ + struct snd_soc_card *card = rtd->card; + int ret; + + ret = snd_soc_dapm_new_controls(&card->dapm, cs35l41_dapm_widgets, + ARRAY_SIZE(cs35l41_dapm_widgets)); + if (ret) { + dev_err(rtd->dev, "fail to add dapm controls, ret %d\n", ret); + return ret; + } + + ret = snd_soc_add_card_controls(card, cs35l41_kcontrols, + ARRAY_SIZE(cs35l41_kcontrols)); + if (ret) { + dev_err(rtd->dev, "fail to add card controls, ret %d\n", ret); + return ret; + } + + ret = snd_soc_dapm_add_routes(&card->dapm, cs35l41_dapm_routes, + ARRAY_SIZE(cs35l41_dapm_routes)); + + if (ret) + dev_err(rtd->dev, "fail to add dapm routes, ret %d\n", ret); + + return ret; +} + +static int cs35l41_hw_params(struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *params) +{ + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); + struct snd_soc_dai *codec_dai; + int clk_freq, i, ret; + + clk_freq = sof_dai_get_bclk(rtd); /* BCLK freq */ + + if (clk_freq <= 0) { + dev_err(rtd->dev, "fail to get bclk freq, ret %d\n", clk_freq); + return -EINVAL; + } + + for_each_rtd_codec_dais(rtd, i, codec_dai) { + /* call dai driver's set_sysclk() callback */ + ret = snd_soc_dai_set_sysclk(codec_dai, CS35L41_CLKID_SCLK, + clk_freq, SND_SOC_CLOCK_IN); + if (ret < 0) { + dev_err(codec_dai->dev, "fail to set sysclk, ret %d\n", + ret); + return ret; + } + + /* call component driver's set_sysclk() callback */ + ret = snd_soc_component_set_sysclk(codec_dai->component, + CS35L41_CLKID_SCLK, 0, + clk_freq, SND_SOC_CLOCK_IN); + if (ret < 0) { + dev_err(codec_dai->dev, "fail to set component sysclk, ret %d\n", + ret); + return ret; + } + } + + return 0; +} + +static const struct snd_soc_ops cs35l41_ops = { + .hw_params = cs35l41_hw_params, +}; + +void cs35l41_set_dai_link(struct snd_soc_dai_link *link) +{ + link->codecs = cs35l41_components; + link->num_codecs = ARRAY_SIZE(cs35l41_components); + link->init = cs35l41_init; + link->ops = &cs35l41_ops; +} +EXPORT_SYMBOL_NS(cs35l41_set_dai_link, SND_SOC_INTEL_SOF_CIRRUS_COMMON); + +void cs35l41_set_codec_conf(struct snd_soc_card *card) +{ + card->codec_conf = cs35l41_codec_conf; + card->num_configs = ARRAY_SIZE(cs35l41_codec_conf); +} +EXPORT_SYMBOL_NS(cs35l41_set_codec_conf, SND_SOC_INTEL_SOF_CIRRUS_COMMON); + +MODULE_DESCRIPTION("ASoC Intel SOF Cirrus Logic helpers"); +MODULE_LICENSE("GPL"); diff --git a/sound/soc/intel/boards/sof_cirrus_common.h b/sound/soc/intel/boards/sof_cirrus_common.h new file mode 100644 index 000000000000..ca438c12c386 --- /dev/null +++ b/sound/soc/intel/boards/sof_cirrus_common.h @@ -0,0 +1,25 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * This file defines data structures used in Machine Driver for Intel + * platforms with Cirrus Logic Codecs. + * + * Copyright 2022 Intel Corporation. + */ +#ifndef __SOF_CIRRUS_COMMON_H +#define __SOF_CIRRUS_COMMON_H + +#include <sound/soc.h> + +/* + * Cirrus Logic CS35L41/CS35L53 + */ +#define CS35L41_CODEC_DAI "cs35l41-pcm" +#define CS35L41_DEV0_NAME "i2c-CSC3541:00" +#define CS35L41_DEV1_NAME "i2c-CSC3541:01" +#define CS35L41_DEV2_NAME "i2c-CSC3541:02" +#define CS35L41_DEV3_NAME "i2c-CSC3541:03" + +void cs35l41_set_dai_link(struct snd_soc_dai_link *link); +void cs35l41_set_codec_conf(struct snd_soc_card *card); + +#endif /* __SOF_CIRRUS_COMMON_H */ diff --git a/sound/soc/intel/boards/sof_es8336.c b/sound/soc/intel/boards/sof_es8336.c index 20d577eaab6d..5e0529aa4f1d 100644 --- a/sound/soc/intel/boards/sof_es8336.c +++ b/sound/soc/intel/boards/sof_es8336.c @@ -21,11 +21,15 @@ #include <sound/soc-acpi.h> #include "hda_dsp_common.h" +/* jd-inv + terminating entry */ +#define MAX_NO_PROPS 2 + #define SOF_ES8336_SSP_CODEC(quirk) ((quirk) & GENMASK(3, 0)) #define SOF_ES8336_SSP_CODEC_MASK (GENMASK(3, 0)) #define SOF_ES8336_TGL_GPIO_QUIRK BIT(4) #define SOF_ES8336_ENABLE_DMIC BIT(5) +#define SOF_ES8336_JD_INVERTED BIT(6) static unsigned long quirk; @@ -63,7 +67,14 @@ static const struct acpi_gpio_mapping *gpio_mapping = acpi_es8336_gpios; static void log_quirks(struct device *dev) { - dev_info(dev, "quirk SSP%ld", SOF_ES8336_SSP_CODEC(quirk)); + dev_info(dev, "quirk mask %#lx\n", quirk); + dev_info(dev, "quirk SSP%ld\n", SOF_ES8336_SSP_CODEC(quirk)); + if (quirk & SOF_ES8336_ENABLE_DMIC) + dev_info(dev, "quirk DMIC enabled\n"); + if (quirk & SOF_ES8336_TGL_GPIO_QUIRK) + dev_info(dev, "quirk TGL GPIO enabled\n"); + if (quirk & SOF_ES8336_JD_INVERTED) + dev_info(dev, "quirk JD inverted enabled\n"); } static int sof_es8316_speaker_power_event(struct snd_soc_dapm_widget *w, @@ -228,24 +239,25 @@ static int sof_es8336_quirk_cb(const struct dmi_system_id *id) return 1; } +/* + * this table should only be used to add GPIO or jack-detection quirks + * that cannot be detected from ACPI tables. The SSP and DMIC + * information are providing by the platform driver and are aligned + * with the topology used. + * + * If the GPIO support is missing, the quirk parameter can be used to + * enable speakers. In that case it's recommended to keep the SSP and DMIC + * information consistent, overriding the SSP and DMIC can only be done + * if the topology file is modified as well. + */ static const struct dmi_system_id sof_es8336_quirk_table[] = { { .callback = sof_es8336_quirk_cb, .matches = { - DMI_MATCH(DMI_SYS_VENDOR, "CHUWI Innovation And Technology"), - DMI_MATCH(DMI_BOARD_NAME, "Hi10 X"), - }, - .driver_data = (void *)SOF_ES8336_SSP_CODEC(2) - }, - { - .callback = sof_es8336_quirk_cb, - .matches = { DMI_MATCH(DMI_SYS_VENDOR, "IP3 tech"), DMI_MATCH(DMI_BOARD_NAME, "WN1"), }, - .driver_data = (void *)(SOF_ES8336_SSP_CODEC(0) | - SOF_ES8336_TGL_GPIO_QUIRK | - SOF_ES8336_ENABLE_DMIC) + .driver_data = (void *)(SOF_ES8336_TGL_GPIO_QUIRK) }, {} }; @@ -280,7 +292,7 @@ static struct snd_soc_dai_link_component platform_component[] = { } }; -SND_SOC_DAILINK_DEF(ssp1_codec, +SND_SOC_DAILINK_DEF(es8336_codec, DAILINK_COMP_ARRAY(COMP_CODEC("i2c-ESSX8336:00", "ES8316 HiFi"))); static struct snd_soc_dai_link_component dmic_component[] = { @@ -344,8 +356,8 @@ static struct snd_soc_dai_link *sof_card_dai_links_create(struct device *dev, goto devm_err; links[id].id = id; - links[id].codecs = ssp1_codec; - links[id].num_codecs = ARRAY_SIZE(ssp1_codec); + links[id].codecs = es8336_codec; + links[id].num_codecs = ARRAY_SIZE(es8336_codec); links[id].platforms = platform_component; links[id].num_platforms = ARRAY_SIZE(platform_component); links[id].init = sof_es8316_init; @@ -447,6 +459,8 @@ devm_err: return NULL; } +static char soc_components[30]; + /* i2c-<HID>:00 with HID being 8 chars */ static char codec_name[SND_ACPI_I2C_ID_LEN]; @@ -455,10 +469,13 @@ static int sof_es8336_probe(struct platform_device *pdev) struct device *dev = &pdev->dev; struct snd_soc_card *card; struct snd_soc_acpi_mach *mach = pdev->dev.platform_data; + struct property_entry props[MAX_NO_PROPS] = {}; struct sof_es8336_private *priv; + struct fwnode_handle *fwnode; struct acpi_device *adev; struct snd_soc_dai_link *dai_links; struct device *codec_dev; + unsigned int cnt = 0; int dmic_be_num = 0; int hdmi_num = 3; int ret; @@ -470,11 +487,33 @@ static int sof_es8336_probe(struct platform_device *pdev) card = &sof_es8336_card; card->dev = dev; - if (!dmi_check_system(sof_es8336_quirk_table)) - quirk = SOF_ES8336_SSP_CODEC(2); + /* check GPIO DMI quirks */ + dmi_check_system(sof_es8336_quirk_table); - if (quirk & SOF_ES8336_ENABLE_DMIC) - dmic_be_num = 2; + if (!mach->mach_params.i2s_link_mask) { + dev_warn(dev, "No I2S link information provided, using SSP0. This may need to be modified with the quirk module parameter\n"); + } 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. + * In some cases multiple SSPs can be reported by NHLT, starting MSB-first + * seems to pick the right connection. + */ + unsigned long ssp = 0; + + if (mach->mach_params.i2s_link_mask & BIT(2)) + ssp = SOF_ES8336_SSP_CODEC(2); + else if (mach->mach_params.i2s_link_mask & BIT(1)) + ssp = SOF_ES8336_SSP_CODEC(1); + else if (mach->mach_params.i2s_link_mask & BIT(0)) + ssp = SOF_ES8336_SSP_CODEC(0); + + quirk |= ssp; + } + + 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 +522,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), @@ -499,6 +541,13 @@ static int sof_es8336_probe(struct platform_device *pdev) "i2c-%s", acpi_dev_name(adev)); put_device(&adev->dev); dai_links[0].codecs->name = codec_name; + + /* also fixup codec dai name if relevant */ + if (!strncmp(mach->id, "ESSX8326", SND_ACPI_I2C_ID_LEN)) + dai_links[0].codecs->dai_name = "ES8326 HiFi"; + } else { + dev_err(dev, "Error cannot find '%s' dev\n", mach->id); + return -ENXIO; } ret = snd_soc_fixup_dai_links_platform_name(&sof_es8336_card, @@ -506,38 +555,64 @@ static int sof_es8336_probe(struct platform_device *pdev) if (ret) return ret; - /* get speaker enable GPIO */ - codec_dev = bus_find_device_by_name(&i2c_bus_type, NULL, codec_name); + codec_dev = acpi_get_first_physical_node(adev); if (!codec_dev) return -EPROBE_DEFER; + priv->codec_dev = get_device(codec_dev); + + if (quirk & SOF_ES8336_JD_INVERTED) + props[cnt++] = PROPERTY_ENTRY_BOOL("everest,jack-detect-inverted"); + + if (cnt) { + fwnode = fwnode_create_software_node(props, NULL); + if (IS_ERR(fwnode)) { + put_device(codec_dev); + return PTR_ERR(fwnode); + } + + ret = device_add_software_node(codec_dev, to_software_node(fwnode)); + fwnode_handle_put(fwnode); + + if (ret) { + put_device(codec_dev); + return ret; + } + } + + /* get speaker enable GPIO */ ret = devm_acpi_dev_add_driver_gpios(codec_dev, gpio_mapping); if (ret) dev_warn(codec_dev, "unable to add GPIO mapping table\n"); - priv->gpio_pa = gpiod_get(codec_dev, "pa-enable", GPIOD_OUT_LOW); + priv->gpio_pa = gpiod_get_optional(codec_dev, "pa-enable", GPIOD_OUT_LOW); if (IS_ERR(priv->gpio_pa)) { - ret = PTR_ERR(priv->gpio_pa); - dev_err(codec_dev, "%s, could not get pa-enable: %d\n", - __func__, ret); - goto err; + ret = dev_err_probe(dev, PTR_ERR(priv->gpio_pa), + "could not get pa-enable GPIO\n"); + goto err_put_codec; } - priv->codec_dev = codec_dev; INIT_LIST_HEAD(&priv->hdmi_pcm_list); snd_soc_card_set_drvdata(card, priv); + if (mach->mach_params.dmic_num > 0) { + snprintf(soc_components, sizeof(soc_components), + "cfg-dmics:%d", mach->mach_params.dmic_num); + card->components = soc_components; + } + ret = devm_snd_soc_register_card(dev, card); if (ret) { gpiod_put(priv->gpio_pa); dev_err(dev, "snd_soc_register_card failed: %d\n", ret); - goto err; + goto err_put_codec; } platform_set_drvdata(pdev, &sof_es8336_card); return 0; -err: +err_put_codec: + device_remove_software_node(priv->codec_dev); put_device(codec_dev); return ret; } @@ -548,6 +623,7 @@ static int sof_es8336_remove(struct platform_device *pdev) struct sof_es8336_private *priv = snd_soc_card_get_drvdata(card); gpiod_put(priv->gpio_pa); + device_remove_software_node(priv->codec_dev); put_device(priv->codec_dev); return 0; diff --git a/sound/soc/intel/boards/sof_realtek_common.c b/sound/soc/intel/boards/sof_realtek_common.c index 4cf131310ad3..a2bcbeee0216 100644 --- a/sound/soc/intel/boards/sof_realtek_common.c +++ b/sound/soc/intel/boards/sof_realtek_common.c @@ -10,9 +10,11 @@ #include <sound/soc-acpi.h> #include <sound/soc-dai.h> #include <sound/soc-dapm.h> +#include <sound/sof.h> #include <uapi/sound/asound.h> #include "../../codecs/rt1011.h" #include "../../codecs/rt1015.h" +#include "../../codecs/rt1308.h" #include "sof_realtek_common.h" /* @@ -132,12 +134,14 @@ void sof_rt1011_dai_link(struct snd_soc_dai_link *link) link->init = rt1011_init; link->ops = &rt1011_ops; } +EXPORT_SYMBOL_NS(sof_rt1011_dai_link, SND_SOC_INTEL_SOF_REALTEK_COMMON); void sof_rt1011_codec_conf(struct snd_soc_card *card) { card->codec_conf = rt1011_codec_confs; card->num_configs = ARRAY_SIZE(rt1011_codec_confs); } +EXPORT_SYMBOL_NS(sof_rt1011_codec_conf, SND_SOC_INTEL_SOF_REALTEK_COMMON); /* * rt1015: i2c mode driver for ALC1015 and ALC1015Q @@ -233,6 +237,7 @@ void sof_rt1015p_dai_link(struct snd_soc_dai_link *link) link->init = rt1015p_init; link->ops = &rt1015p_ops; } +EXPORT_SYMBOL_NS(sof_rt1015p_dai_link, SND_SOC_INTEL_SOF_REALTEK_COMMON); void sof_rt1015p_codec_conf(struct snd_soc_card *card) { @@ -242,6 +247,7 @@ void sof_rt1015p_codec_conf(struct snd_soc_card *card) card->codec_conf = rt1015p_codec_confs; card->num_configs = ARRAY_SIZE(rt1015p_codec_confs); } +EXPORT_SYMBOL_NS(sof_rt1015p_codec_conf, SND_SOC_INTEL_SOF_REALTEK_COMMON); /* * RT1015 audio amplifier @@ -343,6 +349,7 @@ void sof_rt1015_codec_conf(struct snd_soc_card *card) card->codec_conf = rt1015_amp_conf; card->num_configs = ARRAY_SIZE(rt1015_amp_conf); } +EXPORT_SYMBOL_NS(sof_rt1015_codec_conf, SND_SOC_INTEL_SOF_REALTEK_COMMON); void sof_rt1015_dai_link(struct snd_soc_dai_link *link, unsigned int fs) { @@ -354,3 +361,103 @@ void sof_rt1015_dai_link(struct snd_soc_dai_link *link, unsigned int fs) if (fs == 100) rt1015_ops.hw_params = rt1015_hw_params_pll_and_tdm; } +EXPORT_SYMBOL_NS(sof_rt1015_dai_link, SND_SOC_INTEL_SOF_REALTEK_COMMON); + +/* + * RT1308 audio amplifier + */ +static const struct snd_kcontrol_new rt1308_kcontrols[] = { + SOC_DAPM_PIN_SWITCH("Speakers"), +}; + +static const struct snd_soc_dapm_widget rt1308_dapm_widgets[] = { + SND_SOC_DAPM_SPK("Speakers", NULL), +}; + +static const struct snd_soc_dapm_route rt1308_dapm_routes[] = { + /* speaker */ + {"Speakers", NULL, "SPOL"}, + {"Speakers", NULL, "SPOR"}, +}; + +static struct snd_soc_dai_link_component rt1308_components[] = { + { + .name = RT1308_DEV0_NAME, + .dai_name = RT1308_CODEC_DAI, + } +}; + +static int rt1308_init(struct snd_soc_pcm_runtime *rtd) +{ + struct snd_soc_card *card = rtd->card; + int ret; + + ret = snd_soc_dapm_new_controls(&card->dapm, rt1308_dapm_widgets, + ARRAY_SIZE(rt1308_dapm_widgets)); + if (ret) { + dev_err(rtd->dev, "fail to add dapm controls, ret %d\n", ret); + return ret; + } + + ret = snd_soc_add_card_controls(card, rt1308_kcontrols, + ARRAY_SIZE(rt1308_kcontrols)); + if (ret) { + dev_err(rtd->dev, "fail to add card controls, ret %d\n", ret); + return ret; + } + + ret = snd_soc_dapm_add_routes(&card->dapm, rt1308_dapm_routes, + ARRAY_SIZE(rt1308_dapm_routes)); + + if (ret) + dev_err(rtd->dev, "fail to add dapm routes, ret %d\n", ret); + + return ret; +} + +static int rt1308_hw_params(struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *params) +{ + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); + struct snd_soc_card *card = rtd->card; + struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0); + int clk_id, clk_freq, pll_out; + int ret; + + clk_id = RT1308_PLL_S_MCLK; + /* get the tplg configured mclk. */ + clk_freq = sof_dai_get_mclk(rtd); + + pll_out = params_rate(params) * 512; + + /* Set rt1308 pll */ + ret = snd_soc_dai_set_pll(codec_dai, 0, clk_id, clk_freq, pll_out); + if (ret < 0) { + dev_err(card->dev, "Failed to set RT1308 PLL: %d\n", ret); + return ret; + } + + /* Set rt1308 sysclk */ + ret = snd_soc_dai_set_sysclk(codec_dai, RT1308_FS_SYS_S_PLL, pll_out, + SND_SOC_CLOCK_IN); + if (ret < 0) + dev_err(card->dev, "Failed to set RT1308 SYSCLK: %d\n", ret); + + return ret; +} + +static const struct snd_soc_ops rt1308_ops = { + .hw_params = rt1308_hw_params, +}; + +void sof_rt1308_dai_link(struct snd_soc_dai_link *link) +{ + link->codecs = rt1308_components; + link->num_codecs = ARRAY_SIZE(rt1308_components); + link->init = rt1308_init; + link->ops = &rt1308_ops; +} +EXPORT_SYMBOL_NS(sof_rt1308_dai_link, SND_SOC_INTEL_SOF_REALTEK_COMMON); + +MODULE_DESCRIPTION("ASoC Intel SOF Realtek helpers"); +MODULE_LICENSE("GPL"); diff --git a/sound/soc/intel/boards/sof_realtek_common.h b/sound/soc/intel/boards/sof_realtek_common.h index 228ac9c08430..e0a5518e8dd2 100644 --- a/sound/soc/intel/boards/sof_realtek_common.h +++ b/sound/soc/intel/boards/sof_realtek_common.h @@ -35,4 +35,8 @@ void sof_rt1015p_codec_conf(struct snd_soc_card *card); void sof_rt1015_dai_link(struct snd_soc_dai_link *link, unsigned int fs); void sof_rt1015_codec_conf(struct snd_soc_card *card); +#define RT1308_CODEC_DAI "rt1308-aif" +#define RT1308_DEV0_NAME "i2c-10EC1308:00" +void sof_rt1308_dai_link(struct snd_soc_dai_link *link); + #endif /* __SOF_REALTEK_COMMON_H */ diff --git a/sound/soc/intel/boards/sof_rt5682.c b/sound/soc/intel/boards/sof_rt5682.c index bd6d2e7dea53..ebec4d15edaa 100644 --- a/sound/soc/intel/boards/sof_rt5682.c +++ b/sound/soc/intel/boards/sof_rt5682.c @@ -81,6 +81,7 @@ struct sof_card_private { struct snd_soc_jack sof_headset; struct list_head hdmi_pcm_list; bool common_hdmi_codec_drv; + bool idisp_codec; }; static int sof_rt5682_quirk_cb(const struct dmi_system_id *id) @@ -369,11 +370,16 @@ static int sof_rt5682_hw_params(struct snd_pcm_substream *substream, pll_out = params_rate(params) * 512; - /* Configure pll for codec */ - ret = snd_soc_dai_set_pll(codec_dai, pll_id, pll_source, pll_in, - pll_out); - if (ret < 0) - dev_err(rtd->dev, "snd_soc_dai_set_pll err = %d\n", ret); + /* when MCLK is 512FS, no need to set PLL configuration additionally. */ + if (pll_in == pll_out) + clk_id = RT5682S_SCLK_S_MCLK; + else { + /* Configure pll for codec */ + ret = snd_soc_dai_set_pll(codec_dai, pll_id, pll_source, pll_in, + pll_out); + if (ret < 0) + dev_err(rtd->dev, "snd_soc_dai_set_pll err = %d\n", ret); + } /* Configure sysclk for codec */ ret = snd_soc_dai_set_sysclk(codec_dai, clk_id, @@ -417,7 +423,7 @@ static int sof_card_late_probe(struct snd_soc_card *card) int i = 0; /* HDMI is not supported by SOF on Baytrail/CherryTrail */ - if (is_legacy_cpu) + if (is_legacy_cpu || !ctx->idisp_codec) return 0; if (list_empty(&ctx->hdmi_pcm_list)) @@ -558,11 +564,14 @@ static struct snd_soc_dai_link_component dummy_component[] = { } }; +#define IDISP_CODEC_MASK 0x4 + static struct snd_soc_dai_link *sof_card_dai_links_create(struct device *dev, int ssp_codec, int ssp_amp, int dmic_be_num, - int hdmi_num) + int hdmi_num, + bool idisp_codec) { struct snd_soc_dai_link_component *idisp_components; struct snd_soc_dai_link_component *cpus; @@ -676,13 +685,18 @@ static struct snd_soc_dai_link *sof_card_dai_links_create(struct device *dev, if (!links[id].cpus->dai_name) goto devm_err; - idisp_components[i - 1].name = "ehdaudio0D2"; - idisp_components[i - 1].dai_name = devm_kasprintf(dev, - GFP_KERNEL, - "intel-hdmi-hifi%d", - i); - if (!idisp_components[i - 1].dai_name) - goto devm_err; + if (idisp_codec) { + idisp_components[i - 1].name = "ehdaudio0D2"; + idisp_components[i - 1].dai_name = devm_kasprintf(dev, + GFP_KERNEL, + "intel-hdmi-hifi%d", + i); + if (!idisp_components[i - 1].dai_name) + goto devm_err; + } else { + idisp_components[i - 1].name = "snd-soc-dummy"; + idisp_components[i - 1].dai_name = "snd-soc-dummy-dai"; + } links[id].codecs = &idisp_components[i - 1]; links[id].num_codecs = 1; @@ -838,6 +852,9 @@ static int sof_audio_probe(struct platform_device *pdev) /* default number of HDMI DAI's */ if (!hdmi_num) hdmi_num = 3; + + if (mach->mach_params.codec_mask & IDISP_CODEC_MASK) + ctx->idisp_codec = true; } /* need to get main clock from pmc */ @@ -892,7 +909,7 @@ static int sof_audio_probe(struct platform_device *pdev) sof_audio_card_rt5682.num_links++; dai_links = sof_card_dai_links_create(&pdev->dev, ssp_codec, ssp_amp, - dmic_be_num, hdmi_num); + dmic_be_num, hdmi_num, ctx->idisp_codec); if (!dai_links) return -ENOMEM; @@ -1033,6 +1050,14 @@ static const struct platform_device_id board_ids[] = { SOF_BT_OFFLOAD_SSP(2) | SOF_SSP_BT_OFFLOAD_PRESENT), }, + { + .name = "adl_rt5682", + .driver_data = (kernel_ulong_t)(SOF_RT5682_MCLK_EN | + SOF_RT5682_SSP_CODEC(0) | + SOF_RT5682_NUM_HDMIDEV(4) | + SOF_BT_OFFLOAD_SSP(2) | + SOF_SSP_BT_OFFLOAD_PRESENT), + }, { } }; MODULE_DEVICE_TABLE(platform, board_ids); @@ -1056,3 +1081,4 @@ MODULE_AUTHOR("Mac Chiang <mac.chiang@intel.com>"); MODULE_LICENSE("GPL v2"); MODULE_IMPORT_NS(SND_SOC_INTEL_HDA_DSP_COMMON); MODULE_IMPORT_NS(SND_SOC_INTEL_SOF_MAXIM_COMMON); +MODULE_IMPORT_NS(SND_SOC_INTEL_SOF_REALTEK_COMMON); diff --git a/sound/soc/intel/boards/sof_sdw.c b/sound/soc/intel/boards/sof_sdw.c index da515eb1ddbe..1f00679b4240 100644 --- a/sound/soc/intel/boards/sof_sdw.c +++ b/sound/soc/intel/boards/sof_sdw.c @@ -185,7 +185,7 @@ static const struct dmi_system_id sof_sdw_quirk_table[] = { .callback = sof_sdw_quirk_cb, .matches = { DMI_MATCH(DMI_SYS_VENDOR, "HP"), - DMI_MATCH(DMI_PRODUCT_NAME, "HP Spectre x360 Convertible"), + DMI_MATCH(DMI_PRODUCT_NAME, "HP Spectre x360 Conv"), }, .driver_data = (void *)(SOF_SDW_TGL_HDMI | SOF_SDW_PCH_DMIC | diff --git a/sound/soc/intel/boards/sof_ssp_amp.c b/sound/soc/intel/boards/sof_ssp_amp.c new file mode 100644 index 000000000000..88530e9de543 --- /dev/null +++ b/sound/soc/intel/boards/sof_ssp_amp.c @@ -0,0 +1,483 @@ +// SPDX-License-Identifier: GPL-2.0-only +// +// Copyright(c) 2022 Intel Corporation. All rights reserved. + +/* + * sof_ssp_amp.c - ASoc Machine driver for Intel platforms + * with RT1308/CS35L41 codec. + */ + +#include <linux/acpi.h> +#include <linux/delay.h> +#include <linux/module.h> +#include <linux/platform_device.h> +#include <sound/core.h> +#include <sound/jack.h> +#include <sound/pcm.h> +#include <sound/pcm_params.h> +#include <sound/sof.h> +#include "../../codecs/hdac_hdmi.h" +#include "hda_dsp_common.h" +#include "sof_realtek_common.h" +#include "sof_cirrus_common.h" + +#define NAME_SIZE 32 + +/* SSP port ID for speaker amplifier */ +#define SOF_AMPLIFIER_SSP(quirk) ((quirk) & GENMASK(3, 0)) +#define SOF_AMPLIFIER_SSP_MASK (GENMASK(3, 0)) + +/* HDMI capture*/ +#define SOF_SSP_HDMI_CAPTURE_PRESENT BIT(4) +#define SOF_NO_OF_HDMI_CAPTURE_SSP_SHIFT 5 +#define SOF_NO_OF_HDMI_CAPTURE_SSP_MASK (GENMASK(6, 5)) +#define SOF_NO_OF_HDMI_CAPTURE_SSP(quirk) \ + (((quirk) << SOF_NO_OF_HDMI_CAPTURE_SSP_SHIFT) & SOF_NO_OF_HDMI_CAPTURE_SSP_MASK) + +#define SOF_HDMI_CAPTURE_1_SSP_SHIFT 7 +#define SOF_HDMI_CAPTURE_1_SSP_MASK (GENMASK(9, 7)) +#define SOF_HDMI_CAPTURE_1_SSP(quirk) \ + (((quirk) << SOF_HDMI_CAPTURE_1_SSP_SHIFT) & SOF_HDMI_CAPTURE_1_SSP_MASK) + +#define SOF_HDMI_CAPTURE_2_SSP_SHIFT 10 +#define SOF_HDMI_CAPTURE_2_SSP_MASK (GENMASK(12, 10)) +#define SOF_HDMI_CAPTURE_2_SSP(quirk) \ + (((quirk) << SOF_HDMI_CAPTURE_2_SSP_SHIFT) & SOF_HDMI_CAPTURE_2_SSP_MASK) + +/* HDMI playback */ +#define SOF_HDMI_PLAYBACK_PRESENT BIT(13) +#define SOF_NO_OF_HDMI_PLAYBACK_SHIFT 14 +#define SOF_NO_OF_HDMI_PLAYBACK_MASK (GENMASK(16, 14)) +#define SOF_NO_OF_HDMI_PLAYBACK(quirk) \ + (((quirk) << SOF_NO_OF_HDMI_PLAYBACK_SHIFT) & SOF_NO_OF_HDMI_PLAYBACK_MASK) + +/* BT audio offload */ +#define SOF_SSP_BT_OFFLOAD_PRESENT BIT(17) +#define SOF_BT_OFFLOAD_SSP_SHIFT 18 +#define SOF_BT_OFFLOAD_SSP_MASK (GENMASK(20, 18)) +#define SOF_BT_OFFLOAD_SSP(quirk) \ + (((quirk) << SOF_BT_OFFLOAD_SSP_SHIFT) & SOF_BT_OFFLOAD_SSP_MASK) + +/* Speaker amplifiers */ +#define SOF_RT1308_SPEAKER_AMP_PRESENT BIT(21) +#define SOF_CS35L41_SPEAKER_AMP_PRESENT BIT(22) + +/* Default: SSP2 */ +static unsigned long sof_ssp_amp_quirk = SOF_AMPLIFIER_SSP(2); + +struct sof_hdmi_pcm { + struct list_head head; + struct snd_soc_jack sof_hdmi; + struct snd_soc_dai *codec_dai; + int device; +}; + +struct sof_card_private { + struct list_head hdmi_pcm_list; + bool common_hdmi_codec_drv; + bool idisp_codec; +}; + +static const struct snd_soc_dapm_widget sof_ssp_amp_dapm_widgets[] = { + SND_SOC_DAPM_MIC("SoC DMIC", NULL), +}; + +static const struct snd_soc_dapm_route sof_ssp_amp_dapm_routes[] = { + /* digital mics */ + {"DMic", NULL, "SoC DMIC"}, +}; + +static int sof_card_late_probe(struct snd_soc_card *card) +{ + struct sof_card_private *ctx = snd_soc_card_get_drvdata(card); + struct snd_soc_component *component = NULL; + char jack_name[NAME_SIZE]; + struct sof_hdmi_pcm *pcm; + int err; + int i = 0; + + if (!(sof_ssp_amp_quirk & SOF_HDMI_PLAYBACK_PRESENT)) + return 0; + + /* HDMI is not supported by SOF on Baytrail/CherryTrail */ + if (!ctx->idisp_codec) + return 0; + + if (list_empty(&ctx->hdmi_pcm_list)) + return -EINVAL; + + if (ctx->common_hdmi_codec_drv) { + pcm = list_first_entry(&ctx->hdmi_pcm_list, struct sof_hdmi_pcm, + head); + component = pcm->codec_dai->component; + return hda_dsp_hdmi_build_controls(card, component); + } + + list_for_each_entry(pcm, &ctx->hdmi_pcm_list, head) { + component = pcm->codec_dai->component; + snprintf(jack_name, sizeof(jack_name), + "HDMI/DP, pcm=%d Jack", pcm->device); + err = snd_soc_card_jack_new(card, jack_name, + SND_JACK_AVOUT, &pcm->sof_hdmi, + NULL, 0); + + if (err) + return err; + + err = hdac_hdmi_jack_init(pcm->codec_dai, pcm->device, + &pcm->sof_hdmi); + if (err < 0) + return err; + + i++; + } + + return hdac_hdmi_jack_port_init(component, &card->dapm); +} + +static struct snd_soc_card sof_ssp_amp_card = { + .name = "ssp_amp", + .owner = THIS_MODULE, + .dapm_widgets = sof_ssp_amp_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(sof_ssp_amp_dapm_widgets), + .dapm_routes = sof_ssp_amp_dapm_routes, + .num_dapm_routes = ARRAY_SIZE(sof_ssp_amp_dapm_routes), + .fully_routed = true, + .late_probe = sof_card_late_probe, +}; + +static struct snd_soc_dai_link_component platform_component[] = { + { + /* name might be overridden during probe */ + .name = "0000:00:1f.3" + } +}; + +static struct snd_soc_dai_link_component dmic_component[] = { + { + .name = "dmic-codec", + .dai_name = "dmic-hifi", + } +}; + +static struct snd_soc_dai_link_component dummy_component[] = { + { + .name = "snd-soc-dummy", + .dai_name = "snd-soc-dummy-dai", + } +}; + +static int sof_hdmi_init(struct snd_soc_pcm_runtime *rtd) +{ + struct sof_card_private *ctx = snd_soc_card_get_drvdata(rtd->card); + struct snd_soc_dai *dai = asoc_rtd_to_codec(rtd, 0); + struct sof_hdmi_pcm *pcm; + + pcm = devm_kzalloc(rtd->card->dev, sizeof(*pcm), GFP_KERNEL); + if (!pcm) + return -ENOMEM; + + /* dai_link id is 1:1 mapped to the PCM device */ + pcm->device = rtd->dai_link->id; + pcm->codec_dai = dai; + + list_add_tail(&pcm->head, &ctx->hdmi_pcm_list); + + return 0; +} + +#define IDISP_CODEC_MASK 0x4 + +static struct snd_soc_dai_link *sof_card_dai_links_create(struct device *dev, + int ssp_codec, + int dmic_be_num, + int hdmi_num, + bool idisp_codec) +{ + struct snd_soc_dai_link_component *idisp_components; + struct snd_soc_dai_link_component *cpus; + struct snd_soc_dai_link *links; + int i, id = 0; + + links = devm_kzalloc(dev, sizeof(struct snd_soc_dai_link) * + sof_ssp_amp_card.num_links, GFP_KERNEL); + cpus = devm_kzalloc(dev, sizeof(struct snd_soc_dai_link_component) * + sof_ssp_amp_card.num_links, GFP_KERNEL); + if (!links || !cpus) + return NULL; + + /* HDMI-In SSP */ + if (sof_ssp_amp_quirk & SOF_SSP_HDMI_CAPTURE_PRESENT) { + int num_of_hdmi_ssp = (sof_ssp_amp_quirk & SOF_NO_OF_HDMI_CAPTURE_SSP_MASK) >> + SOF_NO_OF_HDMI_CAPTURE_SSP_SHIFT; + + for (i = 1; i <= num_of_hdmi_ssp; i++) { + int port = (i == 1 ? (sof_ssp_amp_quirk & SOF_HDMI_CAPTURE_1_SSP_MASK) >> + SOF_HDMI_CAPTURE_1_SSP_SHIFT : + (sof_ssp_amp_quirk & SOF_HDMI_CAPTURE_2_SSP_MASK) >> + SOF_HDMI_CAPTURE_2_SSP_SHIFT); + + links[id].cpus = &cpus[id]; + links[id].cpus->dai_name = devm_kasprintf(dev, GFP_KERNEL, + "SSP%d Pin", port); + if (!links[id].cpus->dai_name) + return NULL; + links[id].name = devm_kasprintf(dev, GFP_KERNEL, "SSP%d-HDMI", port); + if (!links[id].name) + return NULL; + links[id].id = id; + links[id].codecs = dummy_component; + links[id].num_codecs = ARRAY_SIZE(dummy_component); + links[id].platforms = platform_component; + links[id].num_platforms = ARRAY_SIZE(platform_component); + links[id].dpcm_capture = 1; + links[id].no_pcm = 1; + links[id].num_cpus = 1; + id++; + } + } + + /* codec SSP */ + links[id].name = devm_kasprintf(dev, GFP_KERNEL, "SSP%d-Codec", ssp_codec); + if (!links[id].name) + return NULL; + + links[id].id = id; + if (sof_ssp_amp_quirk & SOF_RT1308_SPEAKER_AMP_PRESENT) { + sof_rt1308_dai_link(&links[id]); + } else if (sof_ssp_amp_quirk & SOF_CS35L41_SPEAKER_AMP_PRESENT) { + cs35l41_set_dai_link(&links[id]); + } + links[id].platforms = platform_component; + links[id].num_platforms = ARRAY_SIZE(platform_component); + links[id].dpcm_playback = 1; + links[id].no_pcm = 1; + links[id].cpus = &cpus[id]; + links[id].num_cpus = 1; + links[id].cpus->dai_name = devm_kasprintf(dev, GFP_KERNEL, "SSP%d Pin", ssp_codec); + if (!links[id].cpus->dai_name) + return NULL; + + id++; + + /* dmic */ + if (dmic_be_num > 0) { + /* at least we have dmic01 */ + links[id].name = "dmic01"; + links[id].cpus = &cpus[id]; + links[id].cpus->dai_name = "DMIC01 Pin"; + if (dmic_be_num > 1) { + /* set up 2 BE links at most */ + links[id + 1].name = "dmic16k"; + links[id + 1].cpus = &cpus[id + 1]; + links[id + 1].cpus->dai_name = "DMIC16k Pin"; + dmic_be_num = 2; + } + } + + for (i = 0; i < dmic_be_num; i++) { + links[id].id = id; + links[id].num_cpus = 1; + links[id].codecs = dmic_component; + links[id].num_codecs = ARRAY_SIZE(dmic_component); + links[id].platforms = platform_component; + links[id].num_platforms = ARRAY_SIZE(platform_component); + links[id].ignore_suspend = 1; + links[id].dpcm_capture = 1; + links[id].no_pcm = 1; + id++; + } + + /* HDMI playback */ + if (sof_ssp_amp_quirk & SOF_HDMI_PLAYBACK_PRESENT) { + /* HDMI */ + if (hdmi_num > 0) { + idisp_components = devm_kzalloc(dev, + sizeof(struct snd_soc_dai_link_component) * + hdmi_num, GFP_KERNEL); + if (!idisp_components) + goto devm_err; + } + for (i = 1; i <= hdmi_num; i++) { + links[id].name = devm_kasprintf(dev, GFP_KERNEL, + "iDisp%d", i); + if (!links[id].name) + goto devm_err; + + links[id].id = id; + links[id].cpus = &cpus[id]; + links[id].num_cpus = 1; + links[id].cpus->dai_name = devm_kasprintf(dev, GFP_KERNEL, + "iDisp%d Pin", i); + if (!links[id].cpus->dai_name) + goto devm_err; + + if (idisp_codec) { + idisp_components[i - 1].name = "ehdaudio0D2"; + idisp_components[i - 1].dai_name = devm_kasprintf(dev, + GFP_KERNEL, + "intel-hdmi-hifi%d", + i); + if (!idisp_components[i - 1].dai_name) + goto devm_err; + } else { + idisp_components[i - 1].name = "snd-soc-dummy"; + idisp_components[i - 1].dai_name = "snd-soc-dummy-dai"; + } + + links[id].codecs = &idisp_components[i - 1]; + links[id].num_codecs = 1; + links[id].platforms = platform_component; + links[id].num_platforms = ARRAY_SIZE(platform_component); + links[id].init = sof_hdmi_init; + links[id].dpcm_playback = 1; + links[id].no_pcm = 1; + id++; + } + } + + /* BT audio offload */ + if (sof_ssp_amp_quirk & SOF_SSP_BT_OFFLOAD_PRESENT) { + int port = (sof_ssp_amp_quirk & SOF_BT_OFFLOAD_SSP_MASK) >> + SOF_BT_OFFLOAD_SSP_SHIFT; + + links[id].id = id; + links[id].cpus = &cpus[id]; + links[id].cpus->dai_name = devm_kasprintf(dev, GFP_KERNEL, + "SSP%d Pin", port); + if (!links[id].cpus->dai_name) + goto devm_err; + links[id].name = devm_kasprintf(dev, GFP_KERNEL, "SSP%d-BT", port); + if (!links[id].name) + goto devm_err; + links[id].codecs = dummy_component; + links[id].num_codecs = ARRAY_SIZE(dummy_component); + links[id].platforms = platform_component; + links[id].num_platforms = ARRAY_SIZE(platform_component); + links[id].dpcm_playback = 1; + links[id].dpcm_capture = 1; + links[id].no_pcm = 1; + links[id].num_cpus = 1; + id++; + } + + return links; +devm_err: + return NULL; +} + +static int sof_ssp_amp_probe(struct platform_device *pdev) +{ + struct snd_soc_dai_link *dai_links; + struct snd_soc_acpi_mach *mach; + struct sof_card_private *ctx; + int dmic_be_num, hdmi_num = 0; + int ret, ssp_codec; + + ctx = devm_kzalloc(&pdev->dev, sizeof(*ctx), GFP_KERNEL); + if (!ctx) + return -ENOMEM; + + if (pdev->id_entry && pdev->id_entry->driver_data) + sof_ssp_amp_quirk = (unsigned long)pdev->id_entry->driver_data; + + mach = pdev->dev.platform_data; + + dmic_be_num = mach->mach_params.dmic_num; + + ssp_codec = sof_ssp_amp_quirk & SOF_AMPLIFIER_SSP_MASK; + + /* set number of dai links */ + sof_ssp_amp_card.num_links = 1 + dmic_be_num; + + if (sof_ssp_amp_quirk & SOF_SSP_HDMI_CAPTURE_PRESENT) + sof_ssp_amp_card.num_links += (sof_ssp_amp_quirk & SOF_NO_OF_HDMI_CAPTURE_SSP_MASK) >> + SOF_NO_OF_HDMI_CAPTURE_SSP_SHIFT; + + if (sof_ssp_amp_quirk & SOF_HDMI_PLAYBACK_PRESENT) { + hdmi_num = (sof_ssp_amp_quirk & SOF_NO_OF_HDMI_PLAYBACK_MASK) >> + SOF_NO_OF_HDMI_PLAYBACK_SHIFT; + /* default number of HDMI DAI's */ + if (!hdmi_num) + hdmi_num = 3; + + if (mach->mach_params.codec_mask & IDISP_CODEC_MASK) + ctx->idisp_codec = true; + + sof_ssp_amp_card.num_links += hdmi_num; + } + + if (sof_ssp_amp_quirk & SOF_SSP_BT_OFFLOAD_PRESENT) + sof_ssp_amp_card.num_links++; + + dai_links = sof_card_dai_links_create(&pdev->dev, ssp_codec, dmic_be_num, hdmi_num, ctx->idisp_codec); + if (!dai_links) + return -ENOMEM; + + sof_ssp_amp_card.dai_link = dai_links; + + /* update codec_conf */ + if (sof_ssp_amp_quirk & SOF_CS35L41_SPEAKER_AMP_PRESENT) { + cs35l41_set_codec_conf(&sof_ssp_amp_card); + } + + INIT_LIST_HEAD(&ctx->hdmi_pcm_list); + + sof_ssp_amp_card.dev = &pdev->dev; + + /* set platform name for each dailink */ + ret = snd_soc_fixup_dai_links_platform_name(&sof_ssp_amp_card, + mach->mach_params.platform); + if (ret) + return ret; + + ctx->common_hdmi_codec_drv = mach->mach_params.common_hdmi_codec_drv; + + snd_soc_card_set_drvdata(&sof_ssp_amp_card, ctx); + + return devm_snd_soc_register_card(&pdev->dev, &sof_ssp_amp_card); +} + +static const struct platform_device_id board_ids[] = { + { + .name = "sof_ssp_amp", + }, + { + .name = "tgl_rt1308_hdmi_ssp", + .driver_data = (kernel_ulong_t)(SOF_AMPLIFIER_SSP(2) | + SOF_NO_OF_HDMI_CAPTURE_SSP(2) | + SOF_HDMI_CAPTURE_1_SSP(1) | + SOF_HDMI_CAPTURE_2_SSP(5) | + SOF_SSP_HDMI_CAPTURE_PRESENT | + SOF_RT1308_SPEAKER_AMP_PRESENT), + }, + { + .name = "adl_cs35l41", + .driver_data = (kernel_ulong_t)(SOF_AMPLIFIER_SSP(1) | + SOF_NO_OF_HDMI_PLAYBACK(4) | + SOF_HDMI_PLAYBACK_PRESENT | + SOF_BT_OFFLOAD_SSP(2) | + SOF_SSP_BT_OFFLOAD_PRESENT | + SOF_CS35L41_SPEAKER_AMP_PRESENT), + }, + { } +}; +MODULE_DEVICE_TABLE(platform, board_ids); + +static struct platform_driver sof_ssp_amp_driver = { + .probe = sof_ssp_amp_probe, + .driver = { + .name = "sof_ssp_amp", + .pm = &snd_soc_pm_ops, + }, + .id_table = board_ids, +}; +module_platform_driver(sof_ssp_amp_driver); + +MODULE_DESCRIPTION("ASoC Intel(R) SOF Amplifier Machine driver"); +MODULE_AUTHOR("balamurugan.c <balamurugan.c@intel.com>"); +MODULE_AUTHOR("Brent Lu <brent.lu@intel.com>"); +MODULE_LICENSE("GPL"); +MODULE_IMPORT_NS(SND_SOC_INTEL_HDA_DSP_COMMON); +MODULE_IMPORT_NS(SND_SOC_INTEL_SOF_REALTEK_COMMON); +MODULE_IMPORT_NS(SND_SOC_INTEL_SOF_CIRRUS_COMMON); |