1e149ca29SPierre-Louis Bossart // SPDX-License-Identifier: GPL-2.0-only 2a79ae0f6SYong Zhi // Copyright(c) 2019-2020 Intel Corporation. 3f70abd75SBard liao 4f70abd75SBard liao /* 5f70abd75SBard liao * Intel SOF Machine Driver with Realtek rt5682 Codec 6a79ae0f6SYong Zhi * and speaker codec MAX98357A or RT1015. 7f70abd75SBard liao */ 8f70abd75SBard liao #include <linux/i2c.h> 9f70abd75SBard liao #include <linux/input.h> 10f70abd75SBard liao #include <linux/module.h> 11f70abd75SBard liao #include <linux/platform_device.h> 121eed6bc0SXun Zhang #include <linux/clk.h> 13f70abd75SBard liao #include <linux/dmi.h> 14f70abd75SBard liao #include <sound/core.h> 15f70abd75SBard liao #include <sound/jack.h> 16f70abd75SBard liao #include <sound/pcm.h> 17f70abd75SBard liao #include <sound/pcm_params.h> 18f70abd75SBard liao #include <sound/soc.h> 19bf939446SKeyon Jie #include <sound/sof.h> 20f70abd75SBard liao #include <sound/rt5682.h> 219a50d609SBrent Lu #include <sound/rt5682s.h> 22f70abd75SBard liao #include <sound/soc-acpi.h> 23f70abd75SBard liao #include "../../codecs/rt5682.h" 249a50d609SBrent Lu #include "../../codecs/rt5682s.h" 256657fcc9SBrent Lu #include "../../codecs/rt5645.h" 26536cfd2fSPierre-Louis Bossart #include "../common/soc-intel-quirks.h" 2789cadbd8SBrent Lu #include "sof_board_helpers.h" 28e2e404a6SSathyanarayana Nujella #include "sof_maxim_common.h" 29aa6cc97cSBrent Lu #include "sof_realtek_common.h" 30f70abd75SBard liao 318efcd486SBrent Lu /* Driver-specific board quirks: from bit 0 to 7 */ 328efcd486SBrent Lu #define SOF_RT5682_MCLK_EN BIT(0) 3337897babSYong Zhi 34f70abd75SBard liao /* Default: MCLK on, MCLK 19.2M, SSP0 */ 35f70abd75SBard liao static unsigned long sof_rt5682_quirk = SOF_RT5682_MCLK_EN | 368efcd486SBrent Lu SOF_SSP_PORT_CODEC(0); 37f70abd75SBard liao 38f70abd75SBard liao static int sof_rt5682_quirk_cb(const struct dmi_system_id *id) 39f70abd75SBard liao { 40f70abd75SBard liao sof_rt5682_quirk = (unsigned long)id->driver_data; 41f70abd75SBard liao return 1; 42f70abd75SBard liao } 43f70abd75SBard liao 44f70abd75SBard liao static const struct dmi_system_id sof_rt5682_quirk_table[] = { 45f70abd75SBard liao { 46f70abd75SBard liao .callback = sof_rt5682_quirk_cb, 47f70abd75SBard liao .matches = { 481eed6bc0SXun Zhang DMI_MATCH(DMI_SYS_VENDOR, "Circuitco"), 491eed6bc0SXun Zhang DMI_MATCH(DMI_PRODUCT_NAME, "Minnowboard Max"), 501eed6bc0SXun Zhang }, 518efcd486SBrent Lu .driver_data = (void *)(SOF_SSP_PORT_CODEC(2)), 521eed6bc0SXun Zhang }, 531eed6bc0SXun Zhang { 541eed6bc0SXun Zhang .callback = sof_rt5682_quirk_cb, 551eed6bc0SXun Zhang .matches = { 561eed6bc0SXun Zhang DMI_MATCH(DMI_SYS_VENDOR, "AAEON"), 571eed6bc0SXun Zhang DMI_MATCH(DMI_PRODUCT_NAME, "UP-CHT01"), 581eed6bc0SXun Zhang }, 598efcd486SBrent Lu .driver_data = (void *)(SOF_SSP_PORT_CODEC(2)), 601eed6bc0SXun Zhang }, 611eed6bc0SXun Zhang { 621eed6bc0SXun Zhang .callback = sof_rt5682_quirk_cb, 631eed6bc0SXun Zhang .matches = { 64f70abd75SBard liao DMI_MATCH(DMI_SYS_VENDOR, "Intel Corporation"), 65f70abd75SBard liao DMI_MATCH(DMI_PRODUCT_NAME, "WhiskeyLake Client"), 66f70abd75SBard liao }, 67f70abd75SBard liao .driver_data = (void *)(SOF_RT5682_MCLK_EN | 688efcd486SBrent Lu SOF_SSP_PORT_CODEC(1)), 69f70abd75SBard liao }, 70f70abd75SBard liao { 71f70abd75SBard liao .callback = sof_rt5682_quirk_cb, 72f70abd75SBard liao .matches = { 731a3fb5d3SSathya Prakash M R DMI_MATCH(DMI_PRODUCT_FAMILY, "Google_Hatch"), 74f70abd75SBard liao }, 75f70abd75SBard liao .driver_data = (void *)(SOF_RT5682_MCLK_EN | 768efcd486SBrent Lu SOF_SSP_PORT_CODEC(0) | 778efcd486SBrent Lu SOF_SSP_PORT_AMP(1)), 78f70abd75SBard liao }, 79f70abd75SBard liao { 80f70abd75SBard liao .callback = sof_rt5682_quirk_cb, 81f70abd75SBard liao .matches = { 823e1734b6SSathyanarayana Nujella DMI_MATCH(DMI_PRODUCT_FAMILY, "Google_Volteer"), 832a4b91a2SSathyanarayana Nujella DMI_MATCH(DMI_OEM_STRING, "AUDIO-MAX98373_ALC5682I_I2S_UP4"), 843e1734b6SSathyanarayana Nujella }, 853e1734b6SSathyanarayana Nujella .driver_data = (void *)(SOF_RT5682_MCLK_EN | 868efcd486SBrent Lu SOF_SSP_PORT_CODEC(0) | 878efcd486SBrent Lu SOF_SSP_PORT_AMP(2) | 888efcd486SBrent Lu SOF_NUM_IDISP_HDMI(4)), 893e1734b6SSathyanarayana Nujella }, 9046fa9a15Sjairaj arava { 9146fa9a15Sjairaj arava .callback = sof_rt5682_quirk_cb, 9246fa9a15Sjairaj arava .matches = { 9346fa9a15Sjairaj arava DMI_MATCH(DMI_SYS_VENDOR, "Intel Corporation"), 9446fa9a15Sjairaj arava DMI_MATCH(DMI_PRODUCT_NAME, "Alder Lake Client Platform"), 9546fa9a15Sjairaj arava DMI_MATCH(DMI_OEM_STRING, "AUDIO-ADL_MAX98373_ALC5682I_I2S"), 9646fa9a15Sjairaj arava }, 9746fa9a15Sjairaj arava .driver_data = (void *)(SOF_RT5682_MCLK_EN | 988efcd486SBrent Lu SOF_SSP_PORT_CODEC(0) | 998efcd486SBrent Lu SOF_SSP_PORT_AMP(2) | 1008efcd486SBrent Lu SOF_NUM_IDISP_HDMI(4)), 10146fa9a15Sjairaj arava }, 102f316c9d9SMac Chiang { 103f316c9d9SMac Chiang .callback = sof_rt5682_quirk_cb, 104f316c9d9SMac Chiang .matches = { 105f316c9d9SMac Chiang DMI_MATCH(DMI_PRODUCT_FAMILY, "Google_Brya"), 106f316c9d9SMac Chiang DMI_MATCH(DMI_OEM_STRING, "AUDIO-MAX98390_ALC5682I_I2S"), 107f316c9d9SMac Chiang }, 108f316c9d9SMac Chiang .driver_data = (void *)(SOF_RT5682_MCLK_EN | 1098efcd486SBrent Lu SOF_SSP_PORT_CODEC(0) | 1108efcd486SBrent Lu SOF_SSP_PORT_AMP(2) | 1118efcd486SBrent Lu SOF_NUM_IDISP_HDMI(4)), 112f316c9d9SMac Chiang }, 113f316c9d9SMac Chiang { 114f316c9d9SMac Chiang .callback = sof_rt5682_quirk_cb, 115f316c9d9SMac Chiang .matches = { 116f316c9d9SMac Chiang DMI_MATCH(DMI_PRODUCT_FAMILY, "Google_Brya"), 117fcd1e39cSAjye Huang DMI_MATCH(DMI_OEM_STRING, "AUDIO-MAX98360_ALC5682I_I2S_AMP_SSP2"), 118fcd1e39cSAjye Huang }, 119fcd1e39cSAjye Huang .driver_data = (void *)(SOF_RT5682_MCLK_EN | 1208efcd486SBrent Lu SOF_SSP_PORT_CODEC(0) | 1218efcd486SBrent Lu SOF_SSP_PORT_AMP(2) | 1228efcd486SBrent Lu SOF_NUM_IDISP_HDMI(4)), 123fcd1e39cSAjye Huang }, 124b4dd2e37SYong Zhi { 125b4dd2e37SYong Zhi .callback = sof_rt5682_quirk_cb, 126b4dd2e37SYong Zhi .matches = { 127b4dd2e37SYong Zhi DMI_MATCH(DMI_PRODUCT_FAMILY, "Google_Rex"), 128b4dd2e37SYong Zhi }, 129b4dd2e37SYong Zhi .driver_data = (void *)(SOF_RT5682_MCLK_EN | 1308efcd486SBrent Lu SOF_SSP_PORT_CODEC(2) | 1318efcd486SBrent Lu SOF_SSP_PORT_AMP(0) | 1328efcd486SBrent Lu SOF_SSP_PORT_BT_OFFLOAD(1) | 1338efcd486SBrent Lu SOF_BT_OFFLOAD_PRESENT 134b4dd2e37SYong Zhi ), 135b4dd2e37SYong Zhi }, 136f70abd75SBard liao {} 137f70abd75SBard liao }; 138f70abd75SBard liao 139c3ce12b2SPierre-Louis Bossart static struct snd_soc_jack_pin jack_pins[] = { 140c3ce12b2SPierre-Louis Bossart { 141c3ce12b2SPierre-Louis Bossart .pin = "Headphone Jack", 142c3ce12b2SPierre-Louis Bossart .mask = SND_JACK_HEADPHONE, 143c3ce12b2SPierre-Louis Bossart }, 144c3ce12b2SPierre-Louis Bossart { 145c3ce12b2SPierre-Louis Bossart .pin = "Headset Mic", 146c3ce12b2SPierre-Louis Bossart .mask = SND_JACK_MICROPHONE, 147c3ce12b2SPierre-Louis Bossart }, 148c3ce12b2SPierre-Louis Bossart }; 149c3ce12b2SPierre-Louis Bossart 150f70abd75SBard liao static int sof_rt5682_codec_init(struct snd_soc_pcm_runtime *rtd) 151f70abd75SBard liao { 152f70abd75SBard liao struct sof_card_private *ctx = snd_soc_card_get_drvdata(rtd->card); 153a2c1125eSKuninori Morimoto struct snd_soc_component *component = snd_soc_rtd_to_codec(rtd, 0)->component; 15489cadbd8SBrent Lu struct snd_soc_jack *jack = &ctx->headset_jack; 1556657fcc9SBrent Lu int extra_jack_data; 15695409545SBrent Lu int ret, mclk_freq; 15795409545SBrent Lu 158e91d54f8SBrent Lu if (ctx->rt5682.mclk_en) { 15995409545SBrent Lu mclk_freq = sof_dai_get_mclk(rtd); 16095409545SBrent Lu if (mclk_freq <= 0) { 16195409545SBrent Lu dev_err(rtd->dev, "invalid mclk freq %d\n", mclk_freq); 16295409545SBrent Lu return -EINVAL; 16395409545SBrent Lu } 164f70abd75SBard liao 165f70abd75SBard liao /* need to enable ASRC function for 24MHz mclk rate */ 16695409545SBrent Lu if (mclk_freq == 24000000) { 16795409545SBrent Lu dev_info(rtd->dev, "enable ASRC\n"); 16895409545SBrent Lu 1695f706c5eSBrent Lu switch (ctx->codec_type) { 1705f706c5eSBrent Lu case CODEC_RT5650: 1716657fcc9SBrent Lu rt5645_sel_asrc_clk_src(component, 1726657fcc9SBrent Lu RT5645_DA_STEREO_FILTER | 1736657fcc9SBrent Lu RT5645_AD_STEREO_FILTER, 1746657fcc9SBrent Lu RT5645_CLK_SEL_I2S1_ASRC); 1756657fcc9SBrent Lu rt5645_sel_asrc_clk_src(component, 1766657fcc9SBrent Lu RT5645_DA_MONO_L_FILTER | 1776657fcc9SBrent Lu RT5645_DA_MONO_R_FILTER, 1786657fcc9SBrent Lu RT5645_CLK_SEL_I2S2_ASRC); 1795f706c5eSBrent Lu break; 1805f706c5eSBrent Lu case CODEC_RT5682: 1819a50d609SBrent Lu rt5682_sel_asrc_clk_src(component, 1829a50d609SBrent Lu RT5682_DA_STEREO1_FILTER | 183f70abd75SBard liao RT5682_AD_STEREO1_FILTER, 184f70abd75SBard liao RT5682_CLK_SEL_I2S1_ASRC); 1855f706c5eSBrent Lu break; 1865f706c5eSBrent Lu case CODEC_RT5682S: 1875f706c5eSBrent Lu rt5682s_sel_asrc_clk_src(component, 1885f706c5eSBrent Lu RT5682S_DA_STEREO1_FILTER | 1895f706c5eSBrent Lu RT5682S_AD_STEREO1_FILTER, 1905f706c5eSBrent Lu RT5682S_CLK_SEL_I2S1_ASRC); 1915f706c5eSBrent Lu break; 1925f706c5eSBrent Lu default: 1935f706c5eSBrent Lu dev_err(rtd->dev, "invalid codec type %d\n", 1945f706c5eSBrent Lu ctx->codec_type); 1955f706c5eSBrent Lu return -EINVAL; 1965f706c5eSBrent Lu } 197f70abd75SBard liao } 198f70abd75SBard liao 199207255f3SBrent Lu if (ctx->rt5682.is_legacy_cpu) { 2001eed6bc0SXun Zhang /* 2011eed6bc0SXun Zhang * The firmware might enable the clock at 2021eed6bc0SXun Zhang * boot (this information may or may not 2031eed6bc0SXun Zhang * be reflected in the enable clock register). 2041eed6bc0SXun Zhang * To change the rate we must disable the clock 2051eed6bc0SXun Zhang * first to cover these cases. Due to common 2061eed6bc0SXun Zhang * clock framework restrictions that do not allow 2071eed6bc0SXun Zhang * to disable a clock that has not been enabled, 2081eed6bc0SXun Zhang * we need to enable the clock first. 2091eed6bc0SXun Zhang */ 21089cadbd8SBrent Lu ret = clk_prepare_enable(ctx->rt5682.mclk); 2111eed6bc0SXun Zhang if (!ret) 21289cadbd8SBrent Lu clk_disable_unprepare(ctx->rt5682.mclk); 2131eed6bc0SXun Zhang 21489cadbd8SBrent Lu ret = clk_set_rate(ctx->rt5682.mclk, 19200000); 2151eed6bc0SXun Zhang 2161eed6bc0SXun Zhang if (ret) 2171eed6bc0SXun Zhang dev_err(rtd->dev, "unable to set MCLK rate\n"); 2181eed6bc0SXun Zhang } 21995409545SBrent Lu } 2201eed6bc0SXun Zhang 221f70abd75SBard liao /* 222f70abd75SBard liao * Headset buttons map to the google Reference headset. 223f70abd75SBard liao * These can be configured by userspace. 224f70abd75SBard liao */ 225c3ce12b2SPierre-Louis Bossart ret = snd_soc_card_jack_new_pins(rtd->card, "Headset Jack", 226f70abd75SBard liao SND_JACK_HEADSET | SND_JACK_BTN_0 | 227f70abd75SBard liao SND_JACK_BTN_1 | SND_JACK_BTN_2 | 228f70abd75SBard liao SND_JACK_BTN_3, 22989cadbd8SBrent Lu jack, 230c3ce12b2SPierre-Louis Bossart jack_pins, 231c3ce12b2SPierre-Louis Bossart ARRAY_SIZE(jack_pins)); 232f70abd75SBard liao if (ret) { 233f70abd75SBard liao dev_err(rtd->dev, "Headset Jack creation failed: %d\n", ret); 234f70abd75SBard liao return ret; 235f70abd75SBard liao } 236f70abd75SBard liao 237f70abd75SBard liao snd_jack_set_key(jack->jack, SND_JACK_BTN_0, KEY_PLAYPAUSE); 238d5952f34SSathya Prakash M R snd_jack_set_key(jack->jack, SND_JACK_BTN_1, KEY_VOICECOMMAND); 239d5952f34SSathya Prakash M R snd_jack_set_key(jack->jack, SND_JACK_BTN_2, KEY_VOLUMEUP); 240d5952f34SSathya Prakash M R snd_jack_set_key(jack->jack, SND_JACK_BTN_3, KEY_VOLUMEDOWN); 2416657fcc9SBrent Lu 2425f706c5eSBrent Lu if (ctx->codec_type == CODEC_RT5650) { 2436657fcc9SBrent Lu extra_jack_data = SND_JACK_MICROPHONE | SND_JACK_BTN_0; 2446657fcc9SBrent Lu ret = snd_soc_component_set_jack(component, jack, &extra_jack_data); 2456657fcc9SBrent Lu } else 246f70abd75SBard liao ret = snd_soc_component_set_jack(component, jack, NULL); 247f70abd75SBard liao 248f70abd75SBard liao if (ret) { 249f70abd75SBard liao dev_err(rtd->dev, "Headset Jack call-back failed: %d\n", ret); 250f70abd75SBard liao return ret; 251f70abd75SBard liao } 252f70abd75SBard liao 253f70abd75SBard liao return ret; 254f70abd75SBard liao }; 255f70abd75SBard liao 256b0c96fc1SFred Oh static void sof_rt5682_codec_exit(struct snd_soc_pcm_runtime *rtd) 257b0c96fc1SFred Oh { 258a2c1125eSKuninori Morimoto struct snd_soc_component *component = snd_soc_rtd_to_codec(rtd, 0)->component; 259b0c96fc1SFred Oh 260b0c96fc1SFred Oh snd_soc_component_set_jack(component, NULL, NULL); 261b0c96fc1SFred Oh } 262b0c96fc1SFred Oh 263f70abd75SBard liao static int sof_rt5682_hw_params(struct snd_pcm_substream *substream, 264f70abd75SBard liao struct snd_pcm_hw_params *params) 265f70abd75SBard liao { 266a2c1125eSKuninori Morimoto struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream); 2671eed6bc0SXun Zhang struct sof_card_private *ctx = snd_soc_card_get_drvdata(rtd->card); 268a2c1125eSKuninori Morimoto struct snd_soc_dai *codec_dai = snd_soc_rtd_to_codec(rtd, 0); 2699a50d609SBrent Lu int pll_id, pll_source, pll_in, pll_out, clk_id, ret; 270f70abd75SBard liao 271e91d54f8SBrent Lu if (ctx->rt5682.mclk_en) { 272207255f3SBrent Lu if (ctx->rt5682.is_legacy_cpu) { 27389cadbd8SBrent Lu ret = clk_prepare_enable(ctx->rt5682.mclk); 2741eed6bc0SXun Zhang if (ret < 0) { 2751eed6bc0SXun Zhang dev_err(rtd->dev, 2761eed6bc0SXun Zhang "could not configure MCLK state"); 2771eed6bc0SXun Zhang return ret; 2781eed6bc0SXun Zhang } 2791eed6bc0SXun Zhang } 2801eed6bc0SXun Zhang 2815f706c5eSBrent Lu switch (ctx->codec_type) { 2825f706c5eSBrent Lu case CODEC_RT5650: 2836657fcc9SBrent Lu pll_source = RT5645_PLL1_S_MCLK; 2845f706c5eSBrent Lu break; 2855f706c5eSBrent Lu case CODEC_RT5682: 2869a50d609SBrent Lu pll_source = RT5682_PLL1_S_MCLK; 2875f706c5eSBrent Lu break; 2885f706c5eSBrent Lu case CODEC_RT5682S: 2895f706c5eSBrent Lu pll_source = RT5682S_PLL_S_MCLK; 2905f706c5eSBrent Lu break; 2915f706c5eSBrent Lu default: 2925f706c5eSBrent Lu dev_err(rtd->dev, "invalid codec type %d\n", 2935f706c5eSBrent Lu ctx->codec_type); 2945f706c5eSBrent Lu return -EINVAL; 2955f706c5eSBrent Lu } 296bf939446SKeyon Jie 297bf939446SKeyon Jie /* get the tplg configured mclk. */ 2989a50d609SBrent Lu pll_in = sof_dai_get_mclk(rtd); 29995409545SBrent Lu if (pll_in <= 0) { 30095409545SBrent Lu dev_err(rtd->dev, "invalid mclk freq %d\n", pll_in); 30195409545SBrent Lu return -EINVAL; 302bf939446SKeyon Jie } 303f70abd75SBard liao } else { 3045f706c5eSBrent Lu switch (ctx->codec_type) { 3055f706c5eSBrent Lu case CODEC_RT5650: 3066657fcc9SBrent Lu pll_source = RT5645_PLL1_S_BCLK1; 3075f706c5eSBrent Lu break; 3085f706c5eSBrent Lu case CODEC_RT5682: 3099a50d609SBrent Lu pll_source = RT5682_PLL1_S_BCLK1; 3105f706c5eSBrent Lu break; 3115f706c5eSBrent Lu case CODEC_RT5682S: 3125f706c5eSBrent Lu pll_source = RT5682S_PLL_S_BCLK1; 3135f706c5eSBrent Lu break; 3145f706c5eSBrent Lu default: 3155f706c5eSBrent Lu dev_err(rtd->dev, "invalid codec type %d\n", 3165f706c5eSBrent Lu ctx->codec_type); 3175f706c5eSBrent Lu return -EINVAL; 3185f706c5eSBrent Lu } 3199a50d609SBrent Lu 3209a50d609SBrent Lu pll_in = params_rate(params) * 50; 3219a50d609SBrent Lu } 3229a50d609SBrent Lu 323*b5aaf6a5SBrent Lu pll_out = params_rate(params) * 512; 324*b5aaf6a5SBrent Lu 325*b5aaf6a5SBrent Lu /* when MCLK is 512FS, no need to set PLL configuration additionally. */ 326*b5aaf6a5SBrent Lu if (pll_in == pll_out) { 327*b5aaf6a5SBrent Lu switch (ctx->codec_type) { 328*b5aaf6a5SBrent Lu case CODEC_RT5650: 329*b5aaf6a5SBrent Lu clk_id = RT5645_SCLK_S_MCLK; 330*b5aaf6a5SBrent Lu break; 331*b5aaf6a5SBrent Lu case CODEC_RT5682: 332*b5aaf6a5SBrent Lu clk_id = RT5682_SCLK_S_MCLK; 333*b5aaf6a5SBrent Lu break; 334*b5aaf6a5SBrent Lu case CODEC_RT5682S: 335*b5aaf6a5SBrent Lu clk_id = RT5682S_SCLK_S_MCLK; 336*b5aaf6a5SBrent Lu break; 337*b5aaf6a5SBrent Lu default: 338*b5aaf6a5SBrent Lu dev_err(rtd->dev, "invalid codec type %d\n", 339*b5aaf6a5SBrent Lu ctx->codec_type); 340*b5aaf6a5SBrent Lu return -EINVAL; 341*b5aaf6a5SBrent Lu } 342*b5aaf6a5SBrent Lu } else { 3435f706c5eSBrent Lu switch (ctx->codec_type) { 3445f706c5eSBrent Lu case CODEC_RT5650: 3456657fcc9SBrent Lu pll_id = 0; /* not used in codec driver */ 3466657fcc9SBrent Lu clk_id = RT5645_SCLK_S_PLL1; 3475f706c5eSBrent Lu break; 3485f706c5eSBrent Lu case CODEC_RT5682: 3499a50d609SBrent Lu pll_id = RT5682_PLL1; 3509a50d609SBrent Lu clk_id = RT5682_SCLK_S_PLL1; 3515f706c5eSBrent Lu break; 3525f706c5eSBrent Lu case CODEC_RT5682S: 353dcc2cd80SBard Liao /* 354dcc2cd80SBard Liao * For MCLK = 24.576MHz and sample rate = 96KHz case, use PLL1 We don't test 355dcc2cd80SBard Liao * pll_out or params_rate() here since rt5682s PLL2 doesn't support 24.576MHz 356dcc2cd80SBard Liao * input, so we have no choice but to use PLL1. Besides, we will not use PLL at 357dcc2cd80SBard Liao * all if pll_in == pll_out. ex, MCLK = 24.576Mhz and sample rate = 48KHz 358dcc2cd80SBard Liao */ 359dcc2cd80SBard Liao if (pll_in == 24576000) { 360dcc2cd80SBard Liao pll_id = RT5682S_PLL1; 361dcc2cd80SBard Liao clk_id = RT5682S_SCLK_S_PLL1; 362dcc2cd80SBard Liao } else { 3635f706c5eSBrent Lu pll_id = RT5682S_PLL2; 3645f706c5eSBrent Lu clk_id = RT5682S_SCLK_S_PLL2; 365dcc2cd80SBard Liao } 3665f706c5eSBrent Lu break; 3675f706c5eSBrent Lu default: 3685f706c5eSBrent Lu dev_err(rtd->dev, "invalid codec type %d\n", ctx->codec_type); 3695f706c5eSBrent Lu return -EINVAL; 370f70abd75SBard liao } 371f70abd75SBard liao 3729a50d609SBrent Lu /* Configure pll for codec */ 3739a50d609SBrent Lu ret = snd_soc_dai_set_pll(codec_dai, pll_id, pll_source, pll_in, 3749a50d609SBrent Lu pll_out); 375f70abd75SBard liao if (ret < 0) 376f70abd75SBard liao dev_err(rtd->dev, "snd_soc_dai_set_pll err = %d\n", ret); 377dbf2f8e3SMac Chiang } 378f70abd75SBard liao 379f70abd75SBard liao /* Configure sysclk for codec */ 3809a50d609SBrent Lu ret = snd_soc_dai_set_sysclk(codec_dai, clk_id, 381f70abd75SBard liao pll_out, SND_SOC_CLOCK_IN); 382f70abd75SBard liao if (ret < 0) 383f70abd75SBard liao dev_err(rtd->dev, "snd_soc_dai_set_sysclk err = %d\n", ret); 384f70abd75SBard liao 385f70abd75SBard liao /* 386f70abd75SBard liao * slot_width should equal or large than data length, set them 387f70abd75SBard liao * be the same 388f70abd75SBard liao */ 389f70abd75SBard liao ret = snd_soc_dai_set_tdm_slot(codec_dai, 0x0, 0x0, 2, 390f70abd75SBard liao params_width(params)); 391f70abd75SBard liao if (ret < 0) { 392f70abd75SBard liao dev_err(rtd->dev, "set TDM slot err:%d\n", ret); 393f70abd75SBard liao return ret; 394f70abd75SBard liao } 395f70abd75SBard liao 396f70abd75SBard liao return ret; 397f70abd75SBard liao } 398f70abd75SBard liao 399f70abd75SBard liao static struct snd_soc_ops sof_rt5682_ops = { 400f70abd75SBard liao .hw_params = sof_rt5682_hw_params, 401f70abd75SBard liao }; 402f70abd75SBard liao 403f70abd75SBard liao static int sof_card_late_probe(struct snd_soc_card *card) 404f70abd75SBard liao { 405f70abd75SBard liao struct sof_card_private *ctx = snd_soc_card_get_drvdata(card); 40694d2d089SDharageswari R struct snd_soc_dapm_context *dapm = &card->dapm; 40798ff5c26SGuennadi Liakhovetski int err; 408f70abd75SBard liao 4095f706c5eSBrent Lu if (ctx->amp_type == CODEC_MAX98373) { 410371a3f01SYong Zhi /* Disable Left and Right Spk pin after boot */ 411371a3f01SYong Zhi snd_soc_dapm_disable_pin(dapm, "Left Spk"); 412371a3f01SYong Zhi snd_soc_dapm_disable_pin(dapm, "Right Spk"); 413371a3f01SYong Zhi err = snd_soc_dapm_sync(dapm); 414371a3f01SYong Zhi if (err < 0) 415371a3f01SYong Zhi return err; 416371a3f01SYong Zhi } 417371a3f01SYong Zhi 41889cadbd8SBrent Lu return sof_intel_board_card_late_probe(card); 41998ff5c26SGuennadi Liakhovetski } 42059bbd703SKai Vehmanen 421f70abd75SBard liao static const struct snd_kcontrol_new sof_controls[] = { 422f70abd75SBard liao SOC_DAPM_PIN_SWITCH("Headphone Jack"), 423f70abd75SBard liao SOC_DAPM_PIN_SWITCH("Headset Mic"), 424f70abd75SBard liao }; 425f70abd75SBard liao 426f70abd75SBard liao static const struct snd_soc_dapm_widget sof_widgets[] = { 427f70abd75SBard liao SND_SOC_DAPM_HP("Headphone Jack", NULL), 428f70abd75SBard liao SND_SOC_DAPM_MIC("Headset Mic", NULL), 4294413adc4SBard Liao }; 4304413adc4SBard Liao 431f70abd75SBard liao static const struct snd_soc_dapm_route sof_map[] = { 432f70abd75SBard liao /* HP jack connectors - unknown if we have jack detection */ 433f70abd75SBard liao { "Headphone Jack", NULL, "HPOL" }, 434f70abd75SBard liao { "Headphone Jack", NULL, "HPOR" }, 435f70abd75SBard liao 436f70abd75SBard liao /* other jacks */ 437f70abd75SBard liao { "IN1P", NULL, "Headset Mic" }, 438f70abd75SBard liao }; 439f70abd75SBard liao 440d2d377fcSBrent Lu static const struct snd_kcontrol_new rt5650_spk_kcontrols[] = { 441d2d377fcSBrent Lu SOC_DAPM_PIN_SWITCH("Left Spk"), 442d2d377fcSBrent Lu SOC_DAPM_PIN_SWITCH("Right Spk"), 443d2d377fcSBrent Lu 444d2d377fcSBrent Lu }; 445d2d377fcSBrent Lu 446d2d377fcSBrent Lu static const struct snd_soc_dapm_widget rt5650_spk_widgets[] = { 447d2d377fcSBrent Lu SND_SOC_DAPM_SPK("Left Spk", NULL), 448d2d377fcSBrent Lu SND_SOC_DAPM_SPK("Right Spk", NULL), 449d2d377fcSBrent Lu }; 450d2d377fcSBrent Lu 4516657fcc9SBrent Lu static const struct snd_soc_dapm_route rt5650_spk_dapm_routes[] = { 4526657fcc9SBrent Lu /* speaker */ 4536657fcc9SBrent Lu { "Left Spk", NULL, "SPOL" }, 4546657fcc9SBrent Lu { "Right Spk", NULL, "SPOR" }, 4556657fcc9SBrent Lu }; 4566657fcc9SBrent Lu 4576657fcc9SBrent Lu static int rt5650_spk_init(struct snd_soc_pcm_runtime *rtd) 4586657fcc9SBrent Lu { 4596657fcc9SBrent Lu struct snd_soc_card *card = rtd->card; 4606657fcc9SBrent Lu int ret; 4616657fcc9SBrent Lu 462d2d377fcSBrent Lu ret = snd_soc_dapm_new_controls(&card->dapm, rt5650_spk_widgets, 463d2d377fcSBrent Lu ARRAY_SIZE(rt5650_spk_widgets)); 464d2d377fcSBrent Lu if (ret) { 465d2d377fcSBrent Lu dev_err(rtd->dev, "fail to add rt5650 spk widgets, ret %d\n", 466d2d377fcSBrent Lu ret); 467d2d377fcSBrent Lu return ret; 468d2d377fcSBrent Lu } 469d2d377fcSBrent Lu 470d2d377fcSBrent Lu ret = snd_soc_add_card_controls(card, rt5650_spk_kcontrols, 471d2d377fcSBrent Lu ARRAY_SIZE(rt5650_spk_kcontrols)); 472d2d377fcSBrent Lu if (ret) { 473d2d377fcSBrent Lu dev_err(rtd->dev, "fail to add rt5650 spk kcontrols, ret %d\n", 474d2d377fcSBrent Lu ret); 475d2d377fcSBrent Lu return ret; 476d2d377fcSBrent Lu } 477d2d377fcSBrent Lu 4786657fcc9SBrent Lu ret = snd_soc_dapm_add_routes(&card->dapm, rt5650_spk_dapm_routes, 4796657fcc9SBrent Lu ARRAY_SIZE(rt5650_spk_dapm_routes)); 4806657fcc9SBrent Lu if (ret) 4816657fcc9SBrent Lu dev_err(rtd->dev, "fail to add dapm routes, ret=%d\n", ret); 4826657fcc9SBrent Lu 4836657fcc9SBrent Lu return ret; 4846657fcc9SBrent Lu } 4856657fcc9SBrent Lu 486f70abd75SBard liao /* sof audio machine driver for rt5682 codec */ 487f70abd75SBard liao static struct snd_soc_card sof_audio_card_rt5682 = { 488d745cc1aSJaroslav Kysela .name = "rt5682", /* the sof- prefix is added by the core */ 489f70abd75SBard liao .owner = THIS_MODULE, 490f70abd75SBard liao .controls = sof_controls, 491f70abd75SBard liao .num_controls = ARRAY_SIZE(sof_controls), 492f70abd75SBard liao .dapm_widgets = sof_widgets, 493f70abd75SBard liao .num_dapm_widgets = ARRAY_SIZE(sof_widgets), 494f70abd75SBard liao .dapm_routes = sof_map, 495f70abd75SBard liao .num_dapm_routes = ARRAY_SIZE(sof_map), 496f70abd75SBard liao .fully_routed = true, 497f70abd75SBard liao .late_probe = sof_card_late_probe, 498f70abd75SBard liao }; 499f70abd75SBard liao 500f70abd75SBard liao static struct snd_soc_dai_link_component rt5682_component[] = { 501f70abd75SBard liao { 502f70abd75SBard liao .name = "i2c-10EC5682:00", 503f70abd75SBard liao .dai_name = "rt5682-aif1", 504f70abd75SBard liao } 505f70abd75SBard liao }; 506f70abd75SBard liao 5079a50d609SBrent Lu static struct snd_soc_dai_link_component rt5682s_component[] = { 5089a50d609SBrent Lu { 5099a50d609SBrent Lu .name = "i2c-RTL5682:00", 5109a50d609SBrent Lu .dai_name = "rt5682s-aif1", 5119a50d609SBrent Lu } 5129a50d609SBrent Lu }; 5139a50d609SBrent Lu 5146657fcc9SBrent Lu static struct snd_soc_dai_link_component rt5650_components[] = { 5156657fcc9SBrent Lu { 5166657fcc9SBrent Lu .name = "i2c-10EC5650:00", 5176657fcc9SBrent Lu .dai_name = "rt5645-aif1", 5186657fcc9SBrent Lu }, 5196657fcc9SBrent Lu { 5206657fcc9SBrent Lu .name = "i2c-10EC5650:00", 5216657fcc9SBrent Lu .dai_name = "rt5645-aif2", 5226657fcc9SBrent Lu } 5236657fcc9SBrent Lu }; 5246657fcc9SBrent Lu 5258fa1116eSBrent Lu static int 5268fa1116eSBrent Lu sof_card_dai_links_create(struct device *dev, struct snd_soc_card *card, 5278fa1116eSBrent Lu struct sof_card_private *ctx) 528f70abd75SBard liao { 52989cadbd8SBrent Lu int ret; 530f70abd75SBard liao 5318fa1116eSBrent Lu ret = sof_intel_board_set_dai_link(dev, card, ctx); 53284c280afSBrent Lu if (ret) 5338fa1116eSBrent Lu return ret; 534f70abd75SBard liao 5358fa1116eSBrent Lu if (!ctx->codec_link) { 5368fa1116eSBrent Lu dev_err(dev, "codec link not available"); 5378fa1116eSBrent Lu return -EINVAL; 5389a50d609SBrent Lu } 5395f706c5eSBrent Lu 5408fa1116eSBrent Lu /* codec-specific fields for headphone codec */ 5418fa1116eSBrent Lu switch (ctx->codec_type) { 5428fa1116eSBrent Lu case CODEC_RT5650: 5438fa1116eSBrent Lu ctx->codec_link->codecs = &rt5650_components[0]; 5448fa1116eSBrent Lu ctx->codec_link->num_codecs = 1; 5458fa1116eSBrent Lu break; 5468fa1116eSBrent Lu case CODEC_RT5682: 5478fa1116eSBrent Lu ctx->codec_link->codecs = rt5682_component; 5488fa1116eSBrent Lu ctx->codec_link->num_codecs = ARRAY_SIZE(rt5682_component); 5498fa1116eSBrent Lu break; 5508fa1116eSBrent Lu case CODEC_RT5682S: 5518fa1116eSBrent Lu ctx->codec_link->codecs = rt5682s_component; 5528fa1116eSBrent Lu ctx->codec_link->num_codecs = ARRAY_SIZE(rt5682s_component); 5538fa1116eSBrent Lu break; 5548fa1116eSBrent Lu default: 5558fa1116eSBrent Lu dev_err(dev, "invalid codec type %d\n", ctx->codec_type); 5568fa1116eSBrent Lu return -EINVAL; 5578fa1116eSBrent Lu } 55884c280afSBrent Lu 5598fa1116eSBrent Lu ctx->codec_link->init = sof_rt5682_codec_init; 5608fa1116eSBrent Lu ctx->codec_link->exit = sof_rt5682_codec_exit; 5618fa1116eSBrent Lu ctx->codec_link->ops = &sof_rt5682_ops; 5628fa1116eSBrent Lu 5638fa1116eSBrent Lu if (!ctx->rt5682.is_legacy_cpu) { 564f70abd75SBard liao /* 565f70abd75SBard liao * Currently, On SKL+ platforms MCLK will be turned off in sof 566f70abd75SBard liao * runtime suspended, and it will go into runtime suspended 567f70abd75SBard liao * right after playback is stop. However, rt5682 will output 568f70abd75SBard liao * static noise if sysclk turns off during playback. Set 569f70abd75SBard liao * ignore_pmdown_time to power down rt5682 immediately and 570f70abd75SBard liao * avoid the noise. 571f70abd75SBard liao * It can be removed once we can control MCLK by driver. 572f70abd75SBard liao */ 5738fa1116eSBrent Lu ctx->codec_link->ignore_pmdown_time = 1; 574e711223aSKeyon Jie } 575f70abd75SBard liao 5768fa1116eSBrent Lu if (ctx->amp_type == CODEC_NONE) 5778fa1116eSBrent Lu return 0; 578c51fc25dSBrent Lu 5798fa1116eSBrent Lu if (!ctx->amp_link) { 5808fa1116eSBrent Lu dev_err(dev, "amp link not available"); 5818fa1116eSBrent Lu return -EINVAL; 582f70abd75SBard liao } 583f70abd75SBard liao 5848fa1116eSBrent Lu /* codec-specific fields for speaker amplifier */ 5858fa1116eSBrent Lu switch (ctx->amp_type) { 5865f706c5eSBrent Lu case CODEC_MAX98357A: 5878fa1116eSBrent Lu max_98357a_dai_link(ctx->amp_link); 5885f706c5eSBrent Lu break; 5895f706c5eSBrent Lu case CODEC_MAX98360A: 5908fa1116eSBrent Lu max_98360a_dai_link(ctx->amp_link); 5915f706c5eSBrent Lu break; 5925f706c5eSBrent Lu case CODEC_MAX98373: 5938fa1116eSBrent Lu ctx->amp_link->codecs = max_98373_components; 5948fa1116eSBrent Lu ctx->amp_link->num_codecs = ARRAY_SIZE(max_98373_components); 5958fa1116eSBrent Lu ctx->amp_link->init = max_98373_spk_codec_init; 5968fa1116eSBrent Lu ctx->amp_link->ops = &max_98373_ops; 5975f706c5eSBrent Lu break; 5985f706c5eSBrent Lu case CODEC_MAX98390: 5998fa1116eSBrent Lu max_98390_dai_link(dev, ctx->amp_link); 6005f706c5eSBrent Lu break; 6015f706c5eSBrent Lu case CODEC_RT1011: 602551fb559SBrent Lu sof_rt1011_dai_link(dev, ctx->amp_link); 6035f706c5eSBrent Lu break; 6045f706c5eSBrent Lu case CODEC_RT1015: 6058fa1116eSBrent Lu sof_rt1015_dai_link(ctx->amp_link); 6065f706c5eSBrent Lu break; 6075f706c5eSBrent Lu case CODEC_RT1015P: 6088fa1116eSBrent Lu sof_rt1015p_dai_link(ctx->amp_link); 6095f706c5eSBrent Lu break; 6105f706c5eSBrent Lu case CODEC_RT1019P: 6118fa1116eSBrent Lu sof_rt1019p_dai_link(ctx->amp_link); 6125f706c5eSBrent Lu break; 6135f706c5eSBrent Lu case CODEC_RT5650: 6145f706c5eSBrent Lu /* use AIF2 to support speaker pipeline */ 6158fa1116eSBrent Lu ctx->amp_link->codecs = &rt5650_components[1]; 6168fa1116eSBrent Lu ctx->amp_link->num_codecs = 1; 6178fa1116eSBrent Lu ctx->amp_link->init = rt5650_spk_init; 6188fa1116eSBrent Lu ctx->amp_link->ops = &sof_rt5682_ops; 6195f706c5eSBrent Lu break; 6205f706c5eSBrent Lu default: 6218fa1116eSBrent Lu dev_err(dev, "invalid amp type %d\n", ctx->amp_type); 6228fa1116eSBrent Lu return -EINVAL; 623a79ae0f6SYong Zhi } 6245f706c5eSBrent Lu 6258fa1116eSBrent Lu return 0; 626f70abd75SBard liao } 627f70abd75SBard liao 62844567d3dSBrent Lu #define GLK_LINK_ORDER SOF_LINK_ORDER(SOF_LINK_AMP, \ 62944567d3dSBrent Lu SOF_LINK_CODEC, \ 63044567d3dSBrent Lu SOF_LINK_DMIC01, \ 63144567d3dSBrent Lu SOF_LINK_IDISP_HDMI, \ 63244567d3dSBrent Lu SOF_LINK_NONE, \ 63344567d3dSBrent Lu SOF_LINK_NONE, \ 63444567d3dSBrent Lu SOF_LINK_NONE) 63544567d3dSBrent Lu 636f70abd75SBard liao static int sof_audio_probe(struct platform_device *pdev) 637f70abd75SBard liao { 6383de206a4SBrent Lu struct snd_soc_acpi_mach *mach = pdev->dev.platform_data; 639f70abd75SBard liao struct sof_card_private *ctx; 6406136d879SBrent Lu char *card_name; 641e45cd972SBrent Lu int ret; 642f70abd75SBard liao 6436605f0caSSathyanarayana Nujella if (pdev->id_entry && pdev->id_entry->driver_data) 6446605f0caSSathyanarayana Nujella sof_rt5682_quirk = (unsigned long)pdev->id_entry->driver_data; 6456605f0caSSathyanarayana Nujella 646c68e0797SSathyanarayana Nujella dmi_check_system(sof_rt5682_quirk_table); 647c68e0797SSathyanarayana Nujella 6488efcd486SBrent Lu dev_dbg(&pdev->dev, "sof_rt5682_quirk = %lx\n", sof_rt5682_quirk); 6498efcd486SBrent Lu 6508efcd486SBrent Lu /* initialize ctx with board quirk */ 6518efcd486SBrent Lu ctx = sof_intel_board_get_ctx(&pdev->dev, sof_rt5682_quirk); 6528efcd486SBrent Lu if (!ctx) 6538efcd486SBrent Lu return -ENOMEM; 654d4b74e21SSam McNally 6555f706c5eSBrent Lu if (ctx->codec_type == CODEC_RT5650) { 6566136d879SBrent Lu card_name = devm_kstrdup(&pdev->dev, "rt5650", GFP_KERNEL); 6576136d879SBrent Lu if (!card_name) 6586136d879SBrent Lu return -ENOMEM; 6596136d879SBrent Lu 6606136d879SBrent Lu sof_audio_card_rt5682.name = card_name; 6615f706c5eSBrent Lu 6625f706c5eSBrent Lu /* create speaker dai link also */ 6635f706c5eSBrent Lu if (ctx->amp_type == CODEC_NONE) 6645f706c5eSBrent Lu ctx->amp_type = CODEC_RT5650; 6656657fcc9SBrent Lu } 6668fe6ec03SBrent Lu 66744567d3dSBrent Lu if (mach->mach_params.codec_mask & IDISP_CODEC_MASK) 66844567d3dSBrent Lu ctx->hdmi.idisp_codec = true; 6696136d879SBrent Lu 67076f33e2fSBrent Lu if (soc_intel_is_byt() || soc_intel_is_cht()) { 67189cadbd8SBrent Lu ctx->rt5682.is_legacy_cpu = true; 672c51fc25dSBrent Lu ctx->dmic_be_num = 0; 67389cadbd8SBrent Lu /* HDMI is not supported by SOF on Baytrail/CherryTrail */ 67489cadbd8SBrent Lu ctx->hdmi_num = 0; 67544567d3dSBrent Lu } else if (soc_intel_is_glk()) { 67644567d3dSBrent Lu /* dmic16k not support */ 67744567d3dSBrent Lu ctx->dmic_be_num = 1; 67844567d3dSBrent Lu 67944567d3dSBrent Lu /* overwrite the DAI link order for GLK boards */ 68044567d3dSBrent Lu ctx->link_order_overwrite = GLK_LINK_ORDER; 6815498a4edSBrent Lu 6825498a4edSBrent Lu /* backward-compatible with existing devices */ 6835498a4edSBrent Lu switch (ctx->amp_type) { 6845498a4edSBrent Lu case CODEC_MAX98357A: 6855498a4edSBrent Lu card_name = devm_kstrdup(&pdev->dev, "glkrt5682max", 6865498a4edSBrent Lu GFP_KERNEL); 6875498a4edSBrent Lu if (!card_name) 6885498a4edSBrent Lu return -ENOMEM; 6895498a4edSBrent Lu 6905498a4edSBrent Lu sof_audio_card_rt5682.name = card_name; 6915498a4edSBrent Lu break; 6925498a4edSBrent Lu default: 6935498a4edSBrent Lu break; 6945498a4edSBrent Lu } 69544567d3dSBrent Lu } else if (soc_intel_is_cml()) { 69644567d3dSBrent Lu /* backward-compatible with existing devices */ 69744567d3dSBrent Lu switch (ctx->amp_type) { 69844567d3dSBrent Lu case CODEC_RT1011: 69944567d3dSBrent Lu card_name = devm_kstrdup(&pdev->dev, "cml_rt1011_rt5682", 70044567d3dSBrent Lu GFP_KERNEL); 70144567d3dSBrent Lu if (!card_name) 70244567d3dSBrent Lu return -ENOMEM; 70344567d3dSBrent Lu 70444567d3dSBrent Lu sof_audio_card_rt5682.name = card_name; 70544567d3dSBrent Lu break; 70644567d3dSBrent Lu default: 70744567d3dSBrent Lu break; 70844567d3dSBrent Lu } 709f70abd75SBard liao } 710f70abd75SBard liao 711207255f3SBrent Lu if (sof_rt5682_quirk & SOF_RT5682_MCLK_EN) { 712e91d54f8SBrent Lu ctx->rt5682.mclk_en = true; 713e91d54f8SBrent Lu 7141eed6bc0SXun Zhang /* need to get main clock from pmc */ 715207255f3SBrent Lu if (ctx->rt5682.is_legacy_cpu) { 71689cadbd8SBrent Lu ctx->rt5682.mclk = devm_clk_get(&pdev->dev, "pmc_plt_clk_3"); 71789cadbd8SBrent Lu if (IS_ERR(ctx->rt5682.mclk)) { 71889cadbd8SBrent Lu ret = PTR_ERR(ctx->rt5682.mclk); 719e5f0d490SChuhong Yuan 720e5f0d490SChuhong Yuan dev_err(&pdev->dev, 721e5f0d490SChuhong Yuan "Failed to get MCLK from pmc_plt_clk_3: %d\n", 722e5f0d490SChuhong Yuan ret); 723e5f0d490SChuhong Yuan return ret; 724e5f0d490SChuhong Yuan } 725e5f0d490SChuhong Yuan 72689cadbd8SBrent Lu ret = clk_prepare_enable(ctx->rt5682.mclk); 7271eed6bc0SXun Zhang if (ret < 0) { 7281eed6bc0SXun Zhang dev_err(&pdev->dev, 7291eed6bc0SXun Zhang "could not configure MCLK state"); 7301eed6bc0SXun Zhang return ret; 7311eed6bc0SXun Zhang } 7321eed6bc0SXun Zhang } 733207255f3SBrent Lu } 7341eed6bc0SXun Zhang 7358fa1116eSBrent Lu /* update dai_link */ 7368fa1116eSBrent Lu ret = sof_card_dai_links_create(&pdev->dev, &sof_audio_card_rt5682, ctx); 7378fa1116eSBrent Lu if (ret) 7388fa1116eSBrent Lu return ret; 739f70abd75SBard liao 7405f706c5eSBrent Lu /* update codec_conf */ 7415f706c5eSBrent Lu switch (ctx->amp_type) { 7425f706c5eSBrent Lu case CODEC_MAX98373: 7435f706c5eSBrent Lu max_98373_set_codec_conf(&sof_audio_card_rt5682); 7445f706c5eSBrent Lu break; 7455f706c5eSBrent Lu case CODEC_MAX98390: 7465f706c5eSBrent Lu max_98390_set_codec_conf(&pdev->dev, &sof_audio_card_rt5682); 7475f706c5eSBrent Lu break; 7485f706c5eSBrent Lu case CODEC_RT1011: 749551fb559SBrent Lu sof_rt1011_codec_conf(&pdev->dev, &sof_audio_card_rt5682); 7505f706c5eSBrent Lu break; 7515f706c5eSBrent Lu case CODEC_RT1015: 75277659872SYong Zhi sof_rt1015_codec_conf(&sof_audio_card_rt5682); 7535f706c5eSBrent Lu break; 7545f706c5eSBrent Lu case CODEC_RT1015P: 7555f706c5eSBrent Lu sof_rt1015p_codec_conf(&sof_audio_card_rt5682); 7565f706c5eSBrent Lu break; 7575f706c5eSBrent Lu case CODEC_MAX98357A: 7585f706c5eSBrent Lu case CODEC_MAX98360A: 7595f706c5eSBrent Lu case CODEC_RT1019P: 7605f706c5eSBrent Lu case CODEC_RT5650: 761b497654fSBrent Lu case CODEC_NONE: 7625f706c5eSBrent Lu /* no codec conf required */ 7635f706c5eSBrent Lu break; 7645f706c5eSBrent Lu default: 7655f706c5eSBrent Lu dev_err(&pdev->dev, "invalid amp type %d\n", ctx->amp_type); 7665f706c5eSBrent Lu return -EINVAL; 7675f706c5eSBrent Lu } 768a79ae0f6SYong Zhi 769f70abd75SBard liao sof_audio_card_rt5682.dev = &pdev->dev; 770f70abd75SBard liao 771f70abd75SBard liao /* set platform name for each dailink */ 772f70abd75SBard liao ret = snd_soc_fixup_dai_links_platform_name(&sof_audio_card_rt5682, 773f70abd75SBard liao mach->mach_params.platform); 774f70abd75SBard liao if (ret) 775f70abd75SBard liao return ret; 776f70abd75SBard liao 777f70abd75SBard liao snd_soc_card_set_drvdata(&sof_audio_card_rt5682, ctx); 778f70abd75SBard liao 779f70abd75SBard liao return devm_snd_soc_register_card(&pdev->dev, 780f70abd75SBard liao &sof_audio_card_rt5682); 781f70abd75SBard liao } 782f70abd75SBard liao 7836605f0caSSathyanarayana Nujella static const struct platform_device_id board_ids[] = { 7846605f0caSSathyanarayana Nujella { 7856605f0caSSathyanarayana Nujella .name = "sof_rt5682", 78676f33e2fSBrent Lu .driver_data = (kernel_ulong_t)(SOF_RT5682_MCLK_EN | 78776f33e2fSBrent Lu SOF_SSP_PORT_CODEC(2)), 7886605f0caSSathyanarayana Nujella }, 7896605f0caSSathyanarayana Nujella { 79044567d3dSBrent Lu .name = "glk_rt5682_def", 79144567d3dSBrent Lu .driver_data = (kernel_ulong_t)(SOF_RT5682_MCLK_EN | 79244567d3dSBrent Lu SOF_SSP_PORT_CODEC(2) | 79344567d3dSBrent Lu SOF_SSP_PORT_AMP(1)), 79444567d3dSBrent Lu }, 79544567d3dSBrent Lu { 79676fb0d32SBrent Lu .name = "icl_rt5682_def", 79776fb0d32SBrent Lu .driver_data = (kernel_ulong_t)(SOF_RT5682_MCLK_EN | 79876fb0d32SBrent Lu SOF_SSP_PORT_CODEC(0)), 79976fb0d32SBrent Lu }, 80076fb0d32SBrent Lu { 80161cafaeaSBrent Lu .name = "cml_rt5682_def", 8026605f0caSSathyanarayana Nujella .driver_data = (kernel_ulong_t)(SOF_RT5682_MCLK_EN | 8038efcd486SBrent Lu SOF_SSP_PORT_CODEC(0) | 8048efcd486SBrent Lu SOF_SSP_PORT_AMP(1)), 8056605f0caSSathyanarayana Nujella }, 806a79ae0f6SYong Zhi { 8079be229ffSBrent Lu .name = "jsl_rt5682_def", 808db31e3a1SBrent Lu .driver_data = (kernel_ulong_t)(SOF_RT5682_MCLK_EN | 8098efcd486SBrent Lu SOF_SSP_PORT_CODEC(0) | 8108efcd486SBrent Lu SOF_SSP_PORT_AMP(1)), 811db31e3a1SBrent Lu }, 812db31e3a1SBrent Lu { 813dbda8647SBrent Lu .name = "tgl_rt5682_def", 814ad83b1adSBrent Lu .driver_data = (kernel_ulong_t)(SOF_RT5682_MCLK_EN | 8158efcd486SBrent Lu SOF_SSP_PORT_CODEC(0) | 8168efcd486SBrent Lu SOF_SSP_PORT_AMP(1) | 8178efcd486SBrent Lu SOF_NUM_IDISP_HDMI(4) | 8188efcd486SBrent Lu SOF_SSP_PORT_BT_OFFLOAD(2) | 8198efcd486SBrent Lu SOF_BT_OFFLOAD_PRESENT), 820ad83b1adSBrent Lu }, 8212e4dba57SVamshi Krishna Gopal { 82241333c35SBrent Lu .name = "adl_rt5682_def", 8232e4dba57SVamshi Krishna Gopal .driver_data = (kernel_ulong_t)(SOF_RT5682_MCLK_EN | 8248efcd486SBrent Lu SOF_SSP_PORT_CODEC(0) | 8258efcd486SBrent Lu SOF_SSP_PORT_AMP(1) | 8268efcd486SBrent Lu SOF_NUM_IDISP_HDMI(4) | 8278efcd486SBrent Lu SOF_SSP_PORT_BT_OFFLOAD(2) | 8288efcd486SBrent Lu SOF_BT_OFFLOAD_PRESENT), 8292e4dba57SVamshi Krishna Gopal }, 8302e4dba57SVamshi Krishna Gopal { 8313c561a09SBrent Lu .name = "adl_mx98357_rt5682", 8322e4dba57SVamshi Krishna Gopal .driver_data = (kernel_ulong_t)(SOF_RT5682_MCLK_EN | 8338efcd486SBrent Lu SOF_SSP_PORT_CODEC(0) | 8348efcd486SBrent Lu SOF_SSP_PORT_AMP(2) | 8358efcd486SBrent Lu SOF_NUM_IDISP_HDMI(4)), 8362e4dba57SVamshi Krishna Gopal }, 83746414bc3SBrent Lu { 838f3c37847Sapoorv .name = "adl_rt5682_c1_h02", 839f3c37847Sapoorv .driver_data = (kernel_ulong_t)(SOF_RT5682_MCLK_EN | 8408efcd486SBrent Lu SOF_SSP_PORT_CODEC(1) | 841f3c37847Sapoorv /* SSP 0 and SSP 2 are used for HDMI IN */ 8428efcd486SBrent Lu SOF_SSP_MASK_HDMI_CAPTURE(0x5)), 843f3c37847Sapoorv }, 844f3c37847Sapoorv { 84526d9726fSTerry Cheong .name = "rpl_mx98357_rt5682", 84626d9726fSTerry Cheong .driver_data = (kernel_ulong_t)(SOF_RT5682_MCLK_EN | 8478efcd486SBrent Lu SOF_SSP_PORT_CODEC(0) | 8488efcd486SBrent Lu SOF_SSP_PORT_AMP(2) | 8498efcd486SBrent Lu SOF_NUM_IDISP_HDMI(4)), 85026d9726fSTerry Cheong }, 85126d9726fSTerry Cheong { 85219ec6b2eSBrent Lu .name = "rpl_rt5682_def", 8535dc51e50STerry Cheong .driver_data = (kernel_ulong_t)(SOF_RT5682_MCLK_EN | 8548efcd486SBrent Lu SOF_SSP_PORT_CODEC(0) | 8558efcd486SBrent Lu SOF_SSP_PORT_AMP(1) | 8568efcd486SBrent Lu SOF_NUM_IDISP_HDMI(4) | 8578efcd486SBrent Lu SOF_SSP_PORT_BT_OFFLOAD(2) | 8588efcd486SBrent Lu SOF_BT_OFFLOAD_PRESENT), 8595dc51e50STerry Cheong }, 8605dc51e50STerry Cheong { 86114b7ed66SBalamurugan C .name = "rpl_rt5682_c1_h02", 86214b7ed66SBalamurugan C .driver_data = (kernel_ulong_t)(SOF_RT5682_MCLK_EN | 8638efcd486SBrent Lu SOF_SSP_PORT_CODEC(1) | 86414b7ed66SBalamurugan C /* SSP 0 and SSP 2 are used for HDMI IN */ 8658efcd486SBrent Lu SOF_SSP_MASK_HDMI_CAPTURE(0x5)), 86614b7ed66SBalamurugan C }, 86714b7ed66SBalamurugan C { 8681f6645b1SYong Zhi .name = "mtl_mx98357_rt5682", 8691f6645b1SYong Zhi .driver_data = (kernel_ulong_t)(SOF_RT5682_MCLK_EN | 8708efcd486SBrent Lu SOF_SSP_PORT_CODEC(0) | 8718efcd486SBrent Lu SOF_SSP_PORT_AMP(1) | 8728efcd486SBrent Lu SOF_SSP_PORT_BT_OFFLOAD(2) | 8738efcd486SBrent Lu SOF_BT_OFFLOAD_PRESENT), 8741f6645b1SYong Zhi }, 875c0660fceSBrent Lu { 8767e43b75dSDharageswari.R .name = "mtl_mx98360_rt5682", 8777e43b75dSDharageswari.R .driver_data = (kernel_ulong_t)(SOF_RT5682_MCLK_EN | 8788efcd486SBrent Lu SOF_SSP_PORT_CODEC(0) | 879b497654fSBrent Lu SOF_SSP_PORT_AMP(1)), 8807e43b75dSDharageswari.R }, 881b20c8137SMac Chiang { 882922edacfSBrent Lu .name = "mtl_rt5682_def", 883a55ea47bSMac Chiang .driver_data = (kernel_ulong_t)(SOF_RT5682_MCLK_EN | 8848efcd486SBrent Lu SOF_SSP_PORT_CODEC(2) | 8858efcd486SBrent Lu SOF_SSP_PORT_AMP(0) | 8868efcd486SBrent Lu SOF_SSP_PORT_BT_OFFLOAD(1) | 8878efcd486SBrent Lu SOF_BT_OFFLOAD_PRESENT), 888a55ea47bSMac Chiang }, 8896605f0caSSathyanarayana Nujella { } 8906605f0caSSathyanarayana Nujella }; 891a75e5cdfSZou Wei MODULE_DEVICE_TABLE(platform, board_ids); 8926605f0caSSathyanarayana Nujella 893f70abd75SBard liao static struct platform_driver sof_audio = { 894f70abd75SBard liao .probe = sof_audio_probe, 895f70abd75SBard liao .driver = { 896f70abd75SBard liao .name = "sof_rt5682", 897f70abd75SBard liao .pm = &snd_soc_pm_ops, 898f70abd75SBard liao }, 8996605f0caSSathyanarayana Nujella .id_table = board_ids, 900f70abd75SBard liao }; 901f70abd75SBard liao module_platform_driver(sof_audio) 902f70abd75SBard liao 903f70abd75SBard liao /* Module information */ 904f70abd75SBard liao MODULE_DESCRIPTION("SOF Audio Machine driver"); 905f70abd75SBard liao MODULE_AUTHOR("Bard Liao <bard.liao@intel.com>"); 906f70abd75SBard liao MODULE_AUTHOR("Sathya Prakash M R <sathya.prakash.m.r@intel.com>"); 907aa6cc97cSBrent Lu MODULE_AUTHOR("Brent Lu <brent.lu@intel.com>"); 908f316c9d9SMac Chiang MODULE_AUTHOR("Mac Chiang <mac.chiang@intel.com>"); 909f70abd75SBard liao MODULE_LICENSE("GPL v2"); 91089cadbd8SBrent Lu MODULE_IMPORT_NS(SND_SOC_INTEL_SOF_BOARD_HELPERS); 9119c5046e4SPierre-Louis Bossart MODULE_IMPORT_NS(SND_SOC_INTEL_SOF_MAXIM_COMMON); 912e1d5e133SBrent Lu MODULE_IMPORT_NS(SND_SOC_INTEL_SOF_REALTEK_COMMON); 913