diff options
author | Takashi Iwai <tiwai@suse.de> | 2020-03-30 13:43:00 +0200 |
---|---|---|
committer | Takashi Iwai <tiwai@suse.de> | 2020-03-30 13:43:00 +0200 |
commit | 3c22baeab40b2f8e75907cfd7aa69147d5343d2c (patch) | |
tree | e8300e52242ae3a9c7bfe6089ee7125324095e27 /sound/soc/intel/boards | |
parent | Merge branch 'for-next' into for-linus (diff) | |
parent | Merge branch 'asoc-5.7' into asoc-next (diff) | |
download | linux-3c22baeab40b2f8e75907cfd7aa69147d5343d2c.tar.xz linux-3c22baeab40b2f8e75907cfd7aa69147d5343d2c.zip |
Merge tag 'asoc-v5.7' of https://git.kernel.org/pub/scm/linux/kernel/git/broonie/sound into for-linus
ASoC: Updates for v5.7
This is a very big update for the core since Morimoto-san has been
rather busy continuing his refactorings to clean up a lot of the cruft
that we have accumilated over the years. We've also gained several new
drivers, including initial (but still not complete) parts of the Intel
SoundWire support.
- Lots of refactorings to modernize the code from Morimoto-san.
- Conversion of SND_SOC_ALL_CODECS to use imply from Geert Uytterhoeven.
- Continued refactoring and fixing of the Intel support.
- Soundwire and more advanced clocking support for Realtek RT5682.
- Support for amlogic GX, Meson 8, Meson 8B and T9015 DAC, Broadcom
DSL/PON, Ingenic JZ4760 and JZ4770, Realtek RL6231, and TI TAS2563 and
TLV320ADCX140.
Diffstat (limited to 'sound/soc/intel/boards')
46 files changed, 2794 insertions, 171 deletions
diff --git a/sound/soc/intel/boards/Kconfig b/sound/soc/intel/boards/Kconfig index 9ca2567d0059..556c3104e641 100644 --- a/sound/soc/intel/boards/Kconfig +++ b/sound/soc/intel/boards/Kconfig @@ -289,7 +289,6 @@ config SND_SOC_INTEL_DA7219_MAX98357A_GENERIC select SND_SOC_DA7219 select SND_SOC_MAX98357A select SND_SOC_DMIC - select SND_HDA_CODEC_HDMI if SND_SOC_SOF_HDA_AUDIO_CODEC select SND_SOC_HDAC_HDMI config SND_SOC_INTEL_BXT_DA7219_MAX98357A_COMMON @@ -302,6 +301,7 @@ config SND_SOC_INTEL_BXT_DA7219_MAX98357A_MACH tristate "Broxton with DA7219 and MAX98357A in I2S Mode" 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 help This adds support for ASoC machine driver for Broxton-P platforms @@ -402,6 +402,7 @@ config SND_SOC_INTEL_GLK_DA7219_MAX98357A_MACH tristate "GLK with DA7219 and MAX98357A in I2S Mode" 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 help This adds support for ASoC machine driver for Geminilake platforms @@ -413,10 +414,10 @@ config SND_SOC_INTEL_GLK_RT5682_MAX98357A_MACH tristate "GLK with RT5682 and MAX98357A in I2S Mode" depends on I2C && ACPI depends on MFD_INTEL_LPSS || COMPILE_TEST + depends on SND_HDA_CODEC_HDMI select SND_SOC_RT5682 select SND_SOC_MAX98357A select SND_SOC_DMIC - select SND_HDA_CODEC_HDMI if SND_SOC_SOF_HDA_AUDIO_CODEC select SND_SOC_HDAC_HDMI help This adds support for ASoC machine driver for Geminilake platforms @@ -430,7 +431,7 @@ if SND_SOC_INTEL_SKYLAKE_HDAUDIO_CODEC || SND_SOC_SOF_HDA_AUDIO_CODEC config SND_SOC_INTEL_SKL_HDA_DSP_GENERIC_MACH tristate "SKL/KBL/BXT/APL with HDA Codecs" - select SND_HDA_CODEC_HDMI if SND_SOC_SOF_HDA_AUDIO_CODEC + depends on SND_HDA_CODEC_HDMI select SND_SOC_HDAC_HDMI select SND_SOC_DMIC # SND_SOC_HDAC_HDA is already selected @@ -448,15 +449,31 @@ config SND_SOC_INTEL_SOF_RT5682_MACH depends on I2C && ACPI depends on (SND_SOC_SOF_HDA_LINK && (MFD_INTEL_LPSS || COMPILE_TEST)) ||\ (SND_SOC_SOF_BAYTRAIL && (X86_INTEL_LPSS || COMPILE_TEST)) + depends on SND_HDA_CODEC_HDMI + select SND_SOC_MAX98373 + select SND_SOC_RT1015 select SND_SOC_RT5682 select SND_SOC_DMIC - select SND_HDA_CODEC_HDMI if SND_SOC_SOF_HDA_AUDIO_CODEC select SND_SOC_HDAC_HDMI help This adds support for ASoC machine driver for SOF platforms with rt5682 codec. Say Y if you have such a device. If unsure select "N". + +config SND_SOC_INTEL_SOF_PCM512x_MACH + tristate "SOF with TI PCM512x codec" + depends on I2C && ACPI + depends on (SND_SOC_SOF_HDA_AUDIO_CODEC && (MFD_INTEL_LPSS || COMPILE_TEST)) ||\ + (SND_SOC_SOF_BAYTRAIL && (X86_INTEL_LPSS || COMPILE_TEST)) + depends on SND_HDA_CODEC_HDMI + select SND_SOC_PCM512x_I2C + help + This adds support for ASoC machine driver for SOF platforms + with TI PCM512x I2S audio codec. + Say Y or m if you have such a device. + If unsure select "N". + endif ## SND_SOC_SOF_HDA_LINK || SND_SOC_SOF_BAYTRAIL if (SND_SOC_SOF_COMETLAKE_LP && SND_SOC_SOF_HDA_LINK) @@ -476,11 +493,11 @@ config SND_SOC_INTEL_SOF_CML_RT1011_RT5682_MACH tristate "CML with RT1011 and RT5682 in I2S Mode" depends on I2C && ACPI depends on MFD_INTEL_LPSS || COMPILE_TEST + depends on SND_HDA_CODEC_HDMI select SND_SOC_RT1011 select SND_SOC_RT5682 select SND_SOC_DMIC select SND_SOC_HDAC_HDMI - select SND_HDA_CODEC_HDMI if SND_SOC_SOF_HDA_AUDIO_CODEC help This adds support for ASoC machine driver for SOF platform with RT1011 + RT5682 I2S codec. @@ -492,19 +509,43 @@ endif ## SND_SOC_SOF_COMETLAKE_LP && SND_SOC_SOF_HDA_LINK if SND_SOC_SOF_JASPERLAKE config SND_SOC_INTEL_SOF_DA7219_MAX98373_MACH - tristate "SOF with DA7219 and MAX98373 in I2S Mode" + tristate "SOF with DA7219 and MAX98373/MAX98360A in I2S Mode" depends on I2C && ACPI depends on MFD_INTEL_LPSS || COMPILE_TEST + depends on SND_HDA_CODEC_HDMI select SND_SOC_DA7219 select SND_SOC_MAX98373 select SND_SOC_DMIC - select SND_HDA_CODEC_HDMI if SND_SOC_SOF_HDA_AUDIO_CODEC help This adds support for ASoC machine driver for SOF platforms - with DA7219 + MAX98373 I2S audio codec. + with DA7219 + MAX98373/MAX98360A I2S audio codec. Say Y if you have such a device. If unsure select "N". endif ## SND_SOC_SOF_JASPERLAKE +if SND_SOC_SOF_INTEL_SOUNDWIRE + +config SND_SOC_INTEL_SOUNDWIRE_SOF_MACH + tristate "SoundWire generic machine driver" + 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 + depends on SND_HDA_CODEC_HDMI + select SND_SOC_RT700_SDW + select SND_SOC_RT711_SDW + select SND_SOC_RT1308_SDW + select SND_SOC_RT1308 + select SND_SOC_RT715_SDW + select SND_SOC_RT5682_SDW + select SND_SOC_DMIC + help + Add support for Intel SoundWire-based platforms connected to + RT700, RT711, RT1308 and RT715 + If unsure select "N". + +endif + + endif ## SND_SOC_INTEL_MACH diff --git a/sound/soc/intel/boards/Makefile b/sound/soc/intel/boards/Makefile index b74ddd49bd39..1ef6e60bc2a0 100644 --- a/sound/soc/intel/boards/Makefile +++ b/sound/soc/intel/boards/Makefile @@ -7,6 +7,7 @@ snd-soc-sst-bdw-rt5677-mach-objs := bdw-rt5677.o snd-soc-sst-broadwell-objs := broadwell.o snd-soc-sst-bxt-da7219_max98357a-objs := bxt_da7219_max98357a.o hda_dsp_common.o snd-soc-sst-bxt-rt298-objs := bxt_rt298.o hda_dsp_common.o +snd-soc-sst-sof-pcm512x-objs := sof_pcm512x.o hda_dsp_common.o snd-soc-sst-glk-rt5682_max98357a-objs := glk_rt5682_max98357a.o hda_dsp_common.o snd-soc-sst-bytcr-rt5640-objs := bytcr_rt5640.o snd-soc-sst-bytcr-rt5651-objs := bytcr_rt5651.o @@ -18,7 +19,7 @@ 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 hda_dsp_common.o +snd-soc-sof_rt5682-objs := sof_rt5682.o hda_dsp_common.o sof_maxim_common.o snd-soc-cml_rt1011_rt5682-objs := cml_rt1011_rt5682.o hda_dsp_common.o snd-soc-kbl_da7219_max98357a-objs := kbl_da7219_max98357a.o snd-soc-kbl_da7219_max98927-objs := kbl_da7219_max98927.o @@ -30,13 +31,18 @@ snd-soc-skl_hda_dsp-objs := skl_hda_dsp_generic.o skl_hda_dsp_common.o hda_dsp_c 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 hda_dsp_common.o - +snd-soc-sof-sdw-objs += sof_sdw.o \ + sof_sdw_rt711.o sof_sdw_rt700.o \ + sof_sdw_rt1308.o sof_sdw_rt715.o \ + sof_sdw_rt5682.o \ + sof_sdw_dmic.o sof_sdw_hdmi.o hda_dsp_common.o obj-$(CONFIG_SND_SOC_INTEL_SOF_RT5682_MACH) += snd-soc-sof_rt5682.o obj-$(CONFIG_SND_SOC_INTEL_HASWELL_MACH) += snd-soc-sst-haswell.o obj-$(CONFIG_SND_SOC_INTEL_BYT_RT5640_MACH) += snd-soc-sst-byt-rt5640-mach.o obj-$(CONFIG_SND_SOC_INTEL_BYT_MAX98090_MACH) += snd-soc-sst-byt-max98090-mach.o obj-$(CONFIG_SND_SOC_INTEL_BXT_DA7219_MAX98357A_COMMON) += snd-soc-sst-bxt-da7219_max98357a.o obj-$(CONFIG_SND_SOC_INTEL_BXT_RT298_MACH) += snd-soc-sst-bxt-rt298.o +obj-$(CONFIG_SND_SOC_INTEL_SOF_PCM512x_MACH) += snd-soc-sst-sof-pcm512x.o obj-$(CONFIG_SND_SOC_INTEL_GLK_RT5682_MAX98357A_MACH) += snd-soc-sst-glk-rt5682_max98357a.o obj-$(CONFIG_SND_SOC_INTEL_BROADWELL_MACH) += snd-soc-sst-broadwell.o obj-$(CONFIG_SND_SOC_INTEL_BDW_RT5650_MACH) += snd-soc-sst-bdw-rt5650-mach.o @@ -62,4 +68,4 @@ obj-$(CONFIG_SND_SOC_INTEL_SKL_NAU88L25_MAX98357A_MACH) += snd-skl_nau88l25_max9 obj-$(CONFIG_SND_SOC_INTEL_SKL_NAU88L25_SSM4567_MACH) += snd-soc-skl_nau88l25_ssm4567.o 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_SOUNDWIRE_SOF_MACH) += snd-soc-sof-sdw.o diff --git a/sound/soc/intel/boards/bdw-rt5650.c b/sound/soc/intel/boards/bdw-rt5650.c index 1a302436d450..6c2fdb5659ed 100644 --- a/sound/soc/intel/boards/bdw-rt5650.c +++ b/sound/soc/intel/boards/bdw-rt5650.c @@ -107,7 +107,7 @@ static int bdw_rt5650_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params) { struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct snd_soc_dai *codec_dai = rtd->codec_dai; + struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0); int ret; /* Workaround: set codec PLL to 19.2MHz that PLL source is @@ -166,8 +166,8 @@ static int bdw_rt5650_init(struct snd_soc_pcm_runtime *rtd) { struct bdw_rt5650_priv *bdw_rt5650 = snd_soc_card_get_drvdata(rtd->card); - struct snd_soc_component *component = rtd->codec_dai->component; - struct snd_soc_dai *codec_dai = rtd->codec_dai; + struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0); + struct snd_soc_component *component = codec_dai->component; int ret; /* Enable codec ASRC function for Stereo DAC/Stereo1 ADC/DMIC/I2S1. @@ -226,9 +226,6 @@ SND_SOC_DAILINK_DEF(be, #if IS_ENABLED(CONFIG_SND_SOC_SOF_BROADWELL) SND_SOC_DAILINK_DEF(ssp0_port, DAILINK_COMP_ARRAY(COMP_CPU("ssp0-port"))); -#else -SND_SOC_DAILINK_DEF(ssp0_port, - DAILINK_COMP_ARRAY(COMP_DUMMY())); #endif static struct snd_soc_dai_link bdw_rt5650_dais[] = { @@ -264,7 +261,11 @@ static struct snd_soc_dai_link bdw_rt5650_dais[] = { .dpcm_playback = 1, .dpcm_capture = 1, .init = bdw_rt5650_init, +#if !IS_ENABLED(CONFIG_SND_SOC_SOF_BROADWELL) + SND_SOC_DAILINK_REG(dummy, be, dummy), +#else SND_SOC_DAILINK_REG(ssp0_port, be, platform), +#endif }, }; @@ -298,7 +299,7 @@ static int bdw_rt5650_probe(struct platform_device *pdev) return -ENOMEM; /* override plaform name, if required */ - mach = (&pdev->dev)->platform_data; + 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 bb643c99069d..6b4b64098d36 100644 --- a/sound/soc/intel/boards/bdw-rt5677.c +++ b/sound/soc/intel/boards/bdw-rt5677.c @@ -157,7 +157,7 @@ static int bdw_rt5677_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params) { struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct snd_soc_dai *codec_dai = rtd->codec_dai; + struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0); int ret; ret = snd_soc_dai_set_sysclk(codec_dai, RT5677_SCLK_S_MCLK, 24576000, @@ -174,7 +174,7 @@ static int bdw_rt5677_dsp_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params) { struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct snd_soc_dai *codec_dai = rtd->codec_dai; + struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0); int ret; ret = snd_soc_dai_set_sysclk(codec_dai, RT5677_SCLK_S_PLL1, 24576000, @@ -226,7 +226,7 @@ static int bdw_rt5677_init(struct snd_soc_pcm_runtime *rtd) { struct bdw_rt5677_priv *bdw_rt5677 = snd_soc_card_get_drvdata(rtd->card); - struct snd_soc_component *component = rtd->codec_dai->component; + struct snd_soc_component *component = asoc_rtd_to_codec(rtd, 0)->component; struct snd_soc_dapm_context *dapm = snd_soc_component_get_dapm(component); int ret; @@ -298,9 +298,6 @@ SND_SOC_DAILINK_DEF(be, #if IS_ENABLED(CONFIG_SND_SOC_SOF_BROADWELL) SND_SOC_DAILINK_DEF(ssp0_port, DAILINK_COMP_ARRAY(COMP_CPU("ssp0-port"))); -#else -SND_SOC_DAILINK_DEF(ssp0_port, - DAILINK_COMP_ARRAY(COMP_DUMMY())); #endif /* Wake on voice interface */ @@ -350,7 +347,11 @@ static struct snd_soc_dai_link bdw_rt5677_dais[] = { .dpcm_playback = 1, .dpcm_capture = 1, .init = bdw_rt5677_init, +#if !IS_ENABLED(CONFIG_SND_SOC_SOF_BROADWELL) + SND_SOC_DAILINK_REG(dummy, be, dummy), +#else SND_SOC_DAILINK_REG(ssp0_port, be, platform), +#endif }, }; @@ -412,7 +413,7 @@ static int bdw_rt5677_probe(struct platform_device *pdev) } /* override plaform name, if required */ - mach = (&pdev->dev)->platform_data; + mach = pdev->dev.platform_data; ret = snd_soc_fixup_dai_links_platform_name(&bdw_rt5677_card, mach->mach_params.platform); if (ret) diff --git a/sound/soc/intel/boards/broadwell.c b/sound/soc/intel/boards/broadwell.c index b9c12e24c70b..acb4e36682cb 100644 --- a/sound/soc/intel/boards/broadwell.c +++ b/sound/soc/intel/boards/broadwell.c @@ -70,7 +70,7 @@ static const struct snd_soc_dapm_route broadwell_rt286_map[] = { static int broadwell_rt286_codec_init(struct snd_soc_pcm_runtime *rtd) { - struct snd_soc_component *component = rtd->codec_dai->component; + struct snd_soc_component *component = asoc_rtd_to_codec(rtd, 0)->component; int ret = 0; ret = snd_soc_card_jack_new(rtd->card, "Headset", SND_JACK_HEADSET | SND_JACK_BTN_0, &broadwell_headset, @@ -104,7 +104,7 @@ static int broadwell_rt286_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params) { struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct snd_soc_dai *codec_dai = rtd->codec_dai; + struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0); int ret; ret = snd_soc_dai_set_sysclk(codec_dai, RT286_SCLK_S_PLL, 24000000, @@ -167,9 +167,6 @@ SND_SOC_DAILINK_DEF(codec, #if IS_ENABLED(CONFIG_SND_SOC_SOF_BROADWELL) SND_SOC_DAILINK_DEF(ssp0_port, DAILINK_COMP_ARRAY(COMP_CPU("ssp0-port"))); -#else -SND_SOC_DAILINK_DEF(ssp0_port, - DAILINK_COMP_ARRAY(COMP_DUMMY())); #endif /* broadwell digital audio interface glue - connects codec <--> CPU */ @@ -226,7 +223,11 @@ static struct snd_soc_dai_link broadwell_rt286_dais[] = { .ops = &broadwell_rt286_ops, .dpcm_playback = 1, .dpcm_capture = 1, +#if !IS_ENABLED(CONFIG_SND_SOC_SOF_BROADWELL) + SND_SOC_DAILINK_REG(dummy, codec, dummy), +#else SND_SOC_DAILINK_REG(ssp0_port, codec, platform), +#endif }, }; @@ -283,7 +284,7 @@ static int broadwell_audio_probe(struct platform_device *pdev) broadwell_rt286.dev = &pdev->dev; /* override plaform name, if required */ - mach = (&pdev->dev)->platform_data; + mach = pdev->dev.platform_data; ret = snd_soc_fixup_dai_links_platform_name(&broadwell_rt286, mach->mach_params.platform); if (ret) diff --git a/sound/soc/intel/boards/bxt_da7219_max98357a.c b/sound/soc/intel/boards/bxt_da7219_max98357a.c index 9177401c37a5..44016c16f25e 100644 --- a/sound/soc/intel/boards/bxt_da7219_max98357a.c +++ b/sound/soc/intel/boards/bxt_da7219_max98357a.c @@ -179,8 +179,8 @@ static int broxton_ssp_fixup(struct snd_soc_pcm_runtime *rtd, static int broxton_da7219_codec_init(struct snd_soc_pcm_runtime *rtd) { int ret; - struct snd_soc_dai *codec_dai = rtd->codec_dai; - struct snd_soc_component *component = rtd->codec_dai->component; + struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0); + struct snd_soc_component *component = asoc_rtd_to_codec(rtd, 0)->component; int clk_freq; /* Configure sysclk for codec */ @@ -226,7 +226,7 @@ static int broxton_da7219_codec_init(struct snd_soc_pcm_runtime *rtd) static int broxton_hdmi_init(struct snd_soc_pcm_runtime *rtd) { struct bxt_card_private *ctx = snd_soc_card_get_drvdata(rtd->card); - struct snd_soc_dai *dai = rtd->codec_dai; + struct snd_soc_dai *dai = asoc_rtd_to_codec(rtd, 0); struct bxt_hdmi_pcm *pcm; pcm = devm_kzalloc(rtd->card->dev, sizeof(*pcm), GFP_KERNEL); @@ -244,7 +244,7 @@ static int broxton_hdmi_init(struct snd_soc_pcm_runtime *rtd) static int broxton_da7219_fe_init(struct snd_soc_pcm_runtime *rtd) { struct snd_soc_dapm_context *dapm; - struct snd_soc_component *component = rtd->cpu_dai->component; + struct snd_soc_component *component = asoc_rtd_to_cpu(rtd, 0)->component; dapm = snd_soc_component_get_dapm(component); snd_soc_dapm_ignore_suspend(dapm, "Reference Capture"); @@ -721,7 +721,7 @@ static int broxton_audio_probe(struct platform_device *pdev) } /* override plaform name, if required */ - mach = (&pdev->dev)->platform_data; + mach = pdev->dev.platform_data; platform_name = mach->mach_params.platform; ret = snd_soc_fixup_dai_links_platform_name(&broxton_audio_card, diff --git a/sound/soc/intel/boards/bxt_rt298.c b/sound/soc/intel/boards/bxt_rt298.c index 4b67f261377c..7a4decf34191 100644 --- a/sound/soc/intel/boards/bxt_rt298.c +++ b/sound/soc/intel/boards/bxt_rt298.c @@ -155,7 +155,7 @@ static const struct snd_soc_dapm_route geminilake_rt298_map[] = { static int broxton_rt298_fe_init(struct snd_soc_pcm_runtime *rtd) { struct snd_soc_dapm_context *dapm; - struct snd_soc_component *component = rtd->cpu_dai->component; + struct snd_soc_component *component = asoc_rtd_to_cpu(rtd, 0)->component; dapm = snd_soc_component_get_dapm(component); snd_soc_dapm_ignore_suspend(dapm, "Reference Capture"); @@ -165,7 +165,7 @@ static int broxton_rt298_fe_init(struct snd_soc_pcm_runtime *rtd) static int broxton_rt298_codec_init(struct snd_soc_pcm_runtime *rtd) { - struct snd_soc_component *component = rtd->codec_dai->component; + struct snd_soc_component *component = asoc_rtd_to_codec(rtd, 0)->component; int ret = 0; ret = snd_soc_card_jack_new(rtd->card, "Headset", @@ -186,7 +186,7 @@ static int broxton_rt298_codec_init(struct snd_soc_pcm_runtime *rtd) static int broxton_hdmi_init(struct snd_soc_pcm_runtime *rtd) { struct bxt_rt286_private *ctx = snd_soc_card_get_drvdata(rtd->card); - struct snd_soc_dai *dai = rtd->codec_dai; + struct snd_soc_dai *dai = asoc_rtd_to_codec(rtd, 0); struct bxt_hdmi_pcm *pcm; pcm = devm_kzalloc(rtd->card->dev, sizeof(*pcm), GFP_KERNEL); @@ -225,7 +225,7 @@ static int broxton_rt298_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params) { struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct snd_soc_dai *codec_dai = rtd->codec_dai; + struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0); int ret; ret = snd_soc_dai_set_sysclk(codec_dai, RT298_SCLK_S_PLL, @@ -627,7 +627,7 @@ static int broxton_audio_probe(struct platform_device *pdev) snd_soc_card_set_drvdata(card, ctx); /* override plaform name, if required */ - mach = (&pdev->dev)->platform_data; + mach = pdev->dev.platform_data; platform_name = mach->mach_params.platform; ret = snd_soc_fixup_dai_links_platform_name(card, diff --git a/sound/soc/intel/boards/byt-max98090.c b/sound/soc/intel/boards/byt-max98090.c index 01739ad75b12..f5097da28828 100644 --- a/sound/soc/intel/boards/byt-max98090.c +++ b/sound/soc/intel/boards/byt-max98090.c @@ -89,7 +89,7 @@ static int byt_max98090_init(struct snd_soc_pcm_runtime *runtime) card->dapm.idle_bias_off = true; - ret = snd_soc_dai_set_sysclk(runtime->codec_dai, + ret = snd_soc_dai_set_sysclk(asoc_rtd_to_codec(runtime, 0), M98090_REG_SYSTEM_CLOCK, 25000000, SND_SOC_CLOCK_IN); if (ret < 0) { diff --git a/sound/soc/intel/boards/byt-rt5640.c b/sound/soc/intel/boards/byt-rt5640.c index 0c76dafdd572..ace232f8aed6 100644 --- a/sound/soc/intel/boards/byt-rt5640.c +++ b/sound/soc/intel/boards/byt-rt5640.c @@ -73,7 +73,7 @@ static int byt_rt5640_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params) { struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct snd_soc_dai *codec_dai = rtd->codec_dai; + struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0); int ret; ret = snd_soc_dai_set_sysclk(codec_dai, RT5640_SCLK_S_PLL1, @@ -123,7 +123,7 @@ static const struct dmi_system_id byt_rt5640_quirk_table[] = { static int byt_rt5640_init(struct snd_soc_pcm_runtime *runtime) { int ret; - struct snd_soc_component *component = runtime->codec_dai->component; + struct snd_soc_component *component = asoc_rtd_to_codec(runtime, 0)->component; struct snd_soc_card *card = runtime->card; const struct snd_soc_dapm_route *custom_map; int num_routes; diff --git a/sound/soc/intel/boards/bytcht_cx2072x.c b/sound/soc/intel/boards/bytcht_cx2072x.c index 67f06c95eec5..3b3df7c9008c 100644 --- a/sound/soc/intel/boards/bytcht_cx2072x.c +++ b/sound/soc/intel/boards/bytcht_cx2072x.c @@ -70,7 +70,7 @@ static const struct acpi_gpio_mapping byt_cht_cx2072x_acpi_gpios[] = { static int byt_cht_cx2072x_init(struct snd_soc_pcm_runtime *rtd) { struct snd_soc_card *card = rtd->card; - struct snd_soc_component *codec = rtd->codec_dai->component; + struct snd_soc_component *codec = asoc_rtd_to_codec(rtd, 0)->component; int ret; if (devm_acpi_dev_add_driver_gpios(codec->dev, @@ -80,7 +80,7 @@ static int byt_cht_cx2072x_init(struct snd_soc_pcm_runtime *rtd) card->dapm.idle_bias_off = true; /* set the default PLL rate, the clock is handled by the codec driver */ - ret = snd_soc_dai_set_sysclk(rtd->codec_dai, CX2072X_MCLK_EXTERNAL_PLL, + ret = snd_soc_dai_set_sysclk(asoc_rtd_to_codec(rtd, 0), CX2072X_MCLK_EXTERNAL_PLL, 19200000, SND_SOC_CLOCK_IN); if (ret) { dev_err(rtd->dev, "Could not set sysclk\n"); @@ -97,7 +97,7 @@ static int byt_cht_cx2072x_init(struct snd_soc_pcm_runtime *rtd) snd_soc_component_set_jack(codec, &byt_cht_cx2072x_headset, NULL); - snd_soc_dai_set_bclk_ratio(rtd->codec_dai, 50); + snd_soc_dai_set_bclk_ratio(asoc_rtd_to_codec(rtd, 0), 50); return ret; } @@ -123,7 +123,7 @@ static int byt_cht_cx2072x_fixup(struct snd_soc_pcm_runtime *rtd, * with explicit setting to I2S 2ch 24-bit. The word length is set with * dai_set_tdm_slot() since there is no other API exposed */ - ret = snd_soc_dai_set_fmt(rtd->cpu_dai, + ret = snd_soc_dai_set_fmt(asoc_rtd_to_cpu(rtd, 0), SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS); @@ -132,7 +132,7 @@ static int byt_cht_cx2072x_fixup(struct snd_soc_pcm_runtime *rtd, return ret; } - ret = snd_soc_dai_set_tdm_slot(rtd->cpu_dai, 0x3, 0x3, 2, 24); + ret = snd_soc_dai_set_tdm_slot(asoc_rtd_to_cpu(rtd, 0), 0x3, 0x3, 2, 24); if (ret < 0) { dev_err(rtd->dev, "can't set I2S config, err %d\n", ret); return ret; diff --git a/sound/soc/intel/boards/bytcht_da7213.c b/sound/soc/intel/boards/bytcht_da7213.c index eda7a500cad6..5e96e7d02733 100644 --- a/sound/soc/intel/boards/bytcht_da7213.c +++ b/sound/soc/intel/boards/bytcht_da7213.c @@ -78,7 +78,7 @@ static int codec_fixup(struct snd_soc_pcm_runtime *rtd, * with explicit setting to I2S 2ch 24-bit. The word length is set with * dai_set_tdm_slot() since there is no other API exposed */ - ret = snd_soc_dai_set_fmt(rtd->cpu_dai, + ret = snd_soc_dai_set_fmt(asoc_rtd_to_cpu(rtd, 0), SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS); @@ -87,7 +87,7 @@ static int codec_fixup(struct snd_soc_pcm_runtime *rtd, return ret; } - ret = snd_soc_dai_set_tdm_slot(rtd->cpu_dai, 0x3, 0x3, 2, 24); + ret = snd_soc_dai_set_tdm_slot(asoc_rtd_to_cpu(rtd, 0), 0x3, 0x3, 2, 24); if (ret < 0) { dev_err(rtd->dev, "can't set I2S config, err %d\n", ret); return ret; @@ -106,7 +106,7 @@ static int aif1_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params) { struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct snd_soc_dai *codec_dai = rtd->codec_dai; + struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0); int ret; ret = snd_soc_dai_set_sysclk(codec_dai, DA7213_CLKSRC_MCLK, @@ -127,7 +127,7 @@ static int aif1_hw_params(struct snd_pcm_substream *substream, static int aif1_hw_free(struct snd_pcm_substream *substream) { struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct snd_soc_dai *codec_dai = rtd->codec_dai; + struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0); int ret; ret = snd_soc_dai_set_pll(codec_dai, 0, @@ -231,7 +231,7 @@ static int bytcht_da7213_probe(struct platform_device *pdev) int ret_val = 0; int i; - mach = (&pdev->dev)->platform_data; + mach = pdev->dev.platform_data; card = &bytcht_da7213_card; card->dev = &pdev->dev; diff --git a/sound/soc/intel/boards/bytcht_es8316.c b/sound/soc/intel/boards/bytcht_es8316.c index 0adc5a5e134a..ddcd070100ef 100644 --- a/sound/soc/intel/boards/bytcht_es8316.c +++ b/sound/soc/intel/boards/bytcht_es8316.c @@ -157,7 +157,7 @@ static struct snd_soc_jack_pin byt_cht_es8316_jack_pins[] = { static int byt_cht_es8316_init(struct snd_soc_pcm_runtime *runtime) { - struct snd_soc_component *codec = runtime->codec_dai->component; + struct snd_soc_component *codec = asoc_rtd_to_codec(runtime, 0)->component; struct snd_soc_card *card = runtime->card; struct byt_cht_es8316_private *priv = snd_soc_card_get_drvdata(card); const struct snd_soc_dapm_route *custom_map; @@ -212,7 +212,7 @@ static int byt_cht_es8316_init(struct snd_soc_pcm_runtime *runtime) if (ret) dev_err(card->dev, "unable to enable MCLK\n"); - ret = snd_soc_dai_set_sysclk(runtime->codec_dai, 0, 19200000, + ret = snd_soc_dai_set_sysclk(asoc_rtd_to_codec(runtime, 0), 0, 19200000, SND_SOC_CLOCK_IN); if (ret < 0) { dev_err(card->dev, "can't set codec clock %d\n", ret); @@ -262,7 +262,7 @@ static int byt_cht_es8316_codec_fixup(struct snd_soc_pcm_runtime *rtd, * with explicit setting to I2S 2ch 24-bit. The word length is set with * dai_set_tdm_slot() since there is no other API exposed */ - ret = snd_soc_dai_set_fmt(rtd->cpu_dai, + ret = snd_soc_dai_set_fmt(asoc_rtd_to_cpu(rtd, 0), SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS @@ -272,7 +272,7 @@ static int byt_cht_es8316_codec_fixup(struct snd_soc_pcm_runtime *rtd, return ret; } - ret = snd_soc_dai_set_tdm_slot(rtd->cpu_dai, 0x3, 0x3, 2, bits); + ret = snd_soc_dai_set_tdm_slot(asoc_rtd_to_cpu(rtd, 0), 0x3, 0x3, 2, bits); if (ret < 0) { dev_err(rtd->dev, "can't set I2S config, err %d\n", ret); return ret; diff --git a/sound/soc/intel/boards/bytcht_nocodec.c b/sound/soc/intel/boards/bytcht_nocodec.c index 479af808ef43..8c0dab1f4030 100644 --- a/sound/soc/intel/boards/bytcht_nocodec.c +++ b/sound/soc/intel/boards/bytcht_nocodec.c @@ -58,7 +58,7 @@ static int codec_fixup(struct snd_soc_pcm_runtime *rtd, * with explicit setting to I2S 2ch 24-bit. The word length is set with * dai_set_tdm_slot() since there is no other API exposed */ - ret = snd_soc_dai_set_fmt(rtd->cpu_dai, + ret = snd_soc_dai_set_fmt(asoc_rtd_to_cpu(rtd, 0), SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS); @@ -68,7 +68,7 @@ static int codec_fixup(struct snd_soc_pcm_runtime *rtd, return ret; } - ret = snd_soc_dai_set_tdm_slot(rtd->cpu_dai, 0x3, 0x3, 2, 24); + ret = snd_soc_dai_set_tdm_slot(asoc_rtd_to_cpu(rtd, 0), 0x3, 0x3, 2, 24); if (ret < 0) { dev_err(rtd->dev, "can't set I2S config, err %d\n", ret); return ret; diff --git a/sound/soc/intel/boards/bytcr_rt5640.c b/sound/soc/intel/boards/bytcr_rt5640.c index 6bd9ae813be2..33fb8ea4e5cb 100644 --- a/sound/soc/intel/boards/bytcr_rt5640.c +++ b/sound/soc/intel/boards/bytcr_rt5640.c @@ -381,7 +381,7 @@ static int byt_rt5640_aif1_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params) { struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct snd_soc_dai *dai = rtd->codec_dai; + struct snd_soc_dai *dai = asoc_rtd_to_codec(rtd, 0); return byt_rt5640_prepare_and_enable_pll1(dai, params_rate(params)); } @@ -805,7 +805,7 @@ static int byt_rt5640_init(struct snd_soc_pcm_runtime *runtime) { struct snd_soc_card *card = runtime->card; struct byt_rt5640_private *priv = snd_soc_card_get_drvdata(card); - struct snd_soc_component *component = runtime->codec_dai->component; + struct snd_soc_component *component = asoc_rtd_to_codec(runtime, 0)->component; const struct snd_soc_dapm_route *custom_map; int num_routes; int ret; @@ -962,7 +962,7 @@ static int byt_rt5640_codec_fixup(struct snd_soc_pcm_runtime *rtd, * with explicit setting to I2S 2ch. The word length is set with * dai_set_tdm_slot() since there is no other API exposed */ - ret = snd_soc_dai_set_fmt(rtd->cpu_dai, + ret = snd_soc_dai_set_fmt(asoc_rtd_to_cpu(rtd, 0), SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS); @@ -971,7 +971,7 @@ static int byt_rt5640_codec_fixup(struct snd_soc_pcm_runtime *rtd, return ret; } - ret = snd_soc_dai_set_tdm_slot(rtd->cpu_dai, 0x3, 0x3, 2, bits); + ret = snd_soc_dai_set_tdm_slot(asoc_rtd_to_cpu(rtd, 0), 0x3, 0x3, 2, bits); if (ret < 0) { dev_err(rtd->dev, "can't set I2S config, err %d\n", ret); return ret; diff --git a/sound/soc/intel/boards/bytcr_rt5651.c b/sound/soc/intel/boards/bytcr_rt5651.c index 5074bb53f98e..214ef41e23e6 100644 --- a/sound/soc/intel/boards/bytcr_rt5651.c +++ b/sound/soc/intel/boards/bytcr_rt5651.c @@ -348,7 +348,7 @@ static int byt_rt5651_aif1_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params) { struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct snd_soc_dai *codec_dai = rtd->codec_dai; + struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0); snd_pcm_format_t format = params_format(params); int rate = params_rate(params); int bclk_ratio; @@ -540,7 +540,7 @@ static int byt_rt5651_add_codec_device_props(struct device *i2c_dev) static int byt_rt5651_init(struct snd_soc_pcm_runtime *runtime) { struct snd_soc_card *card = runtime->card; - struct snd_soc_component *codec = runtime->codec_dai->component; + struct snd_soc_component *codec = asoc_rtd_to_codec(runtime, 0)->component; struct byt_rt5651_private *priv = snd_soc_card_get_drvdata(card); const struct snd_soc_dapm_route *custom_map; int num_routes; @@ -685,7 +685,7 @@ static int byt_rt5651_codec_fixup(struct snd_soc_pcm_runtime *rtd, * with explicit setting to I2S 2ch. The word length is set with * dai_set_tdm_slot() since there is no other API exposed */ - ret = snd_soc_dai_set_fmt(rtd->cpu_dai, + ret = snd_soc_dai_set_fmt(asoc_rtd_to_cpu(rtd, 0), SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS @@ -696,7 +696,7 @@ static int byt_rt5651_codec_fixup(struct snd_soc_pcm_runtime *rtd, return ret; } - ret = snd_soc_dai_set_tdm_slot(rtd->cpu_dai, 0x3, 0x3, 2, bits); + ret = snd_soc_dai_set_tdm_slot(asoc_rtd_to_cpu(rtd, 0), 0x3, 0x3, 2, bits); if (ret < 0) { dev_err(rtd->dev, "can't set I2S config, err %d\n", ret); return ret; diff --git a/sound/soc/intel/boards/cht_bsw_max98090_ti.c b/sound/soc/intel/boards/cht_bsw_max98090_ti.c index 70bb86f3342f..135701738a44 100644 --- a/sound/soc/intel/boards/cht_bsw_max98090_ti.c +++ b/sound/soc/intel/boards/cht_bsw_max98090_ti.c @@ -113,7 +113,7 @@ static int cht_aif1_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params) { struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct snd_soc_dai *codec_dai = rtd->codec_dai; + struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0); int ret; ret = snd_soc_dai_set_sysclk(codec_dai, M98090_REG_SYSTEM_CLOCK, @@ -257,7 +257,7 @@ static int cht_codec_fixup(struct snd_soc_pcm_runtime *rtd, int ret = 0; unsigned int fmt = 0; - ret = snd_soc_dai_set_tdm_slot(rtd->cpu_dai, 0x3, 0x3, 2, 16); + ret = snd_soc_dai_set_tdm_slot(asoc_rtd_to_cpu(rtd, 0), 0x3, 0x3, 2, 16); if (ret < 0) { dev_err(rtd->dev, "can't set cpu_dai slot fmt: %d\n", ret); return ret; @@ -266,7 +266,7 @@ static int cht_codec_fixup(struct snd_soc_pcm_runtime *rtd, fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS; - ret = snd_soc_dai_set_fmt(rtd->cpu_dai, fmt); + ret = snd_soc_dai_set_fmt(asoc_rtd_to_cpu(rtd, 0), fmt); if (ret < 0) { dev_err(rtd->dev, "can't set cpu_dai set fmt: %d\n", ret); return ret; @@ -553,7 +553,7 @@ static int snd_cht_mc_probe(struct platform_device *pdev) /* override plaform name, if required */ snd_soc_card_cht.dev = &pdev->dev; - mach = (&pdev->dev)->platform_data; + mach = pdev->dev.platform_data; platform_name = mach->mach_params.platform; ret_val = snd_soc_fixup_dai_links_platform_name(&snd_soc_card_cht, diff --git a/sound/soc/intel/boards/cht_bsw_nau8824.c b/sound/soc/intel/boards/cht_bsw_nau8824.c index 501bad3976fb..f456150f89c2 100644 --- a/sound/soc/intel/boards/cht_bsw_nau8824.c +++ b/sound/soc/intel/boards/cht_bsw_nau8824.c @@ -73,7 +73,7 @@ static int cht_aif1_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params) { struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct snd_soc_dai *codec_dai = rtd->codec_dai; + struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0); int ret; ret = snd_soc_dai_set_sysclk(codec_dai, NAU8824_CLK_FLL_FS, 0, @@ -96,7 +96,7 @@ static int cht_codec_init(struct snd_soc_pcm_runtime *runtime) { struct cht_mc_private *ctx = snd_soc_card_get_drvdata(runtime->card); struct snd_soc_jack *jack = &ctx->jack; - struct snd_soc_dai *codec_dai = runtime->codec_dai; + struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(runtime, 0); struct snd_soc_component *component = codec_dai->component; int ret, jack_type; @@ -259,7 +259,7 @@ static int snd_cht_mc_probe(struct platform_device *pdev) /* override plaform name, if required */ snd_soc_card_cht.dev = &pdev->dev; - mach = (&pdev->dev)->platform_data; + mach = pdev->dev.platform_data; platform_name = mach->mach_params.platform; ret_val = snd_soc_fixup_dai_links_platform_name(&snd_soc_card_cht, diff --git a/sound/soc/intel/boards/cht_bsw_rt5645.c b/sound/soc/intel/boards/cht_bsw_rt5645.c index b5b016d493f1..e64eca56e426 100644 --- a/sound/soc/intel/boards/cht_bsw_rt5645.c +++ b/sound/soc/intel/boards/cht_bsw_rt5645.c @@ -208,7 +208,7 @@ static int cht_aif1_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params) { struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct snd_soc_dai *codec_dai = rtd->codec_dai; + struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0); int ret; /* set codec PLL source to the 19.2MHz platform clock (MCLK) */ @@ -252,7 +252,7 @@ static int cht_codec_init(struct snd_soc_pcm_runtime *runtime) { struct snd_soc_card *card = runtime->card; struct cht_mc_private *ctx = snd_soc_card_get_drvdata(runtime->card); - struct snd_soc_component *component = runtime->codec_dai->component; + struct snd_soc_component *component = asoc_rtd_to_codec(runtime, 0)->component; int jack_type; int ret; @@ -359,7 +359,7 @@ static int cht_codec_fixup(struct snd_soc_pcm_runtime *rtd, * with explicit setting to I2S 2ch 16-bit. The word length is set with * dai_set_tdm_slot() since there is no other API exposed */ - ret = snd_soc_dai_set_fmt(rtd->cpu_dai, + ret = snd_soc_dai_set_fmt(asoc_rtd_to_cpu(rtd, 0), SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS @@ -369,7 +369,7 @@ static int cht_codec_fixup(struct snd_soc_pcm_runtime *rtd, return ret; } - ret = snd_soc_dai_set_fmt(rtd->codec_dai, + ret = snd_soc_dai_set_fmt(asoc_rtd_to_codec(rtd, 0), SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS @@ -379,7 +379,7 @@ static int cht_codec_fixup(struct snd_soc_pcm_runtime *rtd, return ret; } - ret = snd_soc_dai_set_tdm_slot(rtd->cpu_dai, 0x3, 0x3, 2, 16); + ret = snd_soc_dai_set_tdm_slot(asoc_rtd_to_cpu(rtd, 0), 0x3, 0x3, 2, 16); if (ret < 0) { dev_err(rtd->dev, "can't set I2S config, err %d\n", ret); return ret; @@ -393,7 +393,7 @@ static int cht_codec_fixup(struct snd_soc_pcm_runtime *rtd, /* * Default mode for SSP configuration is TDM 4 slot */ - ret = snd_soc_dai_set_fmt(rtd->codec_dai, + ret = snd_soc_dai_set_fmt(asoc_rtd_to_codec(rtd, 0), SND_SOC_DAIFMT_DSP_B | SND_SOC_DAIFMT_IB_NF | SND_SOC_DAIFMT_CBS_CFS); @@ -403,7 +403,7 @@ static int cht_codec_fixup(struct snd_soc_pcm_runtime *rtd, } /* TDM 4 slots 24 bit, set Rx & Tx bitmask to 4 active slots */ - ret = snd_soc_dai_set_tdm_slot(rtd->codec_dai, 0xF, 0xF, 4, 24); + ret = snd_soc_dai_set_tdm_slot(asoc_rtd_to_codec(rtd, 0), 0xF, 0xF, 4, 24); if (ret < 0) { dev_err(rtd->dev, "can't set codec TDM slot %d\n", ret); return ret; @@ -539,7 +539,7 @@ static int snd_cht_mc_probe(struct platform_device *pdev) if (!drv) return -ENOMEM; - mach = (&pdev->dev)->platform_data; + mach = pdev->dev.platform_data; for (i = 0; i < ARRAY_SIZE(snd_soc_cards); i++) { if (acpi_dev_found(snd_soc_cards[i].codec_id) && diff --git a/sound/soc/intel/boards/cht_bsw_rt5672.c b/sound/soc/intel/boards/cht_bsw_rt5672.c index 9d657421730a..097023a3ec14 100644 --- a/sound/soc/intel/boards/cht_bsw_rt5672.c +++ b/sound/soc/intel/boards/cht_bsw_rt5672.c @@ -144,7 +144,7 @@ static int cht_aif1_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params) { struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct snd_soc_dai *codec_dai = rtd->codec_dai; + struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0); int ret; /* set codec PLL source to the 19.2MHz platform clock (MCLK) */ @@ -176,7 +176,7 @@ static const struct acpi_gpio_mapping cht_rt5672_gpios[] = { static int cht_codec_init(struct snd_soc_pcm_runtime *runtime) { int ret; - struct snd_soc_dai *codec_dai = runtime->codec_dai; + struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(runtime, 0); struct snd_soc_component *component = codec_dai->component; struct cht_mc_private *ctx = snd_soc_card_get_drvdata(runtime->card); @@ -255,7 +255,7 @@ static int cht_codec_fixup(struct snd_soc_pcm_runtime *rtd, /* * Default mode for SSP configuration is TDM 4 slot */ - ret = snd_soc_dai_set_fmt(rtd->codec_dai, + ret = snd_soc_dai_set_fmt(asoc_rtd_to_codec(rtd, 0), SND_SOC_DAIFMT_DSP_B | SND_SOC_DAIFMT_IB_NF | SND_SOC_DAIFMT_CBS_CFS); @@ -265,7 +265,7 @@ static int cht_codec_fixup(struct snd_soc_pcm_runtime *rtd, } /* TDM 4 slots 24 bit, set Rx & Tx bitmask to 4 active slots */ - ret = snd_soc_dai_set_tdm_slot(rtd->codec_dai, 0xF, 0xF, 4, 24); + ret = snd_soc_dai_set_tdm_slot(asoc_rtd_to_codec(rtd, 0), 0xF, 0xF, 4, 24); if (ret < 0) { dev_err(rtd->dev, "can't set codec TDM slot %d\n", ret); return ret; diff --git a/sound/soc/intel/boards/cml_rt1011_rt5682.c b/sound/soc/intel/boards/cml_rt1011_rt5682.c index dd80d0186a6c..8167b2977e1d 100644 --- a/sound/soc/intel/boards/cml_rt1011_rt5682.c +++ b/sound/soc/intel/boards/cml_rt1011_rt5682.c @@ -85,7 +85,7 @@ static const struct snd_soc_dapm_route cml_rt1011_rt5682_map[] = { static int cml_rt5682_codec_init(struct snd_soc_pcm_runtime *rtd) { struct card_private *ctx = snd_soc_card_get_drvdata(rtd->card); - struct snd_soc_component *component = rtd->codec_dai->component; + struct snd_soc_component *component = asoc_rtd_to_codec(rtd, 0)->component; struct snd_soc_jack *jack; int ret; @@ -125,7 +125,7 @@ static int cml_rt5682_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params) { struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct snd_soc_dai *codec_dai = rtd->codec_dai; + struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0); int clk_id, clk_freq, pll_out, ret; clk_id = RT5682_PLL1_S_MCLK; @@ -164,8 +164,7 @@ static int cml_rt1011_hw_params(struct snd_pcm_substream *substream, srate = params_rate(params); - for (i = 0; i < rtd->num_codecs; i++) { - codec_dai = rtd->codec_dais[i]; + for_each_rtd_codec_dais(rtd, i, codec_dai) { /* 100 Fs to drive 24 bit data */ ret = snd_soc_dai_set_pll(codec_dai, 0, RT1011_PLL1_S_BCLK, @@ -275,7 +274,7 @@ static int sof_card_late_probe(struct snd_soc_card *card) static int hdmi_init(struct snd_soc_pcm_runtime *rtd) { struct card_private *ctx = snd_soc_card_get_drvdata(rtd->card); - struct snd_soc_dai *dai = rtd->codec_dai; + struct snd_soc_dai *dai = asoc_rtd_to_codec(rtd, 0); struct hdmi_pcm *pcm; pcm = devm_kzalloc(rtd->card->dev, sizeof(*pcm), GFP_KERNEL); @@ -447,12 +446,12 @@ static int snd_cml_rt1011_probe(struct platform_device *pdev) const char *platform_name; int ret; - ctx = devm_kzalloc(&pdev->dev, sizeof(*ctx), GFP_ATOMIC); + ctx = devm_kzalloc(&pdev->dev, sizeof(*ctx), GFP_KERNEL); if (!ctx) return -ENOMEM; INIT_LIST_HEAD(&ctx->hdmi_pcm_list); - mach = (&pdev->dev)->platform_data; + mach = pdev->dev.platform_data; snd_soc_card_cml.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 8e947bad143c..f13158e4a1fc 100644 --- a/sound/soc/intel/boards/glk_rt5682_max98357a.c +++ b/sound/soc/intel/boards/glk_rt5682_max98357a.c @@ -136,8 +136,8 @@ static int geminilake_ssp_fixup(struct snd_soc_pcm_runtime *rtd, static int geminilake_rt5682_codec_init(struct snd_soc_pcm_runtime *rtd) { struct glk_card_private *ctx = snd_soc_card_get_drvdata(rtd->card); - struct snd_soc_component *component = rtd->codec_dai->component; - struct snd_soc_dai *codec_dai = rtd->codec_dai; + struct snd_soc_component *component = asoc_rtd_to_codec(rtd, 0)->component; + struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0); struct snd_soc_jack *jack; int ret; @@ -188,7 +188,7 @@ static int geminilake_rt5682_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params) { struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct snd_soc_dai *codec_dai = rtd->codec_dai; + struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0); int ret; /* Set valid bitmask & configuration for I2S in 24 bit */ @@ -208,7 +208,7 @@ static struct snd_soc_ops geminilake_rt5682_ops = { static int geminilake_hdmi_init(struct snd_soc_pcm_runtime *rtd) { struct glk_card_private *ctx = snd_soc_card_get_drvdata(rtd->card); - struct snd_soc_dai *dai = rtd->codec_dai; + struct snd_soc_dai *dai = asoc_rtd_to_codec(rtd, 0); struct glk_hdmi_pcm *pcm; pcm = devm_kzalloc(rtd->card->dev, sizeof(*pcm), GFP_KERNEL); @@ -225,7 +225,7 @@ static int geminilake_hdmi_init(struct snd_soc_pcm_runtime *rtd) static int geminilake_rt5682_fe_init(struct snd_soc_pcm_runtime *rtd) { - struct snd_soc_component *component = rtd->cpu_dai->component; + struct snd_soc_component *component = asoc_rtd_to_cpu(rtd, 0)->component; struct snd_soc_dapm_context *dapm; int ret; @@ -409,6 +409,7 @@ static struct snd_soc_dai_link geminilake_dais[] = { .init = NULL, .capture_only = 1, .nonatomic = 1, + .dynamic = 1, SND_SOC_DAILINK_REG(echoref, dummy, platform), }, [GLK_DPCM_AUDIO_REF_CP] = { @@ -604,7 +605,7 @@ static int geminilake_audio_probe(struct platform_device *pdev) snd_soc_card_set_drvdata(card, ctx); /* override plaform name, if required */ - mach = (&pdev->dev)->platform_data; + mach = pdev->dev.platform_data; platform_name = mach->mach_params.platform; ret = snd_soc_fixup_dai_links_platform_name(card, platform_name); diff --git a/sound/soc/intel/boards/haswell.c b/sound/soc/intel/boards/haswell.c index 3dadf9bff796..3ed53d7db4e6 100644 --- a/sound/soc/intel/boards/haswell.c +++ b/sound/soc/intel/boards/haswell.c @@ -56,7 +56,7 @@ static int haswell_rt5640_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params) { struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct snd_soc_dai *codec_dai = rtd->codec_dai; + struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0); int ret; ret = snd_soc_dai_set_sysclk(codec_dai, RT5640_SCLK_S_MCLK, 12288000, @@ -193,7 +193,7 @@ static int haswell_audio_probe(struct platform_device *pdev) haswell_rt5640.dev = &pdev->dev; /* override plaform name, if required */ - mach = (&pdev->dev)->platform_data; + mach = pdev->dev.platform_data; ret = snd_soc_fixup_dai_links_platform_name(&haswell_rt5640, mach->mach_params.platform); if (ret) diff --git a/sound/soc/intel/boards/kbl_da7219_max98357a.c b/sound/soc/intel/boards/kbl_da7219_max98357a.c index bc7f9a9ce9af..32cd90b8d4c4 100644 --- a/sound/soc/intel/boards/kbl_da7219_max98357a.c +++ b/sound/soc/intel/boards/kbl_da7219_max98357a.c @@ -159,8 +159,8 @@ static int kabylake_ssp_fixup(struct snd_soc_pcm_runtime *rtd, static int kabylake_da7219_codec_init(struct snd_soc_pcm_runtime *rtd) { struct kbl_codec_private *ctx = snd_soc_card_get_drvdata(rtd->card); - struct snd_soc_component *component = rtd->codec_dai->component; - struct snd_soc_dai *codec_dai = rtd->codec_dai; + struct snd_soc_component *component = asoc_rtd_to_codec(rtd, 0)->component; + struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0); struct snd_soc_jack *jack; int ret; @@ -203,7 +203,7 @@ static int kabylake_da7219_codec_init(struct snd_soc_pcm_runtime *rtd) static int kabylake_hdmi_init(struct snd_soc_pcm_runtime *rtd, int device) { struct kbl_codec_private *ctx = snd_soc_card_get_drvdata(rtd->card); - struct snd_soc_dai *dai = rtd->codec_dai; + struct snd_soc_dai *dai = asoc_rtd_to_codec(rtd, 0); struct kbl_hdmi_pcm *pcm; pcm = devm_kzalloc(rtd->card->dev, sizeof(*pcm), GFP_KERNEL); @@ -236,7 +236,7 @@ static int kabylake_hdmi3_init(struct snd_soc_pcm_runtime *rtd) static int kabylake_da7219_fe_init(struct snd_soc_pcm_runtime *rtd) { struct snd_soc_dapm_context *dapm; - struct snd_soc_component *component = rtd->cpu_dai->component; + struct snd_soc_component *component = asoc_rtd_to_cpu(rtd, 0)->component; dapm = snd_soc_component_get_dapm(component); snd_soc_dapm_ignore_suspend(dapm, "Reference Capture"); diff --git a/sound/soc/intel/boards/kbl_da7219_max98927.c b/sound/soc/intel/boards/kbl_da7219_max98927.c index 7a13e9b35187..abd4e3839678 100644 --- a/sound/soc/intel/boards/kbl_da7219_max98927.c +++ b/sound/soc/intel/boards/kbl_da7219_max98927.c @@ -176,10 +176,10 @@ static int kabylake_ssp0_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params) { struct snd_soc_pcm_runtime *runtime = substream->private_data; + struct snd_soc_dai *codec_dai; int ret, j; - for (j = 0; j < runtime->num_codecs; j++) { - struct snd_soc_dai *codec_dai = runtime->codec_dais[j]; + for_each_rtd_codec_dais(runtime, j, codec_dai) { if (!strcmp(codec_dai->component->name, MAX98927_DEV0_NAME)) { ret = snd_soc_dai_set_tdm_slot(codec_dai, 0x30, 3, 8, 16); @@ -221,10 +221,10 @@ static int kabylake_ssp0_hw_params(struct snd_pcm_substream *substream, static int kabylake_ssp0_trigger(struct snd_pcm_substream *substream, int cmd) { struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_dai *codec_dai; int j, ret; - for (j = 0; j < rtd->num_codecs; j++) { - struct snd_soc_dai *codec_dai = rtd->codec_dais[j]; + for_each_rtd_codec_dais(rtd, j, codec_dai) { const char *name = codec_dai->component->name; struct snd_soc_component *component = codec_dai->component; struct snd_soc_dapm_context *dapm = @@ -331,7 +331,7 @@ static int kabylake_ssp_fixup(struct snd_soc_pcm_runtime *rtd, static int kabylake_da7219_codec_init(struct snd_soc_pcm_runtime *rtd) { struct kbl_codec_private *ctx = snd_soc_card_get_drvdata(rtd->card); - struct snd_soc_component *component = rtd->codec_dai->component; + struct snd_soc_component *component = asoc_rtd_to_codec(rtd, 0)->component; struct snd_soc_jack *jack; struct snd_soc_card *card = rtd->card; int ret; @@ -381,7 +381,7 @@ static int kabylake_dmic_init(struct snd_soc_pcm_runtime *rtd) static int kabylake_hdmi_init(struct snd_soc_pcm_runtime *rtd, int device) { struct kbl_codec_private *ctx = snd_soc_card_get_drvdata(rtd->card); - struct snd_soc_dai *dai = rtd->codec_dai; + struct snd_soc_dai *dai = asoc_rtd_to_codec(rtd, 0); struct kbl_hdmi_pcm *pcm; pcm = devm_kzalloc(rtd->card->dev, sizeof(*pcm), GFP_KERNEL); @@ -414,7 +414,7 @@ static int kabylake_hdmi3_init(struct snd_soc_pcm_runtime *rtd) static int kabylake_da7219_fe_init(struct snd_soc_pcm_runtime *rtd) { struct snd_soc_dapm_context *dapm; - struct snd_soc_component *component = rtd->cpu_dai->component; + struct snd_soc_component *component = asoc_rtd_to_cpu(rtd, 0)->component; dapm = snd_soc_component_get_dapm(component); snd_soc_dapm_ignore_suspend(dapm, "Reference Capture"); diff --git a/sound/soc/intel/boards/kbl_rt5660.c b/sound/soc/intel/boards/kbl_rt5660.c index e23dea9ab79a..6460e3f0c974 100644 --- a/sound/soc/intel/boards/kbl_rt5660.c +++ b/sound/soc/intel/boards/kbl_rt5660.c @@ -157,7 +157,7 @@ static int kabylake_rt5660_codec_init(struct snd_soc_pcm_runtime *rtd) { int ret; struct kbl_codec_private *ctx = snd_soc_card_get_drvdata(rtd->card); - struct snd_soc_component *component = rtd->codec_dai->component; + struct snd_soc_component *component = asoc_rtd_to_codec(rtd, 0)->component; struct snd_soc_dapm_context *dapm = snd_soc_component_get_dapm(component); ret = devm_acpi_dev_add_driver_gpios(component->dev, acpi_rt5660_gpios); @@ -210,7 +210,7 @@ static int kabylake_rt5660_codec_init(struct snd_soc_pcm_runtime *rtd) static int kabylake_hdmi_init(struct snd_soc_pcm_runtime *rtd, int device) { struct kbl_codec_private *ctx = snd_soc_card_get_drvdata(rtd->card); - struct snd_soc_dai *dai = rtd->codec_dai; + struct snd_soc_dai *dai = asoc_rtd_to_codec(rtd, 0); struct kbl_hdmi_pcm *pcm; pcm = devm_kzalloc(rtd->card->dev, sizeof(*pcm), GFP_KERNEL); @@ -244,7 +244,7 @@ static int kabylake_rt5660_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params) { struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct snd_soc_dai *codec_dai = rtd->codec_dai; + struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0); int ret; ret = snd_soc_dai_set_sysclk(codec_dai, diff --git a/sound/soc/intel/boards/kbl_rt5663_max98927.c b/sound/soc/intel/boards/kbl_rt5663_max98927.c index d8f2ff7139a9..658a9da3a40f 100644 --- a/sound/soc/intel/boards/kbl_rt5663_max98927.c +++ b/sound/soc/intel/boards/kbl_rt5663_max98927.c @@ -242,7 +242,7 @@ static int kabylake_rt5663_fe_init(struct snd_soc_pcm_runtime *rtd) { int ret; struct snd_soc_dapm_context *dapm; - struct snd_soc_component *component = rtd->cpu_dai->component; + struct snd_soc_component *component = asoc_rtd_to_cpu(rtd, 0)->component; dapm = snd_soc_component_get_dapm(component); ret = snd_soc_dapm_ignore_suspend(dapm, "Reference Capture"); @@ -258,7 +258,7 @@ static int kabylake_rt5663_codec_init(struct snd_soc_pcm_runtime *rtd) { int ret; struct kbl_rt5663_private *ctx = snd_soc_card_get_drvdata(rtd->card); - struct snd_soc_component *component = rtd->codec_dai->component; + struct snd_soc_component *component = asoc_rtd_to_codec(rtd, 0)->component; struct snd_soc_jack *jack; /* @@ -305,7 +305,7 @@ static int kabylake_rt5663_max98927_codec_init(struct snd_soc_pcm_runtime *rtd) static int kabylake_hdmi_init(struct snd_soc_pcm_runtime *rtd, int device) { struct kbl_rt5663_private *ctx = snd_soc_card_get_drvdata(rtd->card); - struct snd_soc_dai *dai = rtd->codec_dai; + struct snd_soc_dai *dai = asoc_rtd_to_codec(rtd, 0); struct kbl_hdmi_pcm *pcm; pcm = devm_kzalloc(rtd->card->dev, sizeof(*pcm), GFP_KERNEL); @@ -431,7 +431,7 @@ static int kabylake_rt5663_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params) { struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct snd_soc_dai *codec_dai = rtd->codec_dai; + struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0); int ret; /* use ASRC for internal clocks, as PLL rate isn't multiple of BCLK */ @@ -472,7 +472,7 @@ static int kabylake_ssp0_hw_params(struct snd_pcm_substream *substream, struct snd_soc_dai *codec_dai; int ret = 0, j; - for_each_rtd_codec_dai(rtd, j, codec_dai) { + for_each_rtd_codec_dais(rtd, j, codec_dai) { if (!strcmp(codec_dai->component->name, MAXIM_DEV0_NAME)) { /* * Use channel 4 and 5 for the first amp @@ -962,7 +962,7 @@ static int kabylake_audio_probe(struct platform_device *pdev) kabylake_audio_card->dev = &pdev->dev; snd_soc_card_set_drvdata(kabylake_audio_card, ctx); - mach = (&pdev->dev)->platform_data; + mach = pdev->dev.platform_data; if (mach) dmic_constraints = mach->mach_params.dmic_num == 2 ? &constraints_dmic_2ch : &constraints_dmic_channels; diff --git a/sound/soc/intel/boards/kbl_rt5663_rt5514_max98927.c b/sound/soc/intel/boards/kbl_rt5663_rt5514_max98927.c index 96c814f36458..1b1f8d7a4ea3 100644 --- a/sound/soc/intel/boards/kbl_rt5663_rt5514_max98927.c +++ b/sound/soc/intel/boards/kbl_rt5663_rt5514_max98927.c @@ -206,7 +206,7 @@ static struct snd_soc_codec_conf max98927_codec_conf[] = { static int kabylake_rt5663_fe_init(struct snd_soc_pcm_runtime *rtd) { struct snd_soc_dapm_context *dapm; - struct snd_soc_component *component = rtd->cpu_dai->component; + struct snd_soc_component *component = asoc_rtd_to_cpu(rtd, 0)->component; int ret; dapm = snd_soc_component_get_dapm(component); @@ -221,7 +221,7 @@ static int kabylake_rt5663_codec_init(struct snd_soc_pcm_runtime *rtd) { int ret; struct kbl_codec_private *ctx = snd_soc_card_get_drvdata(rtd->card); - struct snd_soc_component *component = rtd->codec_dai->component; + struct snd_soc_component *component = asoc_rtd_to_codec(rtd, 0)->component; struct snd_soc_jack *jack; /* @@ -255,7 +255,7 @@ static int kabylake_rt5663_codec_init(struct snd_soc_pcm_runtime *rtd) static int kabylake_hdmi_init(struct snd_soc_pcm_runtime *rtd, int device) { struct kbl_codec_private *ctx = snd_soc_card_get_drvdata(rtd->card); - struct snd_soc_dai *dai = rtd->codec_dai; + struct snd_soc_dai *dai = asoc_rtd_to_codec(rtd, 0); struct kbl_hdmi_pcm *pcm; pcm = devm_kzalloc(rtd->card->dev, sizeof(*pcm), GFP_KERNEL); @@ -372,7 +372,7 @@ static int kabylake_rt5663_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params) { struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct snd_soc_dai *codec_dai = rtd->codec_dai; + struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0); int ret; /* use ASRC for internal clocks, as PLL rate isn't multiple of BCLK */ @@ -399,7 +399,7 @@ static int kabylake_ssp0_hw_params(struct snd_pcm_substream *substream, struct snd_soc_dai *codec_dai; int ret = 0, j; - for_each_rtd_codec_dai(rtd, j, codec_dai) { + for_each_rtd_codec_dais(rtd, j, codec_dai) { if (!strcmp(codec_dai->component->name, RT5514_DEV_NAME)) { ret = snd_soc_dai_set_tdm_slot(codec_dai, 0xF, 0, 8, 16); if (ret < 0) { @@ -772,7 +772,7 @@ static int kabylake_audio_probe(struct platform_device *pdev) kabylake_audio_card.dev = &pdev->dev; snd_soc_card_set_drvdata(&kabylake_audio_card, ctx); - mach = (&pdev->dev)->platform_data; + mach = pdev->dev.platform_data; if (mach) dmic_constraints = mach->mach_params.dmic_num == 2 ? &constraints_dmic_2ch : &constraints_dmic_channels; diff --git a/sound/soc/intel/boards/skl_hda_dsp_common.h b/sound/soc/intel/boards/skl_hda_dsp_common.h index d6150670ca05..e8545d13062f 100644 --- a/sound/soc/intel/boards/skl_hda_dsp_common.h +++ b/sound/soc/intel/boards/skl_hda_dsp_common.h @@ -49,6 +49,10 @@ static inline int skl_hda_hdmi_build_controls(struct snd_soc_card *card) struct snd_soc_component *component; struct skl_hda_hdmi_pcm *pcm; + /* HDMI disabled, do not create controls */ + if (list_empty(&ctx->hdmi_pcm_list)) + return 0; + pcm = list_first_entry(&ctx->hdmi_pcm_list, struct skl_hda_hdmi_pcm, head); component = pcm->codec_dai->component; diff --git a/sound/soc/intel/boards/skl_hda_dsp_generic.c b/sound/soc/intel/boards/skl_hda_dsp_generic.c index 11eaee9ae41f..3be764299ab0 100644 --- a/sound/soc/intel/boards/skl_hda_dsp_generic.c +++ b/sound/soc/intel/boards/skl_hda_dsp_generic.c @@ -61,6 +61,9 @@ static const struct snd_soc_dapm_route skl_hda_map[] = { { "Alt Analog CPU Capture", NULL, "Alt Analog Codec Capture" }, }; +SND_SOC_DAILINK_DEF(dummy_codec, + DAILINK_COMP_ARRAY(COMP_CODEC("snd-soc-dummy", "snd-soc-dummy-dai"))); + static int skl_hda_card_late_probe(struct snd_soc_card *card) { return skl_hda_hdmi_jack_init(card); @@ -114,13 +117,19 @@ static int skl_hda_fill_card_info(struct snd_soc_acpi_mach_params *mach_params) { struct snd_soc_card *card = &hda_soc_card; struct snd_soc_dai_link *dai_link; - u32 codec_count, codec_mask; + u32 codec_count, codec_mask, idisp_mask; int i, num_links, num_route; codec_mask = mach_params->codec_mask; codec_count = hweight_long(codec_mask); + idisp_mask = codec_mask & IDISP_CODEC_MASK; + + if (!codec_count || codec_count > 2 || + (codec_count == 2 && !idisp_mask)) + return -EINVAL; - if (codec_count == 1 && codec_mask & IDISP_CODEC_MASK) { + if (codec_mask == idisp_mask) { + /* topology with iDisp as the only HDA codec */ num_links = IDISP_DAI_COUNT + DMIC_DAI_COUNT; num_route = IDISP_ROUTE_COUNT; @@ -135,13 +144,19 @@ static int skl_hda_fill_card_info(struct snd_soc_acpi_mach_params *mach_params) skl_hda_be_dai_links[IDISP_DAI_COUNT + HDAC_DAI_COUNT + i]; } - } else if (codec_count == 2 && codec_mask & IDISP_CODEC_MASK) { + } else { + /* topology with external and iDisp HDA codecs */ num_links = ARRAY_SIZE(skl_hda_be_dai_links); num_route = ARRAY_SIZE(skl_hda_map); card->dapm_widgets = skl_hda_widgets; card->num_dapm_widgets = ARRAY_SIZE(skl_hda_widgets); - } else { - return -EINVAL; + if (!idisp_mask) { + for (i = 0; i < IDISP_DAI_COUNT; i++) { + skl_hda_be_dai_links[i].codecs = dummy_codec; + skl_hda_be_dai_links[i].num_codecs = + ARRAY_SIZE(dummy_codec); + } + } } card->num_links = num_links; @@ -167,7 +182,7 @@ static int skl_hda_audio_probe(struct platform_device *pdev) INIT_LIST_HEAD(&ctx->hdmi_pcm_list); - mach = (&pdev->dev)->platform_data; + mach = pdev->dev.platform_data; if (!mach) return -EINVAL; diff --git a/sound/soc/intel/boards/skl_nau88l25_max98357a.c b/sound/soc/intel/boards/skl_nau88l25_max98357a.c index e6de3b28d840..d7b8154c43a4 100644 --- a/sound/soc/intel/boards/skl_nau88l25_max98357a.c +++ b/sound/soc/intel/boards/skl_nau88l25_max98357a.c @@ -157,7 +157,7 @@ static int skylake_ssp_fixup(struct snd_soc_pcm_runtime *rtd, static int skylake_nau8825_codec_init(struct snd_soc_pcm_runtime *rtd) { int ret; - struct snd_soc_component *component = rtd->codec_dai->component; + struct snd_soc_component *component = asoc_rtd_to_codec(rtd, 0)->component; /* * Headset buttons map to the google Reference headset. @@ -182,7 +182,7 @@ static int skylake_nau8825_codec_init(struct snd_soc_pcm_runtime *rtd) static int skylake_hdmi1_init(struct snd_soc_pcm_runtime *rtd) { struct skl_nau8825_private *ctx = snd_soc_card_get_drvdata(rtd->card); - struct snd_soc_dai *dai = rtd->codec_dai; + struct snd_soc_dai *dai = asoc_rtd_to_codec(rtd, 0); struct skl_hdmi_pcm *pcm; pcm = devm_kzalloc(rtd->card->dev, sizeof(*pcm), GFP_KERNEL); @@ -200,7 +200,7 @@ static int skylake_hdmi1_init(struct snd_soc_pcm_runtime *rtd) static int skylake_hdmi2_init(struct snd_soc_pcm_runtime *rtd) { struct skl_nau8825_private *ctx = snd_soc_card_get_drvdata(rtd->card); - struct snd_soc_dai *dai = rtd->codec_dai; + struct snd_soc_dai *dai = asoc_rtd_to_codec(rtd, 0); struct skl_hdmi_pcm *pcm; pcm = devm_kzalloc(rtd->card->dev, sizeof(*pcm), GFP_KERNEL); @@ -218,7 +218,7 @@ static int skylake_hdmi2_init(struct snd_soc_pcm_runtime *rtd) static int skylake_hdmi3_init(struct snd_soc_pcm_runtime *rtd) { struct skl_nau8825_private *ctx = snd_soc_card_get_drvdata(rtd->card); - struct snd_soc_dai *dai = rtd->codec_dai; + struct snd_soc_dai *dai = asoc_rtd_to_codec(rtd, 0); struct skl_hdmi_pcm *pcm; pcm = devm_kzalloc(rtd->card->dev, sizeof(*pcm), GFP_KERNEL); @@ -236,7 +236,7 @@ static int skylake_hdmi3_init(struct snd_soc_pcm_runtime *rtd) static int skylake_nau8825_fe_init(struct snd_soc_pcm_runtime *rtd) { struct snd_soc_dapm_context *dapm; - struct snd_soc_component *component = rtd->cpu_dai->component; + struct snd_soc_component *component = asoc_rtd_to_cpu(rtd, 0)->component; dapm = snd_soc_component_get_dapm(component); snd_soc_dapm_ignore_suspend(dapm, "Reference Capture"); @@ -296,7 +296,7 @@ static int skylake_nau8825_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params) { struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct snd_soc_dai *codec_dai = rtd->codec_dai; + struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0); int ret; ret = snd_soc_dai_set_sysclk(codec_dai, @@ -660,7 +660,7 @@ static int skylake_audio_probe(struct platform_device *pdev) skylake_audio_card.dev = &pdev->dev; snd_soc_card_set_drvdata(&skylake_audio_card, ctx); - mach = (&pdev->dev)->platform_data; + mach = pdev->dev.platform_data; if (mach) dmic_constraints = mach->mach_params.dmic_num == 2 ? &constraints_dmic_2ch : &constraints_dmic_channels; diff --git a/sound/soc/intel/boards/skl_nau88l25_ssm4567.c b/sound/soc/intel/boards/skl_nau88l25_ssm4567.c index c99c8b23e509..4b317bcf6ea0 100644 --- a/sound/soc/intel/boards/skl_nau88l25_ssm4567.c +++ b/sound/soc/intel/boards/skl_nau88l25_ssm4567.c @@ -161,12 +161,12 @@ static int skylake_ssm4567_codec_init(struct snd_soc_pcm_runtime *rtd) int ret; /* Slot 1 for left */ - ret = snd_soc_dai_set_tdm_slot(rtd->codec_dais[0], 0x01, 0x01, 2, 48); + ret = snd_soc_dai_set_tdm_slot(asoc_rtd_to_codec(rtd, 0), 0x01, 0x01, 2, 48); if (ret < 0) return ret; /* Slot 2 for right */ - ret = snd_soc_dai_set_tdm_slot(rtd->codec_dais[1], 0x02, 0x02, 2, 48); + ret = snd_soc_dai_set_tdm_slot(asoc_rtd_to_codec(rtd, 1), 0x02, 0x02, 2, 48); if (ret < 0) return ret; @@ -176,7 +176,7 @@ static int skylake_ssm4567_codec_init(struct snd_soc_pcm_runtime *rtd) static int skylake_nau8825_codec_init(struct snd_soc_pcm_runtime *rtd) { int ret; - struct snd_soc_component *component = rtd->codec_dai->component; + struct snd_soc_component *component = asoc_rtd_to_codec(rtd, 0)->component; /* * 4 buttons here map to the google Reference headset @@ -201,7 +201,7 @@ static int skylake_nau8825_codec_init(struct snd_soc_pcm_runtime *rtd) static int skylake_hdmi1_init(struct snd_soc_pcm_runtime *rtd) { struct skl_nau88125_private *ctx = snd_soc_card_get_drvdata(rtd->card); - struct snd_soc_dai *dai = rtd->codec_dai; + struct snd_soc_dai *dai = asoc_rtd_to_codec(rtd, 0); struct skl_hdmi_pcm *pcm; pcm = devm_kzalloc(rtd->card->dev, sizeof(*pcm), GFP_KERNEL); @@ -219,7 +219,7 @@ static int skylake_hdmi1_init(struct snd_soc_pcm_runtime *rtd) static int skylake_hdmi2_init(struct snd_soc_pcm_runtime *rtd) { struct skl_nau88125_private *ctx = snd_soc_card_get_drvdata(rtd->card); - struct snd_soc_dai *dai = rtd->codec_dai; + struct snd_soc_dai *dai = asoc_rtd_to_codec(rtd, 0); struct skl_hdmi_pcm *pcm; pcm = devm_kzalloc(rtd->card->dev, sizeof(*pcm), GFP_KERNEL); @@ -238,7 +238,7 @@ static int skylake_hdmi2_init(struct snd_soc_pcm_runtime *rtd) static int skylake_hdmi3_init(struct snd_soc_pcm_runtime *rtd) { struct skl_nau88125_private *ctx = snd_soc_card_get_drvdata(rtd->card); - struct snd_soc_dai *dai = rtd->codec_dai; + struct snd_soc_dai *dai = asoc_rtd_to_codec(rtd, 0); struct skl_hdmi_pcm *pcm; pcm = devm_kzalloc(rtd->card->dev, sizeof(*pcm), GFP_KERNEL); @@ -256,7 +256,7 @@ static int skylake_hdmi3_init(struct snd_soc_pcm_runtime *rtd) static int skylake_nau8825_fe_init(struct snd_soc_pcm_runtime *rtd) { struct snd_soc_dapm_context *dapm; - struct snd_soc_component *component = rtd->cpu_dai->component; + struct snd_soc_component *component = asoc_rtd_to_cpu(rtd, 0)->component; dapm = snd_soc_component_get_dapm(component); snd_soc_dapm_ignore_suspend(dapm, "Reference Capture"); @@ -348,7 +348,7 @@ static int skylake_nau8825_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params) { struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct snd_soc_dai *codec_dai = rtd->codec_dai; + struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0); int ret; ret = snd_soc_dai_set_sysclk(codec_dai, @@ -686,6 +686,7 @@ static struct snd_soc_card skylake_audio_card = { .codec_conf = ssm4567_codec_conf, .num_configs = ARRAY_SIZE(ssm4567_codec_conf), .fully_routed = true, + .disable_route_checks = true, .late_probe = skylake_card_late_probe, }; @@ -703,7 +704,7 @@ static int skylake_audio_probe(struct platform_device *pdev) skylake_audio_card.dev = &pdev->dev; snd_soc_card_set_drvdata(&skylake_audio_card, ctx); - mach = (&pdev->dev)->platform_data; + mach = pdev->dev.platform_data; if (mach) dmic_constraints = mach->mach_params.dmic_num == 2 ? &constraints_dmic_2ch : &constraints_dmic_channels; diff --git a/sound/soc/intel/boards/skl_rt286.c b/sound/soc/intel/boards/skl_rt286.c index a9aec66a2351..903ae1b28ec9 100644 --- a/sound/soc/intel/boards/skl_rt286.c +++ b/sound/soc/intel/boards/skl_rt286.c @@ -112,7 +112,7 @@ static const struct snd_soc_dapm_route skylake_rt286_map[] = { static int skylake_rt286_fe_init(struct snd_soc_pcm_runtime *rtd) { struct snd_soc_dapm_context *dapm; - struct snd_soc_component *component = rtd->cpu_dai->component; + struct snd_soc_component *component = asoc_rtd_to_cpu(rtd, 0)->component; dapm = snd_soc_component_get_dapm(component); snd_soc_dapm_ignore_suspend(dapm, "Reference Capture"); @@ -122,7 +122,7 @@ static int skylake_rt286_fe_init(struct snd_soc_pcm_runtime *rtd) static int skylake_rt286_codec_init(struct snd_soc_pcm_runtime *rtd) { - struct snd_soc_component *component = rtd->codec_dai->component; + struct snd_soc_component *component = asoc_rtd_to_codec(rtd, 0)->component; int ret; ret = snd_soc_card_jack_new(rtd->card, "Headset", @@ -143,7 +143,7 @@ static int skylake_rt286_codec_init(struct snd_soc_pcm_runtime *rtd) static int skylake_hdmi_init(struct snd_soc_pcm_runtime *rtd) { struct skl_rt286_private *ctx = snd_soc_card_get_drvdata(rtd->card); - struct snd_soc_dai *dai = rtd->codec_dai; + struct snd_soc_dai *dai = asoc_rtd_to_codec(rtd, 0); struct skl_hdmi_pcm *pcm; pcm = devm_kzalloc(rtd->card->dev, sizeof(*pcm), GFP_KERNEL); @@ -229,7 +229,7 @@ static int skylake_rt286_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params) { struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct snd_soc_dai *codec_dai = rtd->codec_dai; + struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0); int ret; ret = snd_soc_dai_set_sysclk(codec_dai, RT286_SCLK_S_PLL, 24000000, diff --git a/sound/soc/intel/boards/sof_da7219_max98373.c b/sound/soc/intel/boards/sof_da7219_max98373.c index 8f44f13d2848..b707dd3b5625 100644 --- a/sound/soc/intel/boards/sof_da7219_max98373.c +++ b/sound/soc/intel/boards/sof_da7219_max98373.c @@ -2,7 +2,7 @@ // Copyright(c) 2019 Intel Corporation. /* - * Intel SOF Machine driver for DA7219 + MAX98373 codec + * Intel SOF Machine driver for DA7219 + MAX98373/MAX98360A codec */ #include <linux/input.h> @@ -69,11 +69,20 @@ static const struct snd_kcontrol_new controls[] = { SOC_DAPM_PIN_SWITCH("Right Spk"), }; +static const struct snd_kcontrol_new m98360a_controls[] = { + SOC_DAPM_PIN_SWITCH("Headphone Jack"), + SOC_DAPM_PIN_SWITCH("Headset Mic"), + SOC_DAPM_PIN_SWITCH("Spk"), +}; + +/* For MAX98373 amp */ static const struct snd_soc_dapm_widget widgets[] = { SND_SOC_DAPM_HP("Headphone Jack", NULL), SND_SOC_DAPM_MIC("Headset Mic", NULL), + SND_SOC_DAPM_SPK("Left Spk", NULL), SND_SOC_DAPM_SPK("Right Spk", NULL), + SND_SOC_DAPM_SUPPLY("Platform Clock", SND_SOC_NOPM, 0, 0, platform_clock_control, SND_SOC_DAPM_POST_PMD | SND_SOC_DAPM_PRE_PMU), @@ -83,21 +92,45 @@ static const struct snd_soc_dapm_route audio_map[] = { { "Headphone Jack", NULL, "HPL" }, { "Headphone Jack", NULL, "HPR" }, + { "MIC", NULL, "Headset Mic" }, + + { "Headphone Jack", NULL, "Platform Clock" }, + { "Headset Mic", NULL, "Platform Clock" }, + { "Left Spk", NULL, "Left BE_OUT" }, { "Right Spk", NULL, "Right BE_OUT" }, +}; + +/* For MAX98360A amp */ +static const struct snd_soc_dapm_widget max98360a_widgets[] = { + SND_SOC_DAPM_HP("Headphone Jack", NULL), + SND_SOC_DAPM_MIC("Headset Mic", NULL), + + SND_SOC_DAPM_SPK("Spk", NULL), + + SND_SOC_DAPM_SUPPLY("Platform Clock", SND_SOC_NOPM, 0, 0, + platform_clock_control, SND_SOC_DAPM_POST_PMD | + SND_SOC_DAPM_PRE_PMU), +}; + +static const struct snd_soc_dapm_route max98360a_map[] = { + { "Headphone Jack", NULL, "HPL" }, + { "Headphone Jack", NULL, "HPR" }, { "MIC", NULL, "Headset Mic" }, { "Headphone Jack", NULL, "Platform Clock" }, { "Headset Mic", NULL, "Platform Clock" }, + + {"Spk", NULL, "Speaker"}, }; static struct snd_soc_jack headset; static int da7219_codec_init(struct snd_soc_pcm_runtime *rtd) { - struct snd_soc_component *component = rtd->codec_dai->component; - struct snd_soc_dai *codec_dai = rtd->codec_dai; + struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0); + struct snd_soc_component *component = codec_dai->component; struct snd_soc_jack *jack; int ret; @@ -140,7 +173,7 @@ static int ssp1_hw_params(struct snd_pcm_substream *substream, int ret, j; for (j = 0; j < runtime->num_codecs; j++) { - struct snd_soc_dai *codec_dai = runtime->codec_dais[j]; + struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(runtime, j); if (!strcmp(codec_dai->component->name, MAXIM_DEV0_NAME)) { /* vmon_slot_no = 0 imon_slot_no = 1 for TX slots */ @@ -181,7 +214,7 @@ static struct snd_soc_codec_conf max98373_codec_conf[] = { static int hdmi_init(struct snd_soc_pcm_runtime *rtd) { struct card_private *ctx = snd_soc_card_get_drvdata(rtd->card); - struct snd_soc_dai *dai = rtd->codec_dai; + struct snd_soc_dai *dai = asoc_rtd_to_codec(rtd, 0); struct hdmi_pcm *pcm; pcm = devm_kzalloc(rtd->card->dev, sizeof(*pcm), GFP_KERNEL); @@ -224,6 +257,9 @@ SND_SOC_DAILINK_DEF(ssp1_amps, /* Left */ COMP_CODEC(MAXIM_DEV0_NAME, MAX98373_CODEC_DAI), /* Right */ COMP_CODEC(MAXIM_DEV1_NAME, MAX98373_CODEC_DAI))); +SND_SOC_DAILINK_DEF(ssp1_m98360a, + DAILINK_COMP_ARRAY(COMP_CODEC("MX98360A:00", "HiFi"))); + SND_SOC_DAILINK_DEF(dmic_pin, DAILINK_COMP_ARRAY(COMP_CPU("DMIC01 Pin"))); SND_SOC_DAILINK_DEF(dmic_codec, @@ -320,6 +356,21 @@ static struct snd_soc_card card_da7219_m98373 = { .late_probe = card_late_probe, }; +static struct snd_soc_card card_da7219_m98360a = { + .name = "da7219max98360a", + .owner = THIS_MODULE, + .dai_link = dais, + .num_links = ARRAY_SIZE(dais), + .controls = m98360a_controls, + .num_controls = ARRAY_SIZE(m98360a_controls), + .dapm_widgets = max98360a_widgets, + .num_dapm_widgets = ARRAY_SIZE(max98360a_widgets), + .dapm_routes = max98360a_map, + .num_dapm_routes = ARRAY_SIZE(max98360a_map), + .fully_routed = true, + .late_probe = card_late_probe, +}; + static int audio_probe(struct platform_device *pdev) { static struct snd_soc_card *card; @@ -327,15 +378,26 @@ static int audio_probe(struct platform_device *pdev) struct card_private *ctx; int ret; - ctx = devm_kzalloc(&pdev->dev, sizeof(*ctx), GFP_ATOMIC); + ctx = devm_kzalloc(&pdev->dev, sizeof(*ctx), GFP_KERNEL); if (!ctx) return -ENOMEM; + /* By default dais[0] is configured for max98373 */ + if (!strcmp(pdev->name, "sof_da7219_max98360a")) { + dais[0] = (struct snd_soc_dai_link) { + .name = "SSP1-Codec", + .id = 0, + .no_pcm = 1, + .dpcm_playback = 1, + .ignore_pmdown_time = 1, + SND_SOC_DAILINK_REG(ssp1_pin, ssp1_m98360a, platform) }; + } + INIT_LIST_HEAD(&ctx->hdmi_pcm_list); card = (struct snd_soc_card *)pdev->id_entry->driver_data; card->dev = &pdev->dev; - mach = (&pdev->dev)->platform_data; + mach = pdev->dev.platform_data; ret = snd_soc_fixup_dai_links_platform_name(card, mach->mach_params.platform); if (ret) @@ -351,13 +413,17 @@ static const struct platform_device_id board_ids[] = { .name = "sof_da7219_max98373", .driver_data = (kernel_ulong_t)&card_da7219_m98373, }, + { + .name = "sof_da7219_max98360a", + .driver_data = (kernel_ulong_t)&card_da7219_m98360a, + }, { } }; static struct platform_driver audio = { .probe = audio_probe, .driver = { - .name = "sof_da7219_max98373", + .name = "sof_da7219_max98_360a_373", .pm = &snd_soc_pm_ops, }, .id_table = board_ids, @@ -368,4 +434,5 @@ module_platform_driver(audio) MODULE_DESCRIPTION("ASoC Intel(R) SOF Machine driver"); MODULE_AUTHOR("Yong Zhi <yong.zhi@intel.com>"); MODULE_LICENSE("GPL v2"); +MODULE_ALIAS("platform:sof_da7219_max98360a"); MODULE_ALIAS("platform:sof_da7219_max98373"); diff --git a/sound/soc/intel/boards/sof_maxim_common.c b/sound/soc/intel/boards/sof_maxim_common.c new file mode 100644 index 000000000000..463b39a7ccfd --- /dev/null +++ b/sound/soc/intel/boards/sof_maxim_common.c @@ -0,0 +1,80 @@ +// SPDX-License-Identifier: GPL-2.0 +// +// Copyright(c) 2020 Intel Corporation. All rights reserved. +#include <linux/string.h> +#include <sound/pcm.h> +#include <sound/soc.h> +#include <sound/soc-dai.h> +#include <sound/soc-dapm.h> +#include <uapi/sound/asound.h> +#include "sof_maxim_common.h" + +static const struct snd_soc_dapm_route max_98373_dapm_routes[] = { + /* speaker */ + { "Left Spk", NULL, "Left BE_OUT" }, + { "Right Spk", NULL, "Right BE_OUT" }, +}; + +static struct snd_soc_codec_conf max_98373_codec_conf[] = { + { + .dlc = COMP_CODEC_CONF(MAX_98373_DEV0_NAME), + .name_prefix = "Right", + }, + { + .dlc = COMP_CODEC_CONF(MAX_98373_DEV1_NAME), + .name_prefix = "Left", + }, +}; + +struct snd_soc_dai_link_component max_98373_components[] = { + { /* For Left */ + .name = MAX_98373_DEV0_NAME, + .dai_name = MAX_98373_CODEC_DAI, + }, + { /* For Right */ + .name = MAX_98373_DEV1_NAME, + .dai_name = MAX_98373_CODEC_DAI, + }, +}; + +static int max98373_hw_params(struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *params) +{ + struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_dai *codec_dai; + int j; + + for_each_rtd_codec_dais(rtd, j, codec_dai) { + if (!strcmp(codec_dai->component->name, MAX_98373_DEV0_NAME)) { + /* DEV0 tdm slot configuration */ + snd_soc_dai_set_tdm_slot(codec_dai, 0x30, 3, 8, 16); + } + if (!strcmp(codec_dai->component->name, MAX_98373_DEV1_NAME)) { + /* DEV1 tdm slot configuration */ + snd_soc_dai_set_tdm_slot(codec_dai, 0xC0, 3, 8, 16); + } + } + return 0; +} + +struct snd_soc_ops max_98373_ops = { + .hw_params = max98373_hw_params, +}; + +int max98373_spk_codec_init(struct snd_soc_pcm_runtime *rtd) +{ + struct snd_soc_card *card = rtd->card; + int ret; + + ret = snd_soc_dapm_add_routes(&card->dapm, max_98373_dapm_routes, + ARRAY_SIZE(max_98373_dapm_routes)); + if (ret) + dev_err(rtd->dev, "Speaker map addition failed: %d\n", ret); + return ret; +} + +void sof_max98373_codec_conf(struct snd_soc_card *card) +{ + card->codec_conf = max_98373_codec_conf; + card->num_configs = ARRAY_SIZE(max_98373_codec_conf); +} diff --git a/sound/soc/intel/boards/sof_maxim_common.h b/sound/soc/intel/boards/sof_maxim_common.h new file mode 100644 index 000000000000..406bf0e81155 --- /dev/null +++ b/sound/soc/intel/boards/sof_maxim_common.h @@ -0,0 +1,24 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright(c) 2020 Intel Corporation. + */ + +/* + * This file defines data structures used in Machine Driver for Intel + * platforms with Maxim Codecs. + */ +#ifndef __SOF_MAXIM_COMMON_H +#define __SOF_MAXIM_COMMON_H + +#include <sound/soc.h> + +#define MAX_98373_CODEC_DAI "max98373-aif1" +#define MAX_98373_DEV0_NAME "i2c-MX98373:00" +#define MAX_98373_DEV1_NAME "i2c-MX98373:01" + +extern struct snd_soc_dai_link_component max_98373_components[2]; +extern struct snd_soc_ops max_98373_ops; + +int max98373_spk_codec_init(struct snd_soc_pcm_runtime *rtd); +void sof_max98373_codec_conf(struct snd_soc_card *card); +#endif /* __SOF_MAXIM_COMMON_H */ diff --git a/sound/soc/intel/boards/sof_pcm512x.c b/sound/soc/intel/boards/sof_pcm512x.c new file mode 100644 index 000000000000..fb7811899999 --- /dev/null +++ b/sound/soc/intel/boards/sof_pcm512x.c @@ -0,0 +1,448 @@ +// SPDX-License-Identifier: GPL-2.0 +// Copyright(c) 2018-2020 Intel Corporation. + +/* + * Intel SOF Machine Driver for Intel platforms with TI PCM512x codec, + * e.g. Up or Up2 with Hifiberry DAC+ HAT + */ +#include <linux/clk.h> +#include <linux/dmi.h> +#include <linux/i2c.h> +#include <linux/input.h> +#include <linux/module.h> +#include <linux/platform_device.h> +#include <linux/types.h> +#include <sound/core.h> +#include <sound/jack.h> +#include <sound/pcm.h> +#include <sound/pcm_params.h> +#include <sound/soc.h> +#include <sound/soc-acpi.h> +#include "../../codecs/pcm512x.h" +#include "../common/soc-intel-quirks.h" +#include "hda_dsp_common.h" + +#define NAME_SIZE 32 + +#define SOF_PCM512X_SSP_CODEC(quirk) ((quirk) & GENMASK(3, 0)) +#define SOF_PCM512X_SSP_CODEC_MASK (GENMASK(3, 0)) + +#define IDISP_CODEC_MASK 0x4 + +/* Default: SSP5 */ +static unsigned long sof_pcm512x_quirk = SOF_PCM512X_SSP_CODEC(5); + +static bool is_legacy_cpu; + +struct sof_hdmi_pcm { + struct list_head head; + struct snd_soc_dai *codec_dai; + int device; +}; + +struct sof_card_private { + struct list_head hdmi_pcm_list; + bool idisp_codec; +}; + +static int sof_pcm512x_quirk_cb(const struct dmi_system_id *id) +{ + sof_pcm512x_quirk = (unsigned long)id->driver_data; + return 1; +} + +static const struct dmi_system_id sof_pcm512x_quirk_table[] = { + { + .callback = sof_pcm512x_quirk_cb, + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "AAEON"), + DMI_MATCH(DMI_PRODUCT_NAME, "UP-CHT01"), + }, + .driver_data = (void *)(SOF_PCM512X_SSP_CODEC(2)), + }, + {} +}; + +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; +} + +static int sof_pcm512x_codec_init(struct snd_soc_pcm_runtime *rtd) +{ + struct snd_soc_component *codec = asoc_rtd_to_codec(rtd, 0)->component; + + snd_soc_component_update_bits(codec, PCM512x_GPIO_EN, 0x08, 0x08); + snd_soc_component_update_bits(codec, PCM512x_GPIO_OUTPUT_4, 0x0f, 0x02); + snd_soc_component_update_bits(codec, PCM512x_GPIO_CONTROL_1, + 0x08, 0x08); + + return 0; +} + +static int aif1_startup(struct snd_pcm_substream *substream) +{ + struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_component *codec = asoc_rtd_to_codec(rtd, 0)->component; + + snd_soc_component_update_bits(codec, PCM512x_GPIO_CONTROL_1, + 0x08, 0x08); + + return 0; +} + +static void aif1_shutdown(struct snd_pcm_substream *substream) +{ + struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_component *codec = asoc_rtd_to_codec(rtd, 0)->component; + + snd_soc_component_update_bits(codec, PCM512x_GPIO_CONTROL_1, + 0x08, 0x00); +} + +static const struct snd_soc_ops sof_pcm512x_ops = { + .startup = aif1_startup, + .shutdown = aif1_shutdown, +}; + +static struct snd_soc_dai_link_component platform_component[] = { + { + /* name might be overridden during probe */ + .name = "0000:00:1f.3" + } +}; + +#if IS_ENABLED(CONFIG_SND_HDA_CODEC_HDMI) +static int sof_card_late_probe(struct snd_soc_card *card) +{ + struct sof_card_private *ctx = snd_soc_card_get_drvdata(card); + struct sof_hdmi_pcm *pcm; + + /* HDMI is not supported by SOF on Baytrail/CherryTrail */ + if (is_legacy_cpu) + return 0; + + if (list_empty(&ctx->hdmi_pcm_list)) + return -EINVAL; + + if (!ctx->idisp_codec) + return 0; + + pcm = list_first_entry(&ctx->hdmi_pcm_list, struct sof_hdmi_pcm, head); + + return hda_dsp_hdmi_build_controls(card, pcm->codec_dai->component); +} +#else +static int sof_card_late_probe(struct snd_soc_card *card) +{ + return 0; +} +#endif + +static const struct snd_kcontrol_new sof_controls[] = { + SOC_DAPM_PIN_SWITCH("Ext Spk"), +}; + +static const struct snd_soc_dapm_widget sof_widgets[] = { + SND_SOC_DAPM_SPK("Ext Spk", NULL), +}; + +static const struct snd_soc_dapm_widget dmic_widgets[] = { + SND_SOC_DAPM_MIC("SoC DMIC", NULL), +}; + +static const struct snd_soc_dapm_route sof_map[] = { + /* Speaker */ + {"Ext Spk", NULL, "OUTR"}, + {"Ext Spk", NULL, "OUTL"}, +}; + +static const struct snd_soc_dapm_route dmic_map[] = { + /* digital mics */ + {"DMic", NULL, "SoC DMIC"}, +}; + +static int dmic_init(struct snd_soc_pcm_runtime *rtd) +{ + struct snd_soc_card *card = rtd->card; + int ret; + + ret = snd_soc_dapm_new_controls(&card->dapm, dmic_widgets, + ARRAY_SIZE(dmic_widgets)); + if (ret) { + dev_err(card->dev, "DMic widget addition failed: %d\n", ret); + /* Don't need to add routes if widget addition failed */ + return ret; + } + + ret = snd_soc_dapm_add_routes(&card->dapm, dmic_map, + ARRAY_SIZE(dmic_map)); + + if (ret) + dev_err(card->dev, "DMic map addition failed: %d\n", ret); + + return ret; +} + +/* sof audio machine driver for pcm512x codec */ +static struct snd_soc_card sof_audio_card_pcm512x = { + .name = "pcm512x", + .owner = THIS_MODULE, + .controls = sof_controls, + .num_controls = ARRAY_SIZE(sof_controls), + .dapm_widgets = sof_widgets, + .num_dapm_widgets = ARRAY_SIZE(sof_widgets), + .dapm_routes = sof_map, + .num_dapm_routes = ARRAY_SIZE(sof_map), + .fully_routed = true, + .late_probe = sof_card_late_probe, +}; + +SND_SOC_DAILINK_DEF(pcm512x_component, + DAILINK_COMP_ARRAY(COMP_CODEC("i2c-104C5122:00", "pcm512x-hifi"))); +SND_SOC_DAILINK_DEF(dmic_component, + DAILINK_COMP_ARRAY(COMP_CODEC("dmic-codec", "dmic-hifi"))); + +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_kcalloc(dev, sof_audio_card_pcm512x.num_links, + sizeof(struct snd_soc_dai_link), GFP_KERNEL); + cpus = devm_kcalloc(dev, sof_audio_card_pcm512x.num_links, + sizeof(struct snd_soc_dai_link_component), GFP_KERNEL); + if (!links || !cpus) + goto devm_err; + + /* codec SSP */ + links[id].name = devm_kasprintf(dev, GFP_KERNEL, + "SSP%d-Codec", ssp_codec); + if (!links[id].name) + goto devm_err; + + links[id].id = id; + links[id].codecs = pcm512x_component; + links[id].num_codecs = ARRAY_SIZE(pcm512x_component); + links[id].platforms = platform_component; + links[id].num_platforms = ARRAY_SIZE(platform_component); + links[id].init = sof_pcm512x_codec_init; + links[id].ops = &sof_pcm512x_ops; + links[id].nonatomic = true; + links[id].dpcm_playback = 1; + /* + * capture only supported with specific versions of the Hifiberry DAC+ + * links[id].dpcm_capture = 1; + */ + links[id].no_pcm = 1; + links[id].cpus = &cpus[id]; + links[id].num_cpus = 1; + if (is_legacy_cpu) { + links[id].cpus->dai_name = devm_kasprintf(dev, GFP_KERNEL, + "ssp%d-port", + ssp_codec); + if (!links[id].cpus->dai_name) + goto devm_err; + } else { + links[id].cpus->dai_name = devm_kasprintf(dev, GFP_KERNEL, + "SSP%d Pin", + ssp_codec); + if (!links[id].cpus->dai_name) + goto devm_err; + } + 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"; + links[id].init = dmic_init; + 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 */ + if (hdmi_num > 0) { + idisp_components = devm_kcalloc(dev, hdmi_num, + sizeof(struct snd_soc_dai_link_component), + 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; + + /* + * topology cannot be loaded if codec is missing, so + * use the dummy codec if needed + */ + 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); + } else { + idisp_components[i - 1].name = "snd-soc-dummy"; + idisp_components[i - 1].dai_name = "snd-soc-dummy-dai"; + } + if (!idisp_components[i - 1].dai_name) + goto devm_err; + + 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++; + } + + return links; +devm_err: + return NULL; +} + +static int sof_audio_probe(struct platform_device *pdev) +{ + struct snd_soc_acpi_mach *mach = pdev->dev.platform_data; + struct snd_soc_dai_link *dai_links; + struct sof_card_private *ctx; + int dmic_be_num, hdmi_num; + int ret, ssp_codec; + + ctx = devm_kzalloc(&pdev->dev, sizeof(*ctx), GFP_KERNEL); + if (!ctx) + return -ENOMEM; + + hdmi_num = 0; + if (soc_intel_is_byt() || soc_intel_is_cht()) { + is_legacy_cpu = true; + dmic_be_num = 0; + /* default quirk for legacy cpu */ + sof_pcm512x_quirk = SOF_PCM512X_SSP_CODEC(2); + } else { + dmic_be_num = 2; +#if IS_ENABLED(CONFIG_SND_HDA_CODEC_HDMI) + if (mach->mach_params.common_hdmi_codec_drv && + (mach->mach_params.codec_mask & IDISP_CODEC_MASK)) + ctx->idisp_codec = true; + + /* links are always present in topology */ + hdmi_num = 3; +#endif + } + + dmi_check_system(sof_pcm512x_quirk_table); + + dev_dbg(&pdev->dev, "sof_pcm512x_quirk = %lx\n", sof_pcm512x_quirk); + + ssp_codec = sof_pcm512x_quirk & SOF_PCM512X_SSP_CODEC_MASK; + + /* compute number of dai links */ + sof_audio_card_pcm512x.num_links = 1 + dmic_be_num + hdmi_num; + + 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_audio_card_pcm512x.dai_link = dai_links; + + INIT_LIST_HEAD(&ctx->hdmi_pcm_list); + + sof_audio_card_pcm512x.dev = &pdev->dev; + + /* set platform name for each dailink */ + ret = snd_soc_fixup_dai_links_platform_name(&sof_audio_card_pcm512x, + mach->mach_params.platform); + if (ret) + return ret; + + snd_soc_card_set_drvdata(&sof_audio_card_pcm512x, ctx); + + return devm_snd_soc_register_card(&pdev->dev, + &sof_audio_card_pcm512x); +} + +static int sof_pcm512x_remove(struct platform_device *pdev) +{ + struct snd_soc_card *card = platform_get_drvdata(pdev); + struct snd_soc_component *component = NULL; + + for_each_card_components(card, component) { + if (!strcmp(component->name, pcm512x_component[0].name)) { + snd_soc_component_set_jack(component, NULL, NULL); + break; + } + } + + return 0; +} + +static struct platform_driver sof_audio = { + .probe = sof_audio_probe, + .remove = sof_pcm512x_remove, + .driver = { + .name = "sof_pcm512x", + .pm = &snd_soc_pm_ops, + }, +}; +module_platform_driver(sof_audio) + +MODULE_DESCRIPTION("ASoC Intel(R) SOF + PCM512x Machine driver"); +MODULE_AUTHOR("Pierre-Louis Bossart"); +MODULE_LICENSE("GPL v2"); +MODULE_ALIAS("platform:sof_pcm512x"); diff --git a/sound/soc/intel/boards/sof_rt5682.c b/sound/soc/intel/boards/sof_rt5682.c index 5d878873a8e0..8c29431b5847 100644 --- a/sound/soc/intel/boards/sof_rt5682.c +++ b/sound/soc/intel/boards/sof_rt5682.c @@ -1,9 +1,9 @@ // SPDX-License-Identifier: GPL-2.0 -// Copyright(c) 2019 Intel Corporation. +// Copyright(c) 2019-2020 Intel Corporation. /* * Intel SOF Machine Driver with Realtek rt5682 Codec - * and speaker codec MAX98357A + * and speaker codec MAX98357A or RT1015. */ #include <linux/i2c.h> #include <linux/input.h> @@ -18,10 +18,12 @@ #include <sound/soc.h> #include <sound/rt5682.h> #include <sound/soc-acpi.h> +#include "../../codecs/rt1015.h" #include "../../codecs/rt5682.h" #include "../../codecs/hdac_hdmi.h" #include "../common/soc-intel-quirks.h" #include "hda_dsp_common.h" +#include "sof_maxim_common.h" #define NAME_SIZE 32 @@ -39,6 +41,8 @@ #define SOF_RT5682_NUM_HDMIDEV_MASK (GENMASK(12, 10)) #define SOF_RT5682_NUM_HDMIDEV(quirk) \ ((quirk << SOF_RT5682_NUM_HDMIDEV_SHIFT) & SOF_RT5682_NUM_HDMIDEV_MASK) +#define SOF_RT1015_SPEAKER_AMP_PRESENT BIT(13) +#define SOF_MAX98373_SPEAKER_AMP_PRESENT BIT(14) /* Default: MCLK on, MCLK 19.2M, SSP0 */ static unsigned long sof_rt5682_quirk = SOF_RT5682_MCLK_EN | @@ -120,7 +124,7 @@ static const struct dmi_system_id sof_rt5682_quirk_table[] = { 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 = rtd->codec_dai; + 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); @@ -139,7 +143,7 @@ static int sof_hdmi_init(struct snd_soc_pcm_runtime *rtd) static int sof_rt5682_codec_init(struct snd_soc_pcm_runtime *rtd) { struct sof_card_private *ctx = snd_soc_card_get_drvdata(rtd->card); - struct snd_soc_component *component = rtd->codec_dai->component; + struct snd_soc_component *component = asoc_rtd_to_codec(rtd, 0)->component; struct snd_soc_jack *jack; int ret; @@ -207,7 +211,7 @@ static int sof_rt5682_hw_params(struct snd_pcm_substream *substream, { struct snd_soc_pcm_runtime *rtd = substream->private_data; struct sof_card_private *ctx = snd_soc_card_get_drvdata(rtd->card); - struct snd_soc_dai *codec_dai = rtd->codec_dai; + struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0); int clk_id, clk_freq, pll_out, ret; if (sof_rt5682_quirk & SOF_RT5682_MCLK_EN) { @@ -260,6 +264,42 @@ static struct snd_soc_ops sof_rt5682_ops = { .hw_params = sof_rt5682_hw_params, }; +static int sof_rt1015_hw_params(struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *params) +{ + struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_card *card = rtd->card; + struct snd_soc_dai *codec_dai; + int i, ret; + + if (!snd_soc_card_get_codec_dai(card, "rt1015-aif")) + return 0; + + for_each_rtd_codec_dais(rtd, i, codec_dai) { + ret = snd_soc_dai_set_pll(codec_dai, 0, RT1015_PLL_S_BCLK, + params_rate(params) * 50, + params_rate(params) * 256); + if (ret < 0) { + dev_err(card->dev, "failed to set pll\n"); + return ret; + } + /* Configure sysclk for codec */ + ret = snd_soc_dai_set_sysclk(codec_dai, RT1015_SCLK_S_PLL, + params_rate(params) * 256, + SND_SOC_CLOCK_IN); + if (ret < 0) { + dev_err(card->dev, "failed to set sysclk\n"); + return ret; + } + } + + return 0; +} + +static struct snd_soc_ops sof_rt1015_ops = { + .hw_params = sof_rt1015_hw_params, +}; + static struct snd_soc_dai_link_component platform_component[] = { { /* name might be overridden during probe */ @@ -316,12 +356,17 @@ static const struct snd_kcontrol_new sof_controls[] = { SOC_DAPM_PIN_SWITCH("Headphone Jack"), SOC_DAPM_PIN_SWITCH("Headset Mic"), SOC_DAPM_PIN_SWITCH("Spk"), + SOC_DAPM_PIN_SWITCH("Left Spk"), + SOC_DAPM_PIN_SWITCH("Right Spk"), + }; static const struct snd_soc_dapm_widget sof_widgets[] = { SND_SOC_DAPM_HP("Headphone Jack", NULL), SND_SOC_DAPM_MIC("Headset Mic", NULL), SND_SOC_DAPM_SPK("Spk", NULL), + SND_SOC_DAPM_SPK("Left Spk", NULL), + SND_SOC_DAPM_SPK("Right Spk", NULL), }; static const struct snd_soc_dapm_widget dmic_widgets[] = { @@ -342,11 +387,22 @@ static const struct snd_soc_dapm_route speaker_map[] = { { "Spk", NULL, "Speaker" }, }; +static const struct snd_soc_dapm_route speaker_map_lr[] = { + { "Left Spk", NULL, "Left SPO" }, + { "Right Spk", NULL, "Right SPO" }, +}; + static const struct snd_soc_dapm_route dmic_map[] = { /* digital mics */ {"DMic", NULL, "SoC DMIC"}, }; +static int speaker_codec_init_lr(struct snd_soc_pcm_runtime *rtd) +{ + return snd_soc_dapm_add_routes(&rtd->card->dapm, speaker_map_lr, + ARRAY_SIZE(speaker_map_lr)); +} + static int speaker_codec_init(struct snd_soc_pcm_runtime *rtd) { struct snd_soc_card *card = rtd->card; @@ -382,6 +438,17 @@ static int dmic_init(struct snd_soc_pcm_runtime *rtd) return ret; } +static struct snd_soc_codec_conf rt1015_amp_conf[] = { + { + .dlc = COMP_CODEC_CONF("i2c-10EC1015:00"), + .name_prefix = "Left", + }, + { + .dlc = COMP_CODEC_CONF("i2c-10EC1015:01"), + .name_prefix = "Right", + }, +}; + /* sof audio machine driver for rt5682 codec */ static struct snd_soc_card sof_audio_card_rt5682 = { .name = "rt5682", /* the sof- prefix is added by the core */ @@ -417,6 +484,17 @@ static struct snd_soc_dai_link_component max98357a_component[] = { } }; +static struct snd_soc_dai_link_component rt1015_components[] = { + { + .name = "i2c-10EC1015:00", + .dai_name = "rt1015-aif", + }, + { + .name = "i2c-10EC1015:01", + .dai_name = "rt1015-aif", + }, +}; + static struct snd_soc_dai_link *sof_card_dai_links_create(struct device *dev, int ssp_codec, int ssp_amp, @@ -556,11 +634,24 @@ static struct snd_soc_dai_link *sof_card_dai_links_create(struct device *dev, goto devm_err; links[id].id = id; - links[id].codecs = max98357a_component; - links[id].num_codecs = ARRAY_SIZE(max98357a_component); + if (sof_rt5682_quirk & SOF_RT1015_SPEAKER_AMP_PRESENT) { + links[id].codecs = rt1015_components; + links[id].num_codecs = ARRAY_SIZE(rt1015_components); + links[id].init = speaker_codec_init_lr; + links[id].ops = &sof_rt1015_ops; + } else if (sof_rt5682_quirk & + SOF_MAX98373_SPEAKER_AMP_PRESENT) { + links[id].codecs = max_98373_components; + links[id].num_codecs = ARRAY_SIZE(max_98373_components); + links[id].init = max98373_spk_codec_init; + links[id].ops = &max_98373_ops; + } else { + links[id].codecs = max98357a_component; + links[id].num_codecs = ARRAY_SIZE(max98357a_component); + links[id].init = speaker_codec_init; + } links[id].platforms = platform_component; links[id].num_platforms = ARRAY_SIZE(platform_component); - links[id].init = speaker_codec_init, links[id].nonatomic = true; links[id].dpcm_playback = 1; links[id].no_pcm = 1; @@ -604,7 +695,7 @@ static int sof_audio_probe(struct platform_device *pdev) dmi_check_system(sof_rt5682_quirk_table); - mach = (&pdev->dev)->platform_data; + mach = pdev->dev.platform_data; /* A speaker amp might not be present when the quirk claims one is. * Detect this via whether the machine driver match includes quirk_data. @@ -662,6 +753,9 @@ static int sof_audio_probe(struct platform_device *pdev) if (sof_rt5682_quirk & SOF_SPEAKER_AMP_PRESENT) sof_audio_card_rt5682.num_links++; + if (sof_rt5682_quirk & SOF_MAX98373_SPEAKER_AMP_PRESENT) + sof_max98373_codec_conf(&sof_audio_card_rt5682); + dai_links = sof_card_dai_links_create(&pdev->dev, ssp_codec, ssp_amp, dmic_be_num, hdmi_num); if (!dai_links) @@ -669,6 +763,11 @@ static int sof_audio_probe(struct platform_device *pdev) sof_audio_card_rt5682.dai_link = dai_links; + if (sof_rt5682_quirk & SOF_RT1015_SPEAKER_AMP_PRESENT) { + sof_audio_card_rt5682.codec_conf = rt1015_amp_conf; + sof_audio_card_rt5682.num_configs = ARRAY_SIZE(rt1015_amp_conf); + } + INIT_LIST_HEAD(&ctx->hdmi_pcm_list); sof_audio_card_rt5682.dev = &pdev->dev; @@ -714,6 +813,24 @@ static const struct platform_device_id board_ids[] = { SOF_RT5682_SSP_AMP(1) | SOF_RT5682_NUM_HDMIDEV(4)), }, + { + .name = "jsl_rt5682_rt1015", + .driver_data = (kernel_ulong_t)(SOF_RT5682_MCLK_EN | + SOF_RT5682_MCLK_24MHZ | + SOF_RT5682_SSP_CODEC(0) | + SOF_SPEAKER_AMP_PRESENT | + SOF_RT1015_SPEAKER_AMP_PRESENT | + SOF_RT5682_SSP_AMP(1)), + }, + { + .name = "tgl_max98373_rt5682", + .driver_data = (kernel_ulong_t)(SOF_RT5682_MCLK_EN | + SOF_RT5682_SSP_CODEC(0) | + SOF_SPEAKER_AMP_PRESENT | + SOF_MAX98373_SPEAKER_AMP_PRESENT | + SOF_RT5682_SSP_AMP(1) | + SOF_RT5682_NUM_HDMIDEV(4)), + }, { } }; @@ -735,3 +852,5 @@ MODULE_AUTHOR("Sathya Prakash M R <sathya.prakash.m.r@intel.com>"); MODULE_LICENSE("GPL v2"); MODULE_ALIAS("platform:sof_rt5682"); MODULE_ALIAS("platform:tgl_max98357a_rt5682"); +MODULE_ALIAS("platform:jsl_rt5682_rt1015"); +MODULE_ALIAS("platform:tgl_max98373_rt5682"); diff --git a/sound/soc/intel/boards/sof_sdw.c b/sound/soc/intel/boards/sof_sdw.c new file mode 100644 index 000000000000..a64dc563b47e --- /dev/null +++ b/sound/soc/intel/boards/sof_sdw.c @@ -0,0 +1,962 @@ +// SPDX-License-Identifier: GPL-2.0 +// Copyright (c) 2020 Intel Corporation + +/* + * sof_sdw - ASOC Machine driver for Intel SoundWire platforms + */ + +#include <linux/device.h> +#include <linux/dmi.h> +#include <linux/module.h> +#include <linux/soundwire/sdw.h> +#include <linux/soundwire/sdw_type.h> +#include <sound/soc.h> +#include <sound/soc-acpi.h> +#include "sof_sdw_common.h" + +unsigned long sof_sdw_quirk = SOF_RT711_JD_SRC_JD1; + +#define INC_ID(BE, CPU, LINK) do { (BE)++; (CPU)++; (LINK)++; } while (0) + +static int sof_sdw_quirk_cb(const struct dmi_system_id *id) +{ + sof_sdw_quirk = (unsigned long)id->driver_data; + return 1; +} + +static const struct dmi_system_id sof_sdw_quirk_table[] = { + { + .callback = sof_sdw_quirk_cb, + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"), + DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "09C6") + }, + .driver_data = (void *)(SOF_RT711_JD_SRC_JD2 | + SOF_RT715_DAI_ID_FIX), + }, + { + /* early version of SKU 09C6 */ + .callback = sof_sdw_quirk_cb, + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"), + DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "0983") + }, + .driver_data = (void *)(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, "098F"), + }, + .driver_data = (void *)(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, "0990"), + }, + .driver_data = (void *)(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, "Intel Corporation"), + DMI_MATCH(DMI_PRODUCT_NAME, + "Tiger Lake Client Platform"), + }, + .driver_data = (void *)(SOF_RT711_JD_SRC_JD1 | + SOF_SDW_TGL_HDMI | SOF_SDW_PCH_DMIC | + SOF_SSP_PORT(SOF_I2S_SSP2)), + }, + { + .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, + }, + { + .callback = sof_sdw_quirk_cb, + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Intel Corporation"), + DMI_MATCH(DMI_PRODUCT_NAME, "CometLake Client"), + }, + .driver_data = (void *)SOF_SDW_PCH_DMIC, + }, + { + .callback = sof_sdw_quirk_cb, + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Google"), + DMI_MATCH(DMI_PRODUCT_NAME, "Volteer"), + }, + .driver_data = (void *)(SOF_SDW_TGL_HDMI | SOF_SDW_PCH_DMIC), + }, + + {} +}; + +static struct snd_soc_codec_conf codec_conf[] = { + { + .dlc = COMP_CODEC_CONF("sdw:0:25d:711:0"), + .name_prefix = "rt711", + }, + /* rt1308 w/ I2S connection */ + { + .dlc = COMP_CODEC_CONF("i2c-10EC1308:00"), + .name_prefix = "rt1308-1", + }, + /* rt1308 left on link 1 */ + { + .dlc = COMP_CODEC_CONF("sdw:1:25d:1308:0"), + .name_prefix = "rt1308-1", + }, + /* two 1308s on link1 with different unique id */ + { + .dlc = COMP_CODEC_CONF("sdw:1:25d:1308:0:0"), + .name_prefix = "rt1308-1", + }, + { + .dlc = COMP_CODEC_CONF("sdw:1:25d:1308:0:2"), + .name_prefix = "rt1308-2", + }, + /* rt1308 right on link 2 */ + { + .dlc = COMP_CODEC_CONF("sdw:2:25d:1308:0"), + .name_prefix = "rt1308-2", + }, + { + .dlc = COMP_CODEC_CONF("sdw:3:25d:715:0"), + .name_prefix = "rt715", + }, + { + .dlc = COMP_CODEC_CONF("sdw:0:25d:5682:0"), + .name_prefix = "rt5682", + }, +}; + +static struct snd_soc_dai_link_component dmic_component[] = { + { + .name = "dmic-codec", + .dai_name = "dmic-hifi", + } +}; + +static struct snd_soc_dai_link_component platform_component[] = { + { + /* name might be overridden during probe */ + .name = "0000:00:1f.3" + } +}; + +/* these wrappers are only needed to avoid typecast compilation errors */ +static int sdw_startup(struct snd_pcm_substream *substream) +{ + return sdw_startup_stream(substream); +} + +static void sdw_shutdown(struct snd_pcm_substream *substream) +{ + sdw_shutdown_stream(substream); +} + +static const struct snd_soc_ops sdw_ops = { + .startup = sdw_startup, + .shutdown = sdw_shutdown, +}; + +static struct sof_sdw_codec_info codec_info_list[] = { + { + .id = 0x700, + .direction = {true, true}, + .dai_name = "rt700-aif1", + .init = sof_sdw_rt700_init, + }, + { + .id = 0x711, + .direction = {true, true}, + .dai_name = "rt711-aif1", + .init = sof_sdw_rt711_init, + }, + { + .id = 0x1308, + .acpi_id = "10EC1308", + .direction = {true, false}, + .dai_name = "rt1308-aif", + .ops = &sof_sdw_rt1308_i2s_ops, + .init = sof_sdw_rt1308_init, + }, + { + .id = 0x715, + .direction = {false, true}, + .dai_name = "rt715-aif2", + .init = sof_sdw_rt715_init, + }, + { + .id = 0x5682, + .direction = {true, true}, + .dai_name = "rt5682-sdw", + .init = sof_sdw_rt5682_init, + }, +}; + +static inline int find_codec_info_part(unsigned int part_id) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(codec_info_list); i++) + if (part_id == codec_info_list[i].id) + break; + + if (i == ARRAY_SIZE(codec_info_list)) + return -EINVAL; + + return i; +} + +static inline int find_codec_info_acpi(const u8 *acpi_id) +{ + int i; + + if (!acpi_id[0]) + return -EINVAL; + + for (i = 0; i < ARRAY_SIZE(codec_info_list); i++) + if (!memcmp(codec_info_list[i].acpi_id, acpi_id, + ACPI_ID_LEN)) + break; + + if (i == ARRAY_SIZE(codec_info_list)) + return -EINVAL; + + return i; +} + +/* + * get BE dailink number and CPU DAI number based on sdw link adr. + * Since some sdw slaves may be aggregated, the CPU DAI number + * may be larger than the number of BE dailinks. + */ +static int get_sdw_dailink_info(const struct snd_soc_acpi_link_adr *links, + int *sdw_be_num, int *sdw_cpu_dai_num) +{ + const struct snd_soc_acpi_link_adr *link; + bool group_visited[SDW_MAX_GROUPS]; + bool no_aggregation; + int i; + + no_aggregation = sof_sdw_quirk & SOF_SDW_NO_AGGREGATION; + *sdw_cpu_dai_num = 0; + *sdw_be_num = 0; + + if (!links) + return -EINVAL; + + for (i = 0; i < SDW_MAX_GROUPS; i++) + group_visited[i] = false; + + for (link = links; link->num_adr; link++) { + const struct snd_soc_acpi_endpoint *endpoint; + int part_id, codec_index; + int stream; + u64 adr; + + adr = link->adr_d->adr; + part_id = SDW_PART_ID(adr); + codec_index = find_codec_info_part(part_id); + if (codec_index < 0) + return codec_index; + + endpoint = link->adr_d->endpoints; + + /* count DAI number for playback and capture */ + for_each_pcm_streams(stream) { + if (!codec_info_list[codec_index].direction[stream]) + continue; + + (*sdw_cpu_dai_num)++; + + /* count BE for each non-aggregated slave or group */ + if (!endpoint->aggregated || no_aggregation || + !group_visited[endpoint->group_id]) + (*sdw_be_num)++; + } + + if (endpoint->aggregated) + group_visited[endpoint->group_id] = true; + } + + return 0; +} + +static void init_dai_link(struct snd_soc_dai_link *dai_links, int be_id, + char *name, int playback, int capture, + struct snd_soc_dai_link_component *cpus, + int cpus_num, + struct snd_soc_dai_link_component *codecs, + int codecs_num, + int (*init)(struct snd_soc_pcm_runtime *rtd), + const struct snd_soc_ops *ops) +{ + dai_links->id = be_id; + dai_links->name = name; + dai_links->platforms = platform_component; + dai_links->num_platforms = ARRAY_SIZE(platform_component); + dai_links->nonatomic = true; + dai_links->no_pcm = 1; + dai_links->cpus = cpus; + dai_links->num_cpus = cpus_num; + dai_links->codecs = codecs; + dai_links->num_codecs = codecs_num; + dai_links->dpcm_playback = playback; + dai_links->dpcm_capture = capture; + dai_links->init = init; + dai_links->ops = ops; +} + +static bool is_unique_device(const struct snd_soc_acpi_link_adr *link, + unsigned int sdw_version, + unsigned int mfg_id, + unsigned int part_id, + unsigned int class_id, + int index_in_link + ) +{ + int i; + + for (i = 0; i < link->num_adr; i++) { + unsigned int sdw1_version, mfg1_id, part1_id, class1_id; + u64 adr; + + /* skip itself */ + if (i == index_in_link) + continue; + + adr = link->adr_d[i].adr; + + sdw1_version = SDW_VERSION(adr); + mfg1_id = SDW_MFG_ID(adr); + part1_id = SDW_PART_ID(adr); + class1_id = SDW_CLASS_ID(adr); + + if (sdw_version == sdw1_version && + mfg_id == mfg1_id && + part_id == part1_id && + class_id == class1_id) + return false; + } + + return true; +} + +static int create_codec_dai_name(struct device *dev, + const struct snd_soc_acpi_link_adr *link, + struct snd_soc_dai_link_component *codec, + int offset) +{ + int i; + + for (i = 0; i < link->num_adr; i++) { + unsigned int sdw_version, unique_id, mfg_id; + unsigned int link_id, part_id, class_id; + int codec_index, comp_index; + char *codec_str; + u64 adr; + + adr = link->adr_d[i].adr; + + sdw_version = SDW_VERSION(adr); + link_id = SDW_DISCO_LINK_ID(adr); + unique_id = SDW_UNIQUE_ID(adr); + mfg_id = SDW_MFG_ID(adr); + part_id = SDW_PART_ID(adr); + class_id = SDW_CLASS_ID(adr); + + comp_index = i + offset; + if (is_unique_device(link, sdw_version, mfg_id, part_id, + class_id, i)) { + codec_str = "sdw:%x:%x:%x:%x"; + codec[comp_index].name = + devm_kasprintf(dev, GFP_KERNEL, codec_str, + link_id, mfg_id, part_id, + class_id); + } else { + codec_str = "sdw:%x:%x:%x:%x:%x"; + codec[comp_index].name = + devm_kasprintf(dev, GFP_KERNEL, codec_str, + link_id, mfg_id, part_id, + class_id, unique_id); + } + + if (!codec[comp_index].name) + return -ENOMEM; + + codec_index = find_codec_info_part(part_id); + if (codec_index < 0) + return codec_index; + + codec[comp_index].dai_name = + codec_info_list[codec_index].dai_name; + } + + return 0; +} + +static int set_codec_init_func(const struct snd_soc_acpi_link_adr *link, + struct snd_soc_dai_link *dai_links, + bool playback) +{ + int i; + + for (i = 0; i < link->num_adr; i++) { + unsigned int part_id; + int codec_index; + + part_id = SDW_PART_ID(link->adr_d[i].adr); + codec_index = find_codec_info_part(part_id); + + if (codec_index < 0) + return codec_index; + + if (codec_info_list[codec_index].init) + codec_info_list[codec_index].init(link, dai_links, + &codec_info_list[codec_index], + playback); + } + + return 0; +} + +/* + * check endpoint status in slaves and gather link ID for all slaves in + * the same group to generate different CPU DAI. Now only support + * one sdw link with all slaves set with only single group id. + * + * one slave on one sdw link with aggregated = 0 + * one sdw BE DAI <---> one-cpu DAI <---> one-codec DAI + * + * two or more slaves on one sdw link with aggregated = 0 + * one sdw BE DAI <---> one-cpu DAI <---> multi-codec DAIs + * + * multiple links with multiple slaves with aggregated = 1 + * one sdw BE DAI <---> 1 .. N CPU DAIs <----> 1 .. N codec DAIs + */ +static int get_slave_info(const struct snd_soc_acpi_link_adr *adr_link, + struct device *dev, int *cpu_dai_id, int *cpu_dai_num, + int *codec_num, int *group_id, + bool *group_generated) +{ + const struct snd_soc_acpi_adr_device *adr_d; + const struct snd_soc_acpi_link_adr *adr_next; + bool no_aggregation; + int index = 0; + + no_aggregation = sof_sdw_quirk & SOF_SDW_NO_AGGREGATION; + *codec_num = adr_link->num_adr; + adr_d = adr_link->adr_d; + + /* make sure the link mask has a single bit set */ + if (!is_power_of_2(adr_link->mask)) + return -EINVAL; + + cpu_dai_id[index++] = ffs(adr_link->mask) - 1; + if (!adr_d->endpoints->aggregated || no_aggregation) { + *cpu_dai_num = 1; + *group_id = 0; + return 0; + } + + *group_id = adr_d->endpoints->group_id; + + /* gather other link ID of slaves in the same group */ + for (adr_next = adr_link + 1; adr_next && adr_next->num_adr; + adr_next++) { + const struct snd_soc_acpi_endpoint *endpoint; + + endpoint = adr_next->adr_d->endpoints; + if (!endpoint->aggregated || + endpoint->group_id != *group_id) + continue; + + /* make sure the link mask has a single bit set */ + if (!is_power_of_2(adr_next->mask)) + return -EINVAL; + + if (index >= SDW_MAX_CPU_DAIS) { + dev_err(dev, " cpu_dai_id array overflows"); + return -EINVAL; + } + + cpu_dai_id[index++] = ffs(adr_next->mask) - 1; + *codec_num += adr_next->num_adr; + } + + /* + * indicate CPU DAIs for this group have been generated + * to avoid generating CPU DAIs for this group again. + */ + group_generated[*group_id] = true; + *cpu_dai_num = index; + + return 0; +} + +static int create_sdw_dailink(struct device *dev, int *be_index, + struct snd_soc_dai_link *dai_links, + int sdw_be_num, int sdw_cpu_dai_num, + struct snd_soc_dai_link_component *cpus, + const struct snd_soc_acpi_link_adr *link, + int *cpu_id, bool *group_generated) +{ + const struct snd_soc_acpi_link_adr *link_next; + struct snd_soc_dai_link_component *codecs; + int cpu_dai_id[SDW_MAX_CPU_DAIS]; + int cpu_dai_num, cpu_dai_index; + unsigned int part_id, group_id; + int codec_idx = 0; + int i = 0, j = 0; + int codec_index; + int codec_num; + int stream; + int ret; + int k; + + ret = get_slave_info(link, dev, cpu_dai_id, &cpu_dai_num, &codec_num, + &group_id, group_generated); + if (ret) + return ret; + + codecs = devm_kcalloc(dev, codec_num, sizeof(*codecs), GFP_KERNEL); + if (!codecs) + return -ENOMEM; + + /* generate codec name on different links in the same group */ + for (link_next = link; link_next && link_next->num_adr && + i < cpu_dai_num; link_next++) { + const struct snd_soc_acpi_endpoint *endpoints; + + endpoints = link_next->adr_d->endpoints; + if (group_id && (!endpoints->aggregated || + endpoints->group_id != group_id)) + continue; + + /* skip the link excluded by this processed group */ + if (cpu_dai_id[i] != ffs(link_next->mask) - 1) + continue; + + ret = create_codec_dai_name(dev, link_next, codecs, codec_idx); + if (ret < 0) + return ret; + + /* check next link to create codec dai in the processed group */ + i++; + codec_idx += link_next->num_adr; + } + + /* find codec info to create BE DAI */ + part_id = SDW_PART_ID(link->adr_d[0].adr); + codec_index = find_codec_info_part(part_id); + if (codec_index < 0) + return codec_index; + + cpu_dai_index = *cpu_id; + for_each_pcm_streams(stream) { + char *name, *cpu_name; + int playback, capture; + static const char * const sdw_stream_name[] = { + "SDW%d-Playback", + "SDW%d-Capture", + }; + + if (!codec_info_list[codec_index].direction[stream]) + continue; + + /* create stream name according to first link id */ + name = devm_kasprintf(dev, GFP_KERNEL, + sdw_stream_name[stream], cpu_dai_id[0]); + if (!name) + return -ENOMEM; + + /* + * generate CPU DAI name base on the sdw link ID and + * PIN ID with offset of 2 according to sdw dai driver. + */ + for (k = 0; k < cpu_dai_num; k++) { + cpu_name = devm_kasprintf(dev, GFP_KERNEL, + "SDW%d Pin%d", cpu_dai_id[k], + j + SDW_INTEL_BIDIR_PDI_BASE); + if (!cpu_name) + return -ENOMEM; + + if (cpu_dai_index >= sdw_cpu_dai_num) { + dev_err(dev, "invalid cpu dai index %d", + cpu_dai_index); + return -EINVAL; + } + + cpus[cpu_dai_index++].dai_name = cpu_name; + } + + if (*be_index >= sdw_be_num) { + dev_err(dev, " invalid be dai index %d", *be_index); + return -EINVAL; + } + + if (*cpu_id >= sdw_cpu_dai_num) { + dev_err(dev, " invalid cpu dai index %d", *cpu_id); + return -EINVAL; + } + + playback = (stream == SNDRV_PCM_STREAM_PLAYBACK); + capture = (stream == SNDRV_PCM_STREAM_CAPTURE); + init_dai_link(dai_links + *be_index, *be_index, name, + playback, capture, + cpus + *cpu_id, cpu_dai_num, + codecs, codec_num, + NULL, &sdw_ops); + + ret = set_codec_init_func(link, dai_links + (*be_index)++, + playback); + if (ret < 0) { + dev_err(dev, "failed to init codec %d", codec_index); + return ret; + } + + *cpu_id += cpu_dai_num; + j++; + } + + return 0; +} + +/* + * DAI link ID of SSP & DMIC & HDMI are based on last + * link ID used by sdw link. Since be_id may be changed + * in init func of sdw codec, it is not equal to be_id + */ +static inline int get_next_be_id(struct snd_soc_dai_link *links, + int be_id) +{ + return links[be_id - 1].id + 1; +} + +static int sof_card_dai_links_create(struct device *dev, + struct snd_soc_acpi_mach *mach, + struct snd_soc_card *card) +{ + int ssp_num, sdw_be_num = 0, hdmi_num = 0, dmic_num; +#if IS_ENABLED(CONFIG_SND_SOC_SOF_HDA_AUDIO_CODEC) + struct snd_soc_dai_link_component *idisp_components; +#endif + struct snd_soc_dai_link_component *ssp_components; + struct snd_soc_acpi_mach_params *mach_params; + const struct snd_soc_acpi_link_adr *adr_link; + struct snd_soc_dai_link_component *cpus; + bool group_generated[SDW_MAX_GROUPS]; + int ssp_codec_index, ssp_mask; + struct snd_soc_dai_link *links; + int num_links, link_id = 0; + char *name, *cpu_name; + int total_cpu_dai_num; + int sdw_cpu_dai_num; + int i, j, be_id = 0; + int cpu_id = 0; + int comp_num; + int ret; + + /* reset amp_num to ensure amp_num++ starts from 0 in each probe */ + for (i = 0; i < ARRAY_SIZE(codec_info_list); i++) + codec_info_list[i].amp_num = 0; + +#if IS_ENABLED(CONFIG_SND_SOC_SOF_HDA_AUDIO_CODEC) + hdmi_num = sof_sdw_quirk & SOF_SDW_TGL_HDMI ? + SOF_TGL_HDMI_COUNT : SOF_PRE_TGL_HDMI_COUNT; +#endif + + ssp_mask = SOF_SSP_GET_PORT(sof_sdw_quirk); + /* + * on generic tgl platform, I2S or sdw mode is supported + * based on board rework. A ACPI device is registered in + * system only when I2S mode is supported, not sdw mode. + * Here check ACPI ID to confirm I2S is supported. + */ + ssp_codec_index = find_codec_info_acpi(mach->id); + ssp_num = ssp_codec_index >= 0 ? hweight_long(ssp_mask) : 0; + comp_num = hdmi_num + ssp_num; + + mach_params = &mach->mach_params; + ret = get_sdw_dailink_info(mach_params->links, + &sdw_be_num, &sdw_cpu_dai_num); + if (ret < 0) { + dev_err(dev, "failed to get sdw link info %d", ret); + return ret; + } + + /* enable dmic01 & dmic16k */ + dmic_num = (sof_sdw_quirk & SOF_SDW_PCH_DMIC) ? 2 : 0; + comp_num += dmic_num; + + dev_dbg(dev, "sdw %d, ssp %d, dmic %d, hdmi %d", sdw_be_num, ssp_num, + dmic_num, hdmi_num); + + /* allocate BE dailinks */ + num_links = comp_num + sdw_be_num; + links = devm_kcalloc(dev, num_links, sizeof(*links), GFP_KERNEL); + + /* allocated CPU DAIs */ + total_cpu_dai_num = comp_num + sdw_cpu_dai_num; + cpus = devm_kcalloc(dev, total_cpu_dai_num, sizeof(*cpus), + GFP_KERNEL); + + if (!links || !cpus) + return -ENOMEM; + + /* SDW */ + if (!sdw_be_num) + goto SSP; + + adr_link = mach_params->links; + if (!adr_link) + return -EINVAL; + + /* + * SoundWire Slaves aggregated in the same group may be + * located on different hardware links. Clear array to indicate + * CPU DAIs for this group have not been generated. + */ + for (i = 0; i < SDW_MAX_GROUPS; i++) + group_generated[i] = false; + + /* generate DAI links by each sdw link */ + for (; adr_link->num_adr; adr_link++) { + const struct snd_soc_acpi_endpoint *endpoint; + + endpoint = adr_link->adr_d->endpoints; + if (endpoint->aggregated && !endpoint->group_id) { + dev_err(dev, "invalid group id on link %x", + adr_link->mask); + continue; + } + + /* this group has been generated */ + if (endpoint->aggregated && + group_generated[endpoint->group_id]) + continue; + + ret = create_sdw_dailink(dev, &be_id, links, sdw_be_num, + sdw_cpu_dai_num, cpus, adr_link, + &cpu_id, group_generated); + if (ret < 0) { + dev_err(dev, "failed to create dai link %d", be_id); + return -ENOMEM; + } + } + + /* non-sdw DAI follows sdw DAI */ + link_id = be_id; + + /* get BE ID for non-sdw DAI */ + be_id = get_next_be_id(links, be_id); + +SSP: + /* SSP */ + if (!ssp_num) + goto DMIC; + + for (i = 0, j = 0; ssp_mask; i++, ssp_mask >>= 1) { + struct sof_sdw_codec_info *info; + int playback, capture; + char *codec_name; + + if (!(ssp_mask & 0x1)) + continue; + + name = devm_kasprintf(dev, GFP_KERNEL, + "SSP%d-Codec", i); + if (!name) + return -ENOMEM; + + cpu_name = devm_kasprintf(dev, GFP_KERNEL, "SSP%d Pin", i); + if (!cpu_name) + return -ENOMEM; + + ssp_components = devm_kzalloc(dev, sizeof(*ssp_components), + GFP_KERNEL); + if (!ssp_components) + return -ENOMEM; + + info = &codec_info_list[ssp_codec_index]; + codec_name = devm_kasprintf(dev, GFP_KERNEL, "i2c-%s:0%d", + info->acpi_id, j++); + if (!codec_name) + return -ENOMEM; + + ssp_components->name = codec_name; + ssp_components->dai_name = info->dai_name; + cpus[cpu_id].dai_name = cpu_name; + + playback = info->direction[SNDRV_PCM_STREAM_PLAYBACK]; + capture = info->direction[SNDRV_PCM_STREAM_CAPTURE]; + init_dai_link(links + link_id, be_id, name, + playback, capture, + cpus + cpu_id, 1, + ssp_components, 1, + NULL, info->ops); + + ret = info->init(NULL, links + link_id, info, 0); + if (ret < 0) + return ret; + + INC_ID(be_id, cpu_id, link_id); + } + +DMIC: + /* dmic */ + if (dmic_num > 0) { + cpus[cpu_id].dai_name = "DMIC01 Pin"; + init_dai_link(links + link_id, be_id, "dmic01", + 0, 1, // DMIC only supports capture + cpus + cpu_id, 1, + dmic_component, 1, + sof_sdw_dmic_init, NULL); + INC_ID(be_id, cpu_id, link_id); + + cpus[cpu_id].dai_name = "DMIC16k Pin"; + init_dai_link(links + link_id, be_id, "dmic16k", + 0, 1, // DMIC only supports capture + cpus + cpu_id, 1, + dmic_component, 1, + /* don't call sof_sdw_dmic_init() twice */ + NULL, NULL); + INC_ID(be_id, cpu_id, link_id); + } + +#if IS_ENABLED(CONFIG_SND_SOC_SOF_HDA_AUDIO_CODEC) + /* HDMI */ + if (hdmi_num > 0) { + idisp_components = devm_kcalloc(dev, hdmi_num, + sizeof(*idisp_components), + GFP_KERNEL); + if (!idisp_components) + return -ENOMEM; + } + + for (i = 0; i < hdmi_num; i++) { + name = devm_kasprintf(dev, GFP_KERNEL, + "iDisp%d", i + 1); + if (!name) + return -ENOMEM; + + idisp_components[i].name = "ehdaudio0D2"; + idisp_components[i].dai_name = devm_kasprintf(dev, + GFP_KERNEL, + "intel-hdmi-hifi%d", + i + 1); + if (!idisp_components[i].dai_name) + return -ENOMEM; + + cpu_name = devm_kasprintf(dev, GFP_KERNEL, + "iDisp%d Pin", i + 1); + if (!cpu_name) + return -ENOMEM; + + cpus[cpu_id].dai_name = cpu_name; + init_dai_link(links + link_id, be_id, name, + 1, 0, // HDMI only supports playback + cpus + cpu_id, 1, + idisp_components + i, 1, + sof_sdw_hdmi_init, NULL); + INC_ID(be_id, cpu_id, link_id); + } +#endif + + card->dai_link = links; + card->num_links = num_links; + + return 0; +} + +/* SoC card */ +static const char sdw_card_long_name[] = "Intel Soundwire SOF"; + +static struct snd_soc_card card_sof_sdw = { + .name = "soundwire", + .late_probe = sof_sdw_hdmi_card_late_probe, + .codec_conf = codec_conf, + .num_configs = ARRAY_SIZE(codec_conf), +}; + +static int mc_probe(struct platform_device *pdev) +{ + struct snd_soc_card *card = &card_sof_sdw; + struct snd_soc_acpi_mach *mach; + struct mc_private *ctx; + int ret; + + dev_dbg(&pdev->dev, "Entry %s\n", __func__); + + ctx = devm_kzalloc(&pdev->dev, sizeof(*ctx), GFP_KERNEL); + if (!ctx) + return -ENOMEM; + + dmi_check_system(sof_sdw_quirk_table); + +#if IS_ENABLED(CONFIG_SND_SOC_SOF_HDA_AUDIO_CODEC) + INIT_LIST_HEAD(&ctx->hdmi_pcm_list); +#endif + + card->dev = &pdev->dev; + + mach = pdev->dev.platform_data; + ret = sof_card_dai_links_create(&pdev->dev, mach, + card); + if (ret < 0) + return ret; + + ctx->common_hdmi_codec_drv = mach->mach_params.common_hdmi_codec_drv; + + snd_soc_card_set_drvdata(card, ctx); + + card->components = devm_kasprintf(card->dev, GFP_KERNEL, + "cfg-spk:%d", + (sof_sdw_quirk & SOF_SDW_FOUR_SPK) ? 4 : 2); + if (!card->components) + return -ENOMEM; + + card->long_name = sdw_card_long_name; + + /* Register the card */ + ret = devm_snd_soc_register_card(&pdev->dev, card); + if (ret) { + dev_err(card->dev, "snd_soc_register_card failed %d\n", ret); + return ret; + } + + platform_set_drvdata(pdev, card); + + return ret; +} + +static struct platform_driver sof_sdw_driver = { + .driver = { + .name = "sof_sdw", + .pm = &snd_soc_pm_ops, + }, + .probe = mc_probe, +}; + +module_platform_driver(sof_sdw_driver); + +MODULE_DESCRIPTION("ASoC SoundWire Generic Machine driver"); +MODULE_AUTHOR("Bard Liao <yung-chuan.liao@linux.intel.com>"); +MODULE_AUTHOR("Rander Wang <rander.wang@linux.intel.com>"); +MODULE_AUTHOR("Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>"); +MODULE_LICENSE("GPL v2"); +MODULE_ALIAS("platform:sof_sdw"); diff --git a/sound/soc/intel/boards/sof_sdw_common.h b/sound/soc/intel/boards/sof_sdw_common.h new file mode 100644 index 000000000000..dd593ff3575b --- /dev/null +++ b/sound/soc/intel/boards/sof_sdw_common.h @@ -0,0 +1,114 @@ +/* SPDX-License-Identifier: GPL-2.0 + * Copyright (c) 2020 Intel Corporation + */ + +/* + * sof_sdw_common.h - prototypes for common helpers + */ + +#ifndef SND_SOC_SOF_SDW_COMMON_H +#define SND_SOC_SOF_SDW_COMMON_H + +#include <linux/bits.h> +#include <linux/types.h> + +#define MAX_NO_PROPS 2 +#define MAX_HDMI_NUM 4 +#define SDW_DMIC_DAI_ID 4 +#define SDW_MAX_CPU_DAIS 16 +#define SDW_INTEL_BIDIR_PDI_BASE 2 + +/* 8 combinations with 4 links + unused group 0 */ +#define SDW_MAX_GROUPS 9 + +enum { + SOF_RT711_JD_SRC_JD1 = 1, + SOF_RT711_JD_SRC_JD2 = 2, +}; + +enum { + SOF_PRE_TGL_HDMI_COUNT = 3, + SOF_TGL_HDMI_COUNT = 4, +}; + +enum { + SOF_I2S_SSP0 = BIT(0), + SOF_I2S_SSP1 = BIT(1), + SOF_I2S_SSP2 = BIT(2), + SOF_I2S_SSP3 = BIT(3), + SOF_I2S_SSP4 = BIT(4), + SOF_I2S_SSP5 = BIT(5), +}; + +#define SOF_RT711_JDSRC(quirk) ((quirk) & GENMASK(1, 0)) +#define SOF_SDW_FOUR_SPK BIT(2) +#define SOF_SDW_TGL_HDMI BIT(3) +#define SOF_SDW_PCH_DMIC BIT(4) +#define SOF_SSP_PORT(x) (((x) & GENMASK(5, 0)) << 5) +#define SOF_SSP_GET_PORT(quirk) (((quirk) >> 5) & GENMASK(5, 0)) +#define SOF_RT715_DAI_ID_FIX BIT(11) +#define SOF_SDW_NO_AGGREGATION BIT(12) + +struct sof_sdw_codec_info { + const int id; + int amp_num; + const u8 acpi_id[ACPI_ID_LEN]; + const bool direction[2]; // playback & capture support + const char *dai_name; + const struct snd_soc_ops *ops; + + int (*init)(const struct snd_soc_acpi_link_adr *link, + struct snd_soc_dai_link *dai_links, + struct sof_sdw_codec_info *info, + bool playback); +}; + +struct mc_private { + struct list_head hdmi_pcm_list; + bool common_hdmi_codec_drv; + struct snd_soc_jack sdw_headset; +}; + +extern unsigned long sof_sdw_quirk; + +/* generic HDMI support */ +int sof_sdw_hdmi_init(struct snd_soc_pcm_runtime *rtd); + +int sof_sdw_hdmi_card_late_probe(struct snd_soc_card *card); + +/* DMIC support */ +int sof_sdw_dmic_init(struct snd_soc_pcm_runtime *rtd); + +/* RT711 support */ +int sof_sdw_rt711_init(const struct snd_soc_acpi_link_adr *link, + struct snd_soc_dai_link *dai_links, + struct sof_sdw_codec_info *info, + bool playback); + +/* RT700 support */ +int sof_sdw_rt700_init(const struct snd_soc_acpi_link_adr *link, + struct snd_soc_dai_link *dai_links, + struct sof_sdw_codec_info *info, + bool playback); + +/* RT1308 support */ +extern struct snd_soc_ops sof_sdw_rt1308_i2s_ops; + +int sof_sdw_rt1308_init(const struct snd_soc_acpi_link_adr *link, + struct snd_soc_dai_link *dai_links, + struct sof_sdw_codec_info *info, + bool playback); + +/* RT715 support */ +int sof_sdw_rt715_init(const struct snd_soc_acpi_link_adr *link, + struct snd_soc_dai_link *dai_links, + struct sof_sdw_codec_info *info, + bool playback); + +/* RT5682 support */ +int sof_sdw_rt5682_init(const struct snd_soc_acpi_link_adr *link, + struct snd_soc_dai_link *dai_links, + struct sof_sdw_codec_info *info, + bool playback); + +#endif diff --git a/sound/soc/intel/boards/sof_sdw_dmic.c b/sound/soc/intel/boards/sof_sdw_dmic.c new file mode 100644 index 000000000000..e92176bf0ad4 --- /dev/null +++ b/sound/soc/intel/boards/sof_sdw_dmic.c @@ -0,0 +1,42 @@ +// SPDX-License-Identifier: GPL-2.0 +// Copyright (c) 2020 Intel Corporation + +/* + * sof_sdw_dmic - Helpers to handle dmic from generic machine driver + */ + +#include <sound/soc.h> +#include <sound/soc-acpi.h> +#include "sof_sdw_common.h" + +static const struct snd_soc_dapm_widget dmic_widgets[] = { + SND_SOC_DAPM_MIC("SoC DMIC", NULL), +}; + +static const struct snd_soc_dapm_route dmic_map[] = { + /* digital mics */ + {"DMic", NULL, "SoC DMIC"}, +}; + +int sof_sdw_dmic_init(struct snd_soc_pcm_runtime *rtd) +{ + struct snd_soc_card *card = rtd->card; + int ret; + + ret = snd_soc_dapm_new_controls(&card->dapm, dmic_widgets, + ARRAY_SIZE(dmic_widgets)); + if (ret) { + dev_err(card->dev, "DMic widget addition failed: %d\n", ret); + /* Don't need to add routes if widget addition failed */ + return ret; + } + + ret = snd_soc_dapm_add_routes(&card->dapm, dmic_map, + ARRAY_SIZE(dmic_map)); + + if (ret) + dev_err(card->dev, "DMic map addition failed: %d\n", ret); + + return ret; +} + diff --git a/sound/soc/intel/boards/sof_sdw_hdmi.c b/sound/soc/intel/boards/sof_sdw_hdmi.c new file mode 100644 index 000000000000..c7b5612a39e6 --- /dev/null +++ b/sound/soc/intel/boards/sof_sdw_hdmi.c @@ -0,0 +1,97 @@ +// SPDX-License-Identifier: GPL-2.0 +// Copyright (c) 2020 Intel Corporation + +/* + * sof_sdw_hdmi - Helpers to handle HDMI from generic machine driver + */ + +#include <linux/device.h> +#include <linux/errno.h> +#include <linux/kernel.h> +#include <linux/list.h> +#include <sound/soc.h> +#include <sound/soc-acpi.h> +#include <sound/jack.h> +#include "sof_sdw_common.h" +#include "../../codecs/hdac_hdmi.h" +#include "hda_dsp_common.h" + +#if IS_ENABLED(CONFIG_SND_SOC_SOF_HDA_AUDIO_CODEC) +static struct snd_soc_jack hdmi[MAX_HDMI_NUM]; + +struct hdmi_pcm { + struct list_head head; + struct snd_soc_dai *codec_dai; + int device; +}; + +int sof_sdw_hdmi_init(struct snd_soc_pcm_runtime *rtd) +{ + struct mc_private *ctx = snd_soc_card_get_drvdata(rtd->card); + struct snd_soc_dai *dai = rtd->codec_dai; + struct 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 NAME_SIZE 32 +int sof_sdw_hdmi_card_late_probe(struct snd_soc_card *card) +{ + struct mc_private *ctx = snd_soc_card_get_drvdata(card); + struct hdmi_pcm *pcm; + struct snd_soc_component *component = NULL; + int err, i = 0; + char jack_name[NAME_SIZE]; + + pcm = list_first_entry(&ctx->hdmi_pcm_list, struct hdmi_pcm, + head); + component = pcm->codec_dai->component; + + if (ctx->common_hdmi_codec_drv) + 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, &hdmi[i], + NULL, 0); + + if (err) + return err; + + err = snd_jack_add_new_kctl(hdmi[i].jack, + jack_name, SND_JACK_AVOUT); + if (err) + dev_warn(component->dev, "failed creating Jack kctl\n"); + + err = hdac_hdmi_jack_init(pcm->codec_dai, pcm->device, + &hdmi[i]); + if (err < 0) + return err; + + i++; + } + + if (!component) + return -EINVAL; + + return hdac_hdmi_jack_port_init(component, &card->dapm); +} +#else +int hdmi_card_late_probe(struct snd_soc_card *card) +{ + return 0; +} +#endif diff --git a/sound/soc/intel/boards/sof_sdw_rt1308.c b/sound/soc/intel/boards/sof_sdw_rt1308.c new file mode 100644 index 000000000000..321768e54d08 --- /dev/null +++ b/sound/soc/intel/boards/sof_sdw_rt1308.c @@ -0,0 +1,151 @@ +// SPDX-License-Identifier: GPL-2.0 +// Copyright (c) 2020 Intel Corporation + +/* + * sof_sdw_rt1308 - Helpers to handle RT1308 from generic machine driver + */ + +#include <linux/device.h> +#include <linux/errno.h> +#include <sound/soc.h> +#include <sound/soc-acpi.h> +#include "sof_sdw_common.h" +#include "../../codecs/rt1308.h" + +static const struct snd_soc_dapm_widget rt1308_widgets[] = { + SND_SOC_DAPM_SPK("Speaker", NULL), +}; + +/* + * dapm routes for rt1308 will be registered dynamically according + * to the number of rt1308 used. The first two entries will be registered + * for one codec case, and the last two entries are also registered + * if two 1308s are used. + */ +static const struct snd_soc_dapm_route rt1308_map[] = { + { "Speaker", NULL, "rt1308-1 SPOL" }, + { "Speaker", NULL, "rt1308-1 SPOR" }, + { "Speaker", NULL, "rt1308-2 SPOL" }, + { "Speaker", NULL, "rt1308-2 SPOR" }, +}; + +static const struct snd_kcontrol_new rt1308_controls[] = { + SOC_DAPM_PIN_SWITCH("Speaker"), +}; + +static int first_spk_init(struct snd_soc_pcm_runtime *rtd) +{ + struct snd_soc_card *card = rtd->card; + int ret; + + card->components = devm_kasprintf(card->dev, GFP_KERNEL, + "%s spk:rt1308", + card->components); + if (!card->components) + return -ENOMEM; + + ret = snd_soc_add_card_controls(card, rt1308_controls, + ARRAY_SIZE(rt1308_controls)); + if (ret) { + dev_err(card->dev, "rt1308 controls addition failed: %d\n", ret); + return ret; + } + + ret = snd_soc_dapm_new_controls(&card->dapm, rt1308_widgets, + ARRAY_SIZE(rt1308_widgets)); + if (ret) { + dev_err(card->dev, "rt1308 widgets addition failed: %d\n", ret); + return ret; + } + + ret = snd_soc_dapm_add_routes(&card->dapm, rt1308_map, 2); + if (ret) + dev_err(rtd->dev, "failed to add first SPK map: %d\n", ret); + + return ret; +} + +static int second_spk_init(struct snd_soc_pcm_runtime *rtd) +{ + struct snd_soc_card *card = rtd->card; + int ret; + + ret = snd_soc_dapm_add_routes(&card->dapm, rt1308_map + 2, 2); + if (ret) + dev_err(rtd->dev, "failed to add second SPK map: %d\n", ret); + + return ret; +} + +static int all_spk_init(struct snd_soc_pcm_runtime *rtd) +{ + int ret; + + ret = first_spk_init(rtd); + if (ret) + return ret; + + return second_spk_init(rtd); +} + +static int rt1308_i2s_hw_params(struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *params) +{ + struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_card *card = rtd->card; + struct snd_soc_dai *codec_dai = rtd->codec_dai; + int clk_id, clk_freq, pll_out; + int err; + + clk_id = RT1308_PLL_S_MCLK; + clk_freq = 38400000; + + pll_out = params_rate(params) * 512; + + /* Set rt1308 pll */ + err = snd_soc_dai_set_pll(codec_dai, 0, clk_id, clk_freq, pll_out); + if (err < 0) { + dev_err(card->dev, "Failed to set RT1308 PLL: %d\n", err); + return err; + } + + /* Set rt1308 sysclk */ + err = snd_soc_dai_set_sysclk(codec_dai, RT1308_FS_SYS_S_PLL, pll_out, + SND_SOC_CLOCK_IN); + if (err < 0) { + dev_err(card->dev, "Failed to set RT1308 SYSCLK: %d\n", err); + return err; + } + + return 0; +} + +/* machine stream operations */ +struct snd_soc_ops sof_sdw_rt1308_i2s_ops = { + .hw_params = rt1308_i2s_hw_params, +}; + +int sof_sdw_rt1308_init(const struct snd_soc_acpi_link_adr *link, + struct snd_soc_dai_link *dai_links, + struct sof_sdw_codec_info *info, + bool playback) +{ + info->amp_num++; + if (info->amp_num == 1) + dai_links->init = first_spk_init; + + if (info->amp_num == 2) { + /* + * if two 1308s are in one dai link, the init function + * in this dai link will be first set for the first speaker, + * and it should be reset to initialize all speakers when + * the second speaker is found. + */ + if (dai_links->init) + dai_links->init = all_spk_init; + else + dai_links->init = second_spk_init; + } + + return 0; +} diff --git a/sound/soc/intel/boards/sof_sdw_rt5682.c b/sound/soc/intel/boards/sof_sdw_rt5682.c new file mode 100644 index 000000000000..5aa6211a1ed9 --- /dev/null +++ b/sound/soc/intel/boards/sof_sdw_rt5682.c @@ -0,0 +1,126 @@ +// SPDX-License-Identifier: GPL-2.0 +// Copyright (c) 2020 Intel Corporation + +/* + * sof_sdw_rt5682 - Helpers to handle RT5682 from generic machine driver + */ + +#include <linux/device.h> +#include <linux/errno.h> +#include <linux/input.h> +#include <linux/soundwire/sdw.h> +#include <linux/soundwire/sdw_type.h> +#include <sound/soc.h> +#include <sound/soc-acpi.h> +#include <sound/jack.h> +#include "sof_sdw_common.h" + +static const struct snd_soc_dapm_widget rt5682_widgets[] = { + SND_SOC_DAPM_HP("Headphone", NULL), + SND_SOC_DAPM_MIC("Headset Mic", NULL), +}; + +static const struct snd_soc_dapm_route rt5682_map[] = { + /*Headphones*/ + { "Headphone", NULL, "rt5682 HPOL" }, + { "Headphone", NULL, "rt5682 HPOR" }, + { "rt5682 IN1P", NULL, "Headset Mic" }, +}; + +static const struct snd_kcontrol_new rt5682_controls[] = { + SOC_DAPM_PIN_SWITCH("Headphone"), + SOC_DAPM_PIN_SWITCH("Headset Mic"), +}; + +static struct snd_soc_jack_pin rt5682_jack_pins[] = { + { + .pin = "Headphone", + .mask = SND_JACK_HEADPHONE, + }, + { + .pin = "Headset Mic", + .mask = SND_JACK_MICROPHONE, + }, +}; + +static int rt5682_rtd_init(struct snd_soc_pcm_runtime *rtd) +{ + struct snd_soc_card *card = rtd->card; + struct mc_private *ctx = snd_soc_card_get_drvdata(card); + struct snd_soc_component *component = rtd->codec_dai->component; + struct snd_soc_jack *jack; + int ret; + + card->components = devm_kasprintf(card->dev, GFP_KERNEL, + "%s hs:rt5682", + card->components); + if (!card->components) + return -ENOMEM; + + ret = snd_soc_add_card_controls(card, rt5682_controls, + ARRAY_SIZE(rt5682_controls)); + if (ret) { + dev_err(card->dev, "rt5682 control addition failed: %d\n", ret); + return ret; + } + + ret = snd_soc_dapm_new_controls(&card->dapm, rt5682_widgets, + ARRAY_SIZE(rt5682_widgets)); + if (ret) { + dev_err(card->dev, "rt5682 widgets addition failed: %d\n", ret); + return ret; + } + + ret = snd_soc_dapm_add_routes(&card->dapm, rt5682_map, + ARRAY_SIZE(rt5682_map)); + + if (ret) { + dev_err(card->dev, "rt5682 map addition failed: %d\n", ret); + return ret; + } + + ret = snd_soc_card_jack_new(rtd->card, "Headset Jack", + SND_JACK_HEADSET | SND_JACK_BTN_0 | + SND_JACK_BTN_1 | SND_JACK_BTN_2 | + SND_JACK_BTN_3, + &ctx->sdw_headset, + rt5682_jack_pins, + ARRAY_SIZE(rt5682_jack_pins)); + if (ret) { + dev_err(rtd->card->dev, "Headset Jack creation failed: %d\n", + ret); + return ret; + } + + jack = &ctx->sdw_headset; + + snd_jack_set_key(jack->jack, SND_JACK_BTN_0, KEY_PLAYPAUSE); + snd_jack_set_key(jack->jack, SND_JACK_BTN_1, KEY_VOICECOMMAND); + snd_jack_set_key(jack->jack, SND_JACK_BTN_2, KEY_VOLUMEUP); + snd_jack_set_key(jack->jack, SND_JACK_BTN_3, KEY_VOLUMEDOWN); + + ret = snd_soc_component_set_jack(component, jack, NULL); + + if (ret) + dev_err(rtd->card->dev, "Headset Jack call-back failed: %d\n", + ret); + + return ret; +} + +int sof_sdw_rt5682_init(const struct snd_soc_acpi_link_adr *link, + struct snd_soc_dai_link *dai_links, + struct sof_sdw_codec_info *info, + bool playback) +{ + /* + * headset should be initialized once. + * Do it with dai link for playback. + */ + if (!playback) + return 0; + + dai_links->init = rt5682_rtd_init; + + return 0; +} diff --git a/sound/soc/intel/boards/sof_sdw_rt700.c b/sound/soc/intel/boards/sof_sdw_rt700.c new file mode 100644 index 000000000000..2ee4e6910d7f --- /dev/null +++ b/sound/soc/intel/boards/sof_sdw_rt700.c @@ -0,0 +1,125 @@ +// SPDX-License-Identifier: GPL-2.0 +// Copyright (c) 2020 Intel Corporation + +/* + * sof_sdw_rt700 - Helpers to handle RT700 from generic machine driver + */ + +#include <linux/device.h> +#include <linux/errno.h> +#include <linux/input.h> +#include <sound/soc.h> +#include <sound/soc-acpi.h> +#include <sound/jack.h> +#include "sof_sdw_common.h" + +static const struct snd_soc_dapm_widget rt700_widgets[] = { + SND_SOC_DAPM_HP("Headphones", NULL), + SND_SOC_DAPM_MIC("AMIC", NULL), + SND_SOC_DAPM_SPK("Speaker", NULL), +}; + +static const struct snd_soc_dapm_route rt700_map[] = { + /* Headphones */ + { "Headphones", NULL, "HP" }, + { "Speaker", NULL, "SPK" }, + { "MIC2", NULL, "AMIC" }, +}; + +static const struct snd_kcontrol_new rt700_controls[] = { + SOC_DAPM_PIN_SWITCH("Headphones"), + SOC_DAPM_PIN_SWITCH("AMIC"), + SOC_DAPM_PIN_SWITCH("Speaker"), +}; + +static struct snd_soc_jack_pin rt700_jack_pins[] = { + { + .pin = "Headphones", + .mask = SND_JACK_HEADPHONE, + }, + { + .pin = "AMIC", + .mask = SND_JACK_MICROPHONE, + }, +}; + +static int rt700_rtd_init(struct snd_soc_pcm_runtime *rtd) +{ + struct snd_soc_card *card = rtd->card; + struct mc_private *ctx = snd_soc_card_get_drvdata(card); + struct snd_soc_component *component = rtd->codec_dai->component; + struct snd_soc_jack *jack; + int ret; + + card->components = devm_kasprintf(card->dev, GFP_KERNEL, + "%s hs:rt700", + card->components); + if (!card->components) + return -ENOMEM; + + ret = snd_soc_add_card_controls(card, rt700_controls, + ARRAY_SIZE(rt700_controls)); + if (ret) { + dev_err(card->dev, "rt700 controls addition failed: %d\n", ret); + return ret; + } + + ret = snd_soc_dapm_new_controls(&card->dapm, rt700_widgets, + ARRAY_SIZE(rt700_widgets)); + if (ret) { + dev_err(card->dev, "rt700 widgets addition failed: %d\n", ret); + return ret; + } + + ret = snd_soc_dapm_add_routes(&card->dapm, rt700_map, + ARRAY_SIZE(rt700_map)); + + if (ret) { + dev_err(card->dev, "rt700 map addition failed: %d\n", ret); + return ret; + } + + ret = snd_soc_card_jack_new(rtd->card, "Headset Jack", + SND_JACK_HEADSET | SND_JACK_BTN_0 | + SND_JACK_BTN_1 | SND_JACK_BTN_2 | + SND_JACK_BTN_3, + &ctx->sdw_headset, + rt700_jack_pins, + ARRAY_SIZE(rt700_jack_pins)); + if (ret) { + dev_err(rtd->card->dev, "Headset Jack creation failed: %d\n", + ret); + return ret; + } + + jack = &ctx->sdw_headset; + + snd_jack_set_key(jack->jack, SND_JACK_BTN_0, KEY_VOLUMEUP); + snd_jack_set_key(jack->jack, SND_JACK_BTN_1, KEY_PLAYPAUSE); + snd_jack_set_key(jack->jack, SND_JACK_BTN_2, KEY_VOLUMEDOWN); + snd_jack_set_key(jack->jack, SND_JACK_BTN_3, KEY_VOICECOMMAND); + + ret = snd_soc_component_set_jack(component, jack, NULL); + if (ret) + dev_err(rtd->card->dev, "Headset Jack call-back failed: %d\n", + ret); + + return ret; +} + +int sof_sdw_rt700_init(const struct snd_soc_acpi_link_adr *link, + struct snd_soc_dai_link *dai_links, + struct sof_sdw_codec_info *info, + bool playback) +{ + /* + * headset should be initialized once. + * Do it with dai link for playback. + */ + if (!playback) + return 0; + + dai_links->init = rt700_rtd_init; + + return 0; +} diff --git a/sound/soc/intel/boards/sof_sdw_rt711.c b/sound/soc/intel/boards/sof_sdw_rt711.c new file mode 100644 index 000000000000..2a4917e3d561 --- /dev/null +++ b/sound/soc/intel/boards/sof_sdw_rt711.c @@ -0,0 +1,156 @@ +// SPDX-License-Identifier: GPL-2.0 +// Copyright (c) 2020 Intel Corporation + +/* + * sof_sdw_rt711 - Helpers to handle RT711 from generic machine driver + */ + +#include <linux/device.h> +#include <linux/errno.h> +#include <linux/input.h> +#include <linux/soundwire/sdw.h> +#include <linux/soundwire/sdw_type.h> +#include <sound/soc.h> +#include <sound/soc-acpi.h> +#include <sound/jack.h> +#include "sof_sdw_common.h" + +/* + * Note this MUST be called before snd_soc_register_card(), so that the props + * are in place before the codec component driver's probe function parses them. + */ +static int rt711_add_codec_device_props(const char *sdw_dev_name) +{ + struct property_entry props[MAX_NO_PROPS] = {}; + struct device *sdw_dev; + int ret; + + sdw_dev = bus_find_device_by_name(&sdw_bus_type, NULL, sdw_dev_name); + if (!sdw_dev) + return -EPROBE_DEFER; + + if (SOF_RT711_JDSRC(sof_sdw_quirk)) { + props[0] = PROPERTY_ENTRY_U32("realtek,jd-src", + SOF_RT711_JDSRC(sof_sdw_quirk)); + } + + ret = device_add_properties(sdw_dev, props); + put_device(sdw_dev); + + return ret; +} + +static const struct snd_soc_dapm_widget rt711_widgets[] = { + SND_SOC_DAPM_HP("Headphone", NULL), + SND_SOC_DAPM_MIC("Headset Mic", NULL), +}; + +static const struct snd_soc_dapm_route rt711_map[] = { + /* Headphones */ + { "Headphone", NULL, "rt711 HP" }, + { "rt711 MIC2", NULL, "Headset Mic" }, +}; + +static const struct snd_kcontrol_new rt711_controls[] = { + SOC_DAPM_PIN_SWITCH("Headphone"), + SOC_DAPM_PIN_SWITCH("Headset Mic"), +}; + +static struct snd_soc_jack_pin rt711_jack_pins[] = { + { + .pin = "Headphone", + .mask = SND_JACK_HEADPHONE, + }, + { + .pin = "Headset Mic", + .mask = SND_JACK_MICROPHONE, + }, +}; + +static int rt711_rtd_init(struct snd_soc_pcm_runtime *rtd) +{ + struct snd_soc_card *card = rtd->card; + struct mc_private *ctx = snd_soc_card_get_drvdata(card); + struct snd_soc_component *component = rtd->codec_dai->component; + struct snd_soc_jack *jack; + int ret; + + card->components = devm_kasprintf(card->dev, GFP_KERNEL, + "%s hs:rt711", + card->components); + if (!card->components) + return -ENOMEM; + + ret = snd_soc_add_card_controls(card, rt711_controls, + ARRAY_SIZE(rt711_controls)); + if (ret) { + dev_err(card->dev, "rt711 controls addition failed: %d\n", ret); + return ret; + } + + ret = snd_soc_dapm_new_controls(&card->dapm, rt711_widgets, + ARRAY_SIZE(rt711_widgets)); + if (ret) { + dev_err(card->dev, "rt711 widgets addition failed: %d\n", ret); + return ret; + } + + ret = snd_soc_dapm_add_routes(&card->dapm, rt711_map, + ARRAY_SIZE(rt711_map)); + + if (ret) { + dev_err(card->dev, "rt711 map addition failed: %d\n", ret); + return ret; + } + + ret = snd_soc_card_jack_new(rtd->card, "Headset Jack", + SND_JACK_HEADSET | SND_JACK_BTN_0 | + SND_JACK_BTN_1 | SND_JACK_BTN_2 | + SND_JACK_BTN_3, + &ctx->sdw_headset, + rt711_jack_pins, + ARRAY_SIZE(rt711_jack_pins)); + if (ret) { + dev_err(rtd->card->dev, "Headset Jack creation failed: %d\n", + ret); + return ret; + } + + jack = &ctx->sdw_headset; + + snd_jack_set_key(jack->jack, SND_JACK_BTN_0, KEY_VOLUMEUP); + snd_jack_set_key(jack->jack, SND_JACK_BTN_1, KEY_PLAYPAUSE); + snd_jack_set_key(jack->jack, SND_JACK_BTN_2, KEY_VOLUMEDOWN); + snd_jack_set_key(jack->jack, SND_JACK_BTN_3, KEY_VOICECOMMAND); + + ret = snd_soc_component_set_jack(component, jack, NULL); + + if (ret) + dev_err(rtd->card->dev, "Headset Jack call-back failed: %d\n", + ret); + + return ret; +} + +int sof_sdw_rt711_init(const struct snd_soc_acpi_link_adr *link, + struct snd_soc_dai_link *dai_links, + struct sof_sdw_codec_info *info, + bool playback) +{ + int ret; + + /* + * headset should be initialized once. + * Do it with dai link for playback. + */ + if (!playback) + return 0; + + ret = rt711_add_codec_device_props("sdw:0:25d:711:0"); + if (ret < 0) + return ret; + + dai_links->init = rt711_rtd_init; + + return 0; +} diff --git a/sound/soc/intel/boards/sof_sdw_rt715.c b/sound/soc/intel/boards/sof_sdw_rt715.c new file mode 100644 index 000000000000..321e1cbc03ed --- /dev/null +++ b/sound/soc/intel/boards/sof_sdw_rt715.c @@ -0,0 +1,42 @@ +// SPDX-License-Identifier: GPL-2.0 +// Copyright (c) 2020 Intel Corporation + +/* + * sof_sdw_rt715 - Helpers to handle RT715 from generic machine driver + */ + +#include <linux/device.h> +#include <linux/errno.h> +#include <sound/soc.h> +#include <sound/soc-acpi.h> +#include "sof_sdw_common.h" + +static int rt715_rtd_init(struct snd_soc_pcm_runtime *rtd) +{ + struct snd_soc_card *card = rtd->card; + + card->components = devm_kasprintf(card->dev, GFP_KERNEL, + "%s mic:rt715", + card->components); + if (!card->components) + return -ENOMEM; + + return 0; +} + +int sof_sdw_rt715_init(const struct snd_soc_acpi_link_adr *link, + struct snd_soc_dai_link *dai_links, + struct sof_sdw_codec_info *info, + bool playback) +{ + /* + * DAI ID is fixed at SDW_DMIC_DAI_ID for 715 to + * keep sdw DMIC and HDMI setting static in UCM + */ + if (sof_sdw_quirk & SOF_RT715_DAI_ID_FIX) + dai_links->id = SDW_DMIC_DAI_ID; + + dai_links->init = rt715_rtd_init; + + return 0; +} |