This configuration supports JSL boards which implement ALC5650 dual I2S interface codec. Two DAI links are added: AIF1 (on codec side) for headphone and AIF2 for speakers. Signed-off-by: Brent Lu <brent.lu@xxxxxxxxx> --- sound/soc/intel/boards/Kconfig | 5 +- sound/soc/intel/boards/sof_rt5682.c | 80 ++++++++++++++++++- .../intel/common/soc-acpi-intel-jsl-match.c | 12 +++ 3 files changed, 93 insertions(+), 4 deletions(-) diff --git a/sound/soc/intel/boards/Kconfig b/sound/soc/intel/boards/Kconfig index f472f603ab75..1fe830af2b84 100644 --- a/sound/soc/intel/boards/Kconfig +++ b/sound/soc/intel/boards/Kconfig @@ -475,7 +475,7 @@ endif ## SND_SOC_INTEL_SKYLAKE_HDAUDIO_CODEC || SND_SOC_SOF_HDA_AUDIO_CODEC if SND_SOC_SOF_HDA_LINK || SND_SOC_SOF_BAYTRAIL config SND_SOC_INTEL_SOF_RT5682_MACH - tristate "SOF with rt5682 codec in I2S Mode" + tristate "SOF with rt5650/rt5682 codec in I2S Mode" depends on I2C && ACPI depends on ((SND_HDA_CODEC_HDMI && SND_SOC_SOF_HDA_AUDIO_CODEC) &&\ (MFD_INTEL_LPSS || COMPILE_TEST)) ||\ @@ -485,6 +485,7 @@ config SND_SOC_INTEL_SOF_RT5682_MACH select SND_SOC_RT1011 select SND_SOC_RT1015 select SND_SOC_RT1015P + select SND_SOC_RT5645 select SND_SOC_RT5682_I2C select SND_SOC_RT5682S select SND_SOC_DMIC @@ -494,7 +495,7 @@ config SND_SOC_INTEL_SOF_RT5682_MACH select SND_SOC_INTEL_SOF_REALTEK_COMMON help This adds support for ASoC machine driver for SOF platforms - with rt5682 codec. + with rt5650 or rt5682 codec. Say Y if you have such a device. If unsure select "N". diff --git a/sound/soc/intel/boards/sof_rt5682.c b/sound/soc/intel/boards/sof_rt5682.c index 7c034d671cf3..b4f07bdcf8b4 100644 --- a/sound/soc/intel/boards/sof_rt5682.c +++ b/sound/soc/intel/boards/sof_rt5682.c @@ -22,6 +22,7 @@ #include <sound/soc-acpi.h> #include "../../codecs/rt5682.h" #include "../../codecs/rt5682s.h" +#include "../../codecs/rt5645.h" #include "../../codecs/hdac_hdmi.h" #include "../common/soc-intel-quirks.h" #include "hda_dsp_common.h" @@ -60,6 +61,7 @@ #define SOF_MAX98390_SPEAKER_AMP_PRESENT BIT(24) #define SOF_MAX98390_TWEETER_SPEAKER_PRESENT BIT(25) #define SOF_RT1019_SPEAKER_AMP_PRESENT BIT(26) +#define SOF_RT5650_HEADPHONE_CODEC_PRESENT BIT(27) /* Default: MCLK on, MCLK 19.2M, SSP0 */ @@ -305,6 +307,7 @@ 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 = asoc_rtd_to_codec(rtd, 0)->component; struct snd_soc_jack *jack; + int extra_jack_data; int ret; /* need to enable ASRC function for 24MHz mclk rate */ @@ -315,7 +318,16 @@ static int sof_rt5682_codec_init(struct snd_soc_pcm_runtime *rtd) RT5682S_DA_STEREO1_FILTER | RT5682S_AD_STEREO1_FILTER, RT5682S_CLK_SEL_I2S1_ASRC); - else + else if (sof_rt5682_quirk & SOF_RT5650_HEADPHONE_CODEC_PRESENT) { + rt5645_sel_asrc_clk_src(component, + RT5645_DA_STEREO_FILTER | + RT5645_AD_STEREO_FILTER, + RT5645_CLK_SEL_I2S1_ASRC); + rt5645_sel_asrc_clk_src(component, + RT5645_DA_MONO_L_FILTER | + RT5645_DA_MONO_R_FILTER, + RT5645_CLK_SEL_I2S2_ASRC); + } else rt5682_sel_asrc_clk_src(component, RT5682_DA_STEREO1_FILTER | RT5682_AD_STEREO1_FILTER, @@ -365,7 +377,12 @@ static int sof_rt5682_codec_init(struct snd_soc_pcm_runtime *rtd) 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 (sof_rt5682_quirk & SOF_RT5650_HEADPHONE_CODEC_PRESENT) { + extra_jack_data = SND_JACK_MICROPHONE | SND_JACK_BTN_0; + ret = snd_soc_component_set_jack(component, jack, &extra_jack_data); + } else + ret = snd_soc_component_set_jack(component, jack, NULL); if (ret) { dev_err(rtd->dev, "Headset Jack call-back failed: %d\n", ret); @@ -402,6 +419,8 @@ static int sof_rt5682_hw_params(struct snd_pcm_substream *substream, if (sof_rt5682_quirk & SOF_RT5682S_HEADPHONE_CODEC_PRESENT) pll_source = RT5682S_PLL_S_MCLK; + else if (sof_rt5682_quirk & SOF_RT5650_HEADPHONE_CODEC_PRESENT) + pll_source = RT5645_PLL1_S_MCLK; else pll_source = RT5682_PLL1_S_MCLK; @@ -422,6 +441,8 @@ static int sof_rt5682_hw_params(struct snd_pcm_substream *substream, } else { if (sof_rt5682_quirk & SOF_RT5682S_HEADPHONE_CODEC_PRESENT) pll_source = RT5682S_PLL_S_BCLK1; + else if (sof_rt5682_quirk & SOF_RT5650_HEADPHONE_CODEC_PRESENT) + pll_source = RT5645_PLL1_S_BCLK1; else pll_source = RT5682_PLL1_S_BCLK1; @@ -431,6 +452,9 @@ static int sof_rt5682_hw_params(struct snd_pcm_substream *substream, if (sof_rt5682_quirk & SOF_RT5682S_HEADPHONE_CODEC_PRESENT) { pll_id = RT5682S_PLL2; clk_id = RT5682S_SCLK_S_PLL2; + } else if (sof_rt5682_quirk & SOF_RT5650_HEADPHONE_CODEC_PRESENT) { + pll_id = 0; /* not used in codec driver */ + clk_id = RT5645_SCLK_S_PLL1; } else { pll_id = RT5682_PLL1; clk_id = RT5682_SCLK_S_PLL1; @@ -559,11 +583,30 @@ static const struct snd_soc_dapm_route sof_map[] = { { "IN1P", NULL, "Headset Mic" }, }; +static const struct snd_soc_dapm_route rt5650_spk_dapm_routes[] = { + /* speaker */ + { "Left Spk", NULL, "SPOL" }, + { "Right Spk", NULL, "SPOR" }, +}; + static const struct snd_soc_dapm_route dmic_map[] = { /* digital mics */ {"DMic", NULL, "SoC DMIC"}, }; +static int rt5650_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, rt5650_spk_dapm_routes, + ARRAY_SIZE(rt5650_spk_dapm_routes)); + if (ret) + dev_err(rtd->dev, "fail to add dapm routes, ret=%d\n", ret); + + return ret; +} + static int dmic_init(struct snd_soc_pcm_runtime *rtd) { struct snd_soc_card *card = rtd->card; @@ -614,6 +657,17 @@ static struct snd_soc_dai_link_component rt5682s_component[] = { } }; +static struct snd_soc_dai_link_component rt5650_components[] = { + { + .name = "i2c-10EC5650:00", + .dai_name = "rt5645-aif1", + }, + { + .name = "i2c-10EC5650:00", + .dai_name = "rt5645-aif2", + } +}; + static struct snd_soc_dai_link_component dmic_component[] = { { .name = "dmic-codec", @@ -652,6 +706,9 @@ static struct snd_soc_dai_link *sof_card_dai_links_create(struct device *dev, if (sof_rt5682_quirk & SOF_RT5682S_HEADPHONE_CODEC_PRESENT) { links[id].codecs = rt5682s_component; links[id].num_codecs = ARRAY_SIZE(rt5682s_component); + } else if (sof_rt5682_quirk & SOF_RT5650_HEADPHONE_CODEC_PRESENT) { + links[id].codecs = &rt5650_components[0]; + links[id].num_codecs = 1; } else { links[id].codecs = rt5682_component; links[id].num_codecs = ARRAY_SIZE(rt5682_component); @@ -804,6 +861,11 @@ static struct snd_soc_dai_link *sof_card_dai_links_create(struct device *dev, links[id].init = max_98390_spk_codec_init; links[id].ops = &max_98390_ops; + } else if (sof_rt5682_quirk & SOF_RT5650_HEADPHONE_CODEC_PRESENT) { + links[id].codecs = &rt5650_components[1]; + links[id].num_codecs = 1; + links[id].init = rt5650_spk_init; + links[id].ops = &sof_rt5682_ops; } else { max_98357a_dai_link(&links[id]); } @@ -890,6 +952,12 @@ static int sof_audio_probe(struct platform_device *pdev) /* Detect the headset codec variant */ if (acpi_dev_present("RTL5682", NULL, -1)) sof_rt5682_quirk |= SOF_RT5682S_HEADPHONE_CODEC_PRESENT; + else if (acpi_dev_present("10EC5650", NULL, -1)) { + sof_rt5682_quirk |= SOF_RT5650_HEADPHONE_CODEC_PRESENT; + + sof_audio_card_rt5682.name = devm_kstrdup(&pdev->dev, "rt5650", + GFP_KERNEL); + } if (soc_intel_is_byt() || soc_intel_is_cht()) { is_legacy_cpu = 1; @@ -1178,6 +1246,14 @@ static const struct platform_device_id board_ids[] = { SOF_RT5682_SSP_AMP(0) | SOF_RT5682_NUM_HDMIDEV(3)), }, + { + .name = "jsl_rt5650", + .driver_data = (kernel_ulong_t)(SOF_RT5682_MCLK_EN | + SOF_RT5682_MCLK_24MHZ | + SOF_RT5682_SSP_CODEC(0) | + SOF_SPEAKER_AMP_PRESENT | + SOF_RT5682_SSP_AMP(1)), + }, { } }; MODULE_DEVICE_TABLE(platform, board_ids); diff --git a/sound/soc/intel/common/soc-acpi-intel-jsl-match.c b/sound/soc/intel/common/soc-acpi-intel-jsl-match.c index f5c7e1bbded0..36ea2bacbe7d 100644 --- a/sound/soc/intel/common/soc-acpi-intel-jsl-match.c +++ b/sound/soc/intel/common/soc-acpi-intel-jsl-match.c @@ -34,6 +34,11 @@ static const struct snd_soc_acpi_codecs mx98360a_spk = { .codecs = {"MX98360A"} }; +static struct snd_soc_acpi_codecs rt5650_spk = { + .num_codecs = 1, + .codecs = {"10EC5650"} +}; + static const struct snd_soc_acpi_codecs rt5682_rt5682s_hp = { .num_codecs = 2, .codecs = {"10EC5682", "RTL5682"}, @@ -98,6 +103,13 @@ struct snd_soc_acpi_mach snd_soc_acpi_intel_jsl_machines[] = { SND_SOC_ACPI_TPLG_INTEL_SSP_MSB | SND_SOC_ACPI_TPLG_INTEL_DMIC_NUMBER, }, + { + .id = "10EC5650", + .drv_name = "jsl_rt5650", + .machine_quirk = snd_soc_acpi_codec_list, + .quirk_data = &rt5650_spk, + .sof_tplg_filename = "sof-jsl-rt5650-dual.tplg", + }, {}, }; EXPORT_SYMBOL_GPL(snd_soc_acpi_intel_jsl_machines); -- 2.34.1