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
sof_rt5682_quirk_cb(const struct dmi_system_id * id)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 = {
733e1734b6SSathyanarayana Nujella DMI_MATCH(DMI_PRODUCT_FAMILY, "Google_Volteer"),
742a4b91a2SSathyanarayana Nujella DMI_MATCH(DMI_OEM_STRING, "AUDIO-MAX98373_ALC5682I_I2S_UP4"),
753e1734b6SSathyanarayana Nujella },
763e1734b6SSathyanarayana Nujella .driver_data = (void *)(SOF_RT5682_MCLK_EN |
778efcd486SBrent Lu SOF_SSP_PORT_CODEC(0) |
788efcd486SBrent Lu SOF_SSP_PORT_AMP(2) |
798efcd486SBrent Lu SOF_NUM_IDISP_HDMI(4)),
803e1734b6SSathyanarayana Nujella },
8146fa9a15Sjairaj arava {
8246fa9a15Sjairaj arava .callback = sof_rt5682_quirk_cb,
8346fa9a15Sjairaj arava .matches = {
8446fa9a15Sjairaj arava DMI_MATCH(DMI_SYS_VENDOR, "Intel Corporation"),
8546fa9a15Sjairaj arava DMI_MATCH(DMI_PRODUCT_NAME, "Alder Lake Client Platform"),
8646fa9a15Sjairaj arava DMI_MATCH(DMI_OEM_STRING, "AUDIO-ADL_MAX98373_ALC5682I_I2S"),
8746fa9a15Sjairaj arava },
8846fa9a15Sjairaj arava .driver_data = (void *)(SOF_RT5682_MCLK_EN |
898efcd486SBrent Lu SOF_SSP_PORT_CODEC(0) |
908efcd486SBrent Lu SOF_SSP_PORT_AMP(2) |
918efcd486SBrent Lu SOF_NUM_IDISP_HDMI(4)),
9246fa9a15Sjairaj arava },
93f316c9d9SMac Chiang {
94f316c9d9SMac Chiang .callback = sof_rt5682_quirk_cb,
95f316c9d9SMac Chiang .matches = {
96f316c9d9SMac Chiang DMI_MATCH(DMI_PRODUCT_FAMILY, "Google_Brya"),
97f316c9d9SMac Chiang DMI_MATCH(DMI_OEM_STRING, "AUDIO-MAX98390_ALC5682I_I2S"),
98f316c9d9SMac Chiang },
99f316c9d9SMac Chiang .driver_data = (void *)(SOF_RT5682_MCLK_EN |
1008efcd486SBrent Lu SOF_SSP_PORT_CODEC(0) |
1018efcd486SBrent Lu SOF_SSP_PORT_AMP(2) |
1028efcd486SBrent Lu SOF_NUM_IDISP_HDMI(4)),
103f316c9d9SMac Chiang },
104f316c9d9SMac Chiang {
105f316c9d9SMac Chiang .callback = sof_rt5682_quirk_cb,
106f316c9d9SMac Chiang .matches = {
107f316c9d9SMac Chiang DMI_MATCH(DMI_PRODUCT_FAMILY, "Google_Brya"),
108fcd1e39cSAjye Huang DMI_MATCH(DMI_OEM_STRING, "AUDIO-MAX98360_ALC5682I_I2S_AMP_SSP2"),
109fcd1e39cSAjye Huang },
110fcd1e39cSAjye Huang .driver_data = (void *)(SOF_RT5682_MCLK_EN |
1118efcd486SBrent Lu SOF_SSP_PORT_CODEC(0) |
1128efcd486SBrent Lu SOF_SSP_PORT_AMP(2) |
1138efcd486SBrent Lu SOF_NUM_IDISP_HDMI(4)),
114fcd1e39cSAjye Huang },
115b4dd2e37SYong Zhi {
116b4dd2e37SYong Zhi .callback = sof_rt5682_quirk_cb,
117b4dd2e37SYong Zhi .matches = {
118b4dd2e37SYong Zhi DMI_MATCH(DMI_PRODUCT_FAMILY, "Google_Rex"),
119b4dd2e37SYong Zhi },
120b4dd2e37SYong Zhi .driver_data = (void *)(SOF_RT5682_MCLK_EN |
1218efcd486SBrent Lu SOF_SSP_PORT_CODEC(2) |
1228efcd486SBrent Lu SOF_SSP_PORT_AMP(0) |
1238efcd486SBrent Lu SOF_SSP_PORT_BT_OFFLOAD(1) |
1248efcd486SBrent Lu SOF_BT_OFFLOAD_PRESENT
125b4dd2e37SYong Zhi ),
126b4dd2e37SYong Zhi },
127f70abd75SBard liao {}
128f70abd75SBard liao };
129f70abd75SBard liao
130c3ce12b2SPierre-Louis Bossart static struct snd_soc_jack_pin jack_pins[] = {
131c3ce12b2SPierre-Louis Bossart {
132c3ce12b2SPierre-Louis Bossart .pin = "Headphone Jack",
133c3ce12b2SPierre-Louis Bossart .mask = SND_JACK_HEADPHONE,
134c3ce12b2SPierre-Louis Bossart },
135c3ce12b2SPierre-Louis Bossart {
136c3ce12b2SPierre-Louis Bossart .pin = "Headset Mic",
137c3ce12b2SPierre-Louis Bossart .mask = SND_JACK_MICROPHONE,
138c3ce12b2SPierre-Louis Bossart },
139c3ce12b2SPierre-Louis Bossart };
140c3ce12b2SPierre-Louis Bossart
sof_rt5682_codec_init(struct snd_soc_pcm_runtime * rtd)141f70abd75SBard liao static int sof_rt5682_codec_init(struct snd_soc_pcm_runtime *rtd)
142f70abd75SBard liao {
143f70abd75SBard liao struct sof_card_private *ctx = snd_soc_card_get_drvdata(rtd->card);
144a2c1125eSKuninori Morimoto struct snd_soc_component *component = snd_soc_rtd_to_codec(rtd, 0)->component;
14589cadbd8SBrent Lu struct snd_soc_jack *jack = &ctx->headset_jack;
1466657fcc9SBrent Lu int extra_jack_data;
14795409545SBrent Lu int ret, mclk_freq;
14895409545SBrent Lu
149e91d54f8SBrent Lu if (ctx->rt5682.mclk_en) {
15095409545SBrent Lu mclk_freq = sof_dai_get_mclk(rtd);
15195409545SBrent Lu if (mclk_freq <= 0) {
15295409545SBrent Lu dev_err(rtd->dev, "invalid mclk freq %d\n", mclk_freq);
15395409545SBrent Lu return -EINVAL;
15495409545SBrent Lu }
155f70abd75SBard liao
156f70abd75SBard liao /* need to enable ASRC function for 24MHz mclk rate */
15795409545SBrent Lu if (mclk_freq == 24000000) {
15895409545SBrent Lu dev_info(rtd->dev, "enable ASRC\n");
15995409545SBrent Lu
1605f706c5eSBrent Lu switch (ctx->codec_type) {
1615f706c5eSBrent Lu case CODEC_RT5650:
1626657fcc9SBrent Lu rt5645_sel_asrc_clk_src(component,
1636657fcc9SBrent Lu RT5645_DA_STEREO_FILTER |
1646657fcc9SBrent Lu RT5645_AD_STEREO_FILTER,
1656657fcc9SBrent Lu RT5645_CLK_SEL_I2S1_ASRC);
1666657fcc9SBrent Lu rt5645_sel_asrc_clk_src(component,
1676657fcc9SBrent Lu RT5645_DA_MONO_L_FILTER |
1686657fcc9SBrent Lu RT5645_DA_MONO_R_FILTER,
1696657fcc9SBrent Lu RT5645_CLK_SEL_I2S2_ASRC);
1705f706c5eSBrent Lu break;
1715f706c5eSBrent Lu case CODEC_RT5682:
1729a50d609SBrent Lu rt5682_sel_asrc_clk_src(component,
1739a50d609SBrent Lu RT5682_DA_STEREO1_FILTER |
174f70abd75SBard liao RT5682_AD_STEREO1_FILTER,
175f70abd75SBard liao RT5682_CLK_SEL_I2S1_ASRC);
1765f706c5eSBrent Lu break;
1775f706c5eSBrent Lu case CODEC_RT5682S:
1785f706c5eSBrent Lu rt5682s_sel_asrc_clk_src(component,
1795f706c5eSBrent Lu RT5682S_DA_STEREO1_FILTER |
1805f706c5eSBrent Lu RT5682S_AD_STEREO1_FILTER,
1815f706c5eSBrent Lu RT5682S_CLK_SEL_I2S1_ASRC);
1825f706c5eSBrent Lu break;
1835f706c5eSBrent Lu default:
1845f706c5eSBrent Lu dev_err(rtd->dev, "invalid codec type %d\n",
1855f706c5eSBrent Lu ctx->codec_type);
1865f706c5eSBrent Lu return -EINVAL;
1875f706c5eSBrent Lu }
188f70abd75SBard liao }
189f70abd75SBard liao
190207255f3SBrent Lu if (ctx->rt5682.is_legacy_cpu) {
1911eed6bc0SXun Zhang /*
1921eed6bc0SXun Zhang * The firmware might enable the clock at
1931eed6bc0SXun Zhang * boot (this information may or may not
1941eed6bc0SXun Zhang * be reflected in the enable clock register).
1951eed6bc0SXun Zhang * To change the rate we must disable the clock
1961eed6bc0SXun Zhang * first to cover these cases. Due to common
1971eed6bc0SXun Zhang * clock framework restrictions that do not allow
1981eed6bc0SXun Zhang * to disable a clock that has not been enabled,
1991eed6bc0SXun Zhang * we need to enable the clock first.
2001eed6bc0SXun Zhang */
20189cadbd8SBrent Lu ret = clk_prepare_enable(ctx->rt5682.mclk);
2021eed6bc0SXun Zhang if (!ret)
20389cadbd8SBrent Lu clk_disable_unprepare(ctx->rt5682.mclk);
2041eed6bc0SXun Zhang
20589cadbd8SBrent Lu ret = clk_set_rate(ctx->rt5682.mclk, 19200000);
2061eed6bc0SXun Zhang
2071eed6bc0SXun Zhang if (ret)
2081eed6bc0SXun Zhang dev_err(rtd->dev, "unable to set MCLK rate\n");
2091eed6bc0SXun Zhang }
21095409545SBrent Lu }
2111eed6bc0SXun Zhang
212f70abd75SBard liao /*
213f70abd75SBard liao * Headset buttons map to the google Reference headset.
214f70abd75SBard liao * These can be configured by userspace.
215f70abd75SBard liao */
216c3ce12b2SPierre-Louis Bossart ret = snd_soc_card_jack_new_pins(rtd->card, "Headset Jack",
217f70abd75SBard liao SND_JACK_HEADSET | SND_JACK_BTN_0 |
218f70abd75SBard liao SND_JACK_BTN_1 | SND_JACK_BTN_2 |
219f70abd75SBard liao SND_JACK_BTN_3,
22089cadbd8SBrent Lu jack,
221c3ce12b2SPierre-Louis Bossart jack_pins,
222c3ce12b2SPierre-Louis Bossart ARRAY_SIZE(jack_pins));
223f70abd75SBard liao if (ret) {
224f70abd75SBard liao dev_err(rtd->dev, "Headset Jack creation failed: %d\n", ret);
225f70abd75SBard liao return ret;
226f70abd75SBard liao }
227f70abd75SBard liao
228f70abd75SBard liao snd_jack_set_key(jack->jack, SND_JACK_BTN_0, KEY_PLAYPAUSE);
229d5952f34SSathya Prakash M R snd_jack_set_key(jack->jack, SND_JACK_BTN_1, KEY_VOICECOMMAND);
230d5952f34SSathya Prakash M R snd_jack_set_key(jack->jack, SND_JACK_BTN_2, KEY_VOLUMEUP);
231d5952f34SSathya Prakash M R snd_jack_set_key(jack->jack, SND_JACK_BTN_3, KEY_VOLUMEDOWN);
2326657fcc9SBrent Lu
2335f706c5eSBrent Lu if (ctx->codec_type == CODEC_RT5650) {
2346657fcc9SBrent Lu extra_jack_data = SND_JACK_MICROPHONE | SND_JACK_BTN_0;
2356657fcc9SBrent Lu ret = snd_soc_component_set_jack(component, jack, &extra_jack_data);
2366657fcc9SBrent Lu } else
237f70abd75SBard liao ret = snd_soc_component_set_jack(component, jack, NULL);
238f70abd75SBard liao
239f70abd75SBard liao if (ret) {
240f70abd75SBard liao dev_err(rtd->dev, "Headset Jack call-back failed: %d\n", ret);
241f70abd75SBard liao return ret;
242f70abd75SBard liao }
243f70abd75SBard liao
244f70abd75SBard liao return ret;
245f70abd75SBard liao };
246f70abd75SBard liao
sof_rt5682_codec_exit(struct snd_soc_pcm_runtime * rtd)247b0c96fc1SFred Oh static void sof_rt5682_codec_exit(struct snd_soc_pcm_runtime *rtd)
248b0c96fc1SFred Oh {
249a2c1125eSKuninori Morimoto struct snd_soc_component *component = snd_soc_rtd_to_codec(rtd, 0)->component;
250b0c96fc1SFred Oh
251b0c96fc1SFred Oh snd_soc_component_set_jack(component, NULL, NULL);
252b0c96fc1SFred Oh }
253b0c96fc1SFred Oh
sof_rt5682_hw_params(struct snd_pcm_substream * substream,struct snd_pcm_hw_params * params)254f70abd75SBard liao static int sof_rt5682_hw_params(struct snd_pcm_substream *substream,
255f70abd75SBard liao struct snd_pcm_hw_params *params)
256f70abd75SBard liao {
257a2c1125eSKuninori Morimoto struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream);
2581eed6bc0SXun Zhang struct sof_card_private *ctx = snd_soc_card_get_drvdata(rtd->card);
259a2c1125eSKuninori Morimoto struct snd_soc_dai *codec_dai = snd_soc_rtd_to_codec(rtd, 0);
2609a50d609SBrent Lu int pll_id, pll_source, pll_in, pll_out, clk_id, ret;
261f70abd75SBard liao
262e91d54f8SBrent Lu if (ctx->rt5682.mclk_en) {
263207255f3SBrent Lu if (ctx->rt5682.is_legacy_cpu) {
26489cadbd8SBrent Lu ret = clk_prepare_enable(ctx->rt5682.mclk);
2651eed6bc0SXun Zhang if (ret < 0) {
2661eed6bc0SXun Zhang dev_err(rtd->dev,
2671eed6bc0SXun Zhang "could not configure MCLK state");
2681eed6bc0SXun Zhang return ret;
2691eed6bc0SXun Zhang }
2701eed6bc0SXun Zhang }
2711eed6bc0SXun Zhang
2725f706c5eSBrent Lu switch (ctx->codec_type) {
2735f706c5eSBrent Lu case CODEC_RT5650:
2746657fcc9SBrent Lu pll_source = RT5645_PLL1_S_MCLK;
2755f706c5eSBrent Lu break;
2765f706c5eSBrent Lu case CODEC_RT5682:
2779a50d609SBrent Lu pll_source = RT5682_PLL1_S_MCLK;
2785f706c5eSBrent Lu break;
2795f706c5eSBrent Lu case CODEC_RT5682S:
2805f706c5eSBrent Lu pll_source = RT5682S_PLL_S_MCLK;
2815f706c5eSBrent Lu break;
2825f706c5eSBrent Lu default:
2835f706c5eSBrent Lu dev_err(rtd->dev, "invalid codec type %d\n",
2845f706c5eSBrent Lu ctx->codec_type);
2855f706c5eSBrent Lu return -EINVAL;
2865f706c5eSBrent Lu }
287bf939446SKeyon Jie
288bf939446SKeyon Jie /* get the tplg configured mclk. */
2899a50d609SBrent Lu pll_in = sof_dai_get_mclk(rtd);
29095409545SBrent Lu if (pll_in <= 0) {
29195409545SBrent Lu dev_err(rtd->dev, "invalid mclk freq %d\n", pll_in);
29295409545SBrent Lu return -EINVAL;
293bf939446SKeyon Jie }
294f70abd75SBard liao } else {
2955f706c5eSBrent Lu switch (ctx->codec_type) {
2965f706c5eSBrent Lu case CODEC_RT5650:
2976657fcc9SBrent Lu pll_source = RT5645_PLL1_S_BCLK1;
2985f706c5eSBrent Lu break;
2995f706c5eSBrent Lu case CODEC_RT5682:
3009a50d609SBrent Lu pll_source = RT5682_PLL1_S_BCLK1;
3015f706c5eSBrent Lu break;
3025f706c5eSBrent Lu case CODEC_RT5682S:
3035f706c5eSBrent Lu pll_source = RT5682S_PLL_S_BCLK1;
3045f706c5eSBrent Lu break;
3055f706c5eSBrent Lu default:
3065f706c5eSBrent Lu dev_err(rtd->dev, "invalid codec type %d\n",
3075f706c5eSBrent Lu ctx->codec_type);
3085f706c5eSBrent Lu return -EINVAL;
3095f706c5eSBrent Lu }
3109a50d609SBrent Lu
3114524b1e3SBrent Lu /* get the tplg configured bclk. */
3124524b1e3SBrent Lu pll_in = sof_dai_get_bclk(rtd);
3134524b1e3SBrent Lu if (pll_in <= 0) {
3144524b1e3SBrent Lu dev_err(rtd->dev, "invalid bclk freq %d\n", pll_in);
3154524b1e3SBrent Lu return -EINVAL;
3164524b1e3SBrent Lu }
3179a50d609SBrent Lu }
3189a50d609SBrent Lu
319b5aaf6a5SBrent Lu pll_out = params_rate(params) * 512;
320b5aaf6a5SBrent Lu
321b5aaf6a5SBrent Lu /* when MCLK is 512FS, no need to set PLL configuration additionally. */
322b5aaf6a5SBrent Lu if (pll_in == pll_out) {
323b5aaf6a5SBrent Lu switch (ctx->codec_type) {
324b5aaf6a5SBrent Lu case CODEC_RT5650:
325b5aaf6a5SBrent Lu clk_id = RT5645_SCLK_S_MCLK;
326b5aaf6a5SBrent Lu break;
327b5aaf6a5SBrent Lu case CODEC_RT5682:
328b5aaf6a5SBrent Lu clk_id = RT5682_SCLK_S_MCLK;
329b5aaf6a5SBrent Lu break;
330b5aaf6a5SBrent Lu case CODEC_RT5682S:
331b5aaf6a5SBrent Lu clk_id = RT5682S_SCLK_S_MCLK;
332b5aaf6a5SBrent Lu break;
333b5aaf6a5SBrent Lu default:
334b5aaf6a5SBrent Lu dev_err(rtd->dev, "invalid codec type %d\n",
335b5aaf6a5SBrent Lu ctx->codec_type);
336b5aaf6a5SBrent Lu return -EINVAL;
337b5aaf6a5SBrent Lu }
338b5aaf6a5SBrent Lu } else {
3395f706c5eSBrent Lu switch (ctx->codec_type) {
3405f706c5eSBrent Lu case CODEC_RT5650:
3416657fcc9SBrent Lu pll_id = 0; /* not used in codec driver */
3426657fcc9SBrent Lu clk_id = RT5645_SCLK_S_PLL1;
3435f706c5eSBrent Lu break;
3445f706c5eSBrent Lu case CODEC_RT5682:
3459a50d609SBrent Lu pll_id = RT5682_PLL1;
3469a50d609SBrent Lu clk_id = RT5682_SCLK_S_PLL1;
3475f706c5eSBrent Lu break;
3485f706c5eSBrent Lu case CODEC_RT5682S:
3493d84e070SBrent Lu /* check plla_table and pllb_table in rt5682s.c */
3503d84e070SBrent Lu switch (pll_in) {
3513d84e070SBrent Lu case 3072000:
3523d84e070SBrent Lu case 24576000:
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 pll_id = RT5682S_PLL1;
360dcc2cd80SBard Liao clk_id = RT5682S_SCLK_S_PLL1;
3613d84e070SBrent Lu break;
3623d84e070SBrent Lu default:
3635f706c5eSBrent Lu pll_id = RT5682S_PLL2;
3645f706c5eSBrent Lu clk_id = RT5682S_SCLK_S_PLL2;
3653d84e070SBrent Lu break;
366dcc2cd80SBard Liao }
3675f706c5eSBrent Lu break;
3685f706c5eSBrent Lu default:
3695f706c5eSBrent Lu dev_err(rtd->dev, "invalid codec type %d\n", ctx->codec_type);
3705f706c5eSBrent Lu return -EINVAL;
371f70abd75SBard liao }
372f70abd75SBard liao
3739a50d609SBrent Lu /* Configure pll for codec */
3749a50d609SBrent Lu ret = snd_soc_dai_set_pll(codec_dai, pll_id, pll_source, pll_in,
3759a50d609SBrent Lu pll_out);
376f70abd75SBard liao if (ret < 0)
377f70abd75SBard liao dev_err(rtd->dev, "snd_soc_dai_set_pll err = %d\n", ret);
378dbf2f8e3SMac Chiang }
379f70abd75SBard liao
380f70abd75SBard liao /* Configure sysclk for codec */
3819a50d609SBrent Lu ret = snd_soc_dai_set_sysclk(codec_dai, clk_id,
382f70abd75SBard liao pll_out, SND_SOC_CLOCK_IN);
383f70abd75SBard liao if (ret < 0)
384f70abd75SBard liao dev_err(rtd->dev, "snd_soc_dai_set_sysclk err = %d\n", ret);
385f70abd75SBard liao
386f70abd75SBard liao /*
387f70abd75SBard liao * slot_width should equal or large than data length, set them
388f70abd75SBard liao * be the same
389f70abd75SBard liao */
390f70abd75SBard liao ret = snd_soc_dai_set_tdm_slot(codec_dai, 0x0, 0x0, 2,
391f70abd75SBard liao params_width(params));
392f70abd75SBard liao if (ret < 0) {
393f70abd75SBard liao dev_err(rtd->dev, "set TDM slot err:%d\n", ret);
394f70abd75SBard liao return ret;
395f70abd75SBard liao }
396f70abd75SBard liao
397f70abd75SBard liao return ret;
398f70abd75SBard liao }
399f70abd75SBard liao
400ed258130SChristophe JAILLET static const struct snd_soc_ops sof_rt5682_ops = {
401f70abd75SBard liao .hw_params = sof_rt5682_hw_params,
402f70abd75SBard liao };
403f70abd75SBard liao
sof_card_late_probe(struct snd_soc_card * card)404f70abd75SBard liao static int sof_card_late_probe(struct snd_soc_card *card)
405f70abd75SBard liao {
406f70abd75SBard liao struct sof_card_private *ctx = snd_soc_card_get_drvdata(card);
40794d2d089SDharageswari R struct snd_soc_dapm_context *dapm = &card->dapm;
40898ff5c26SGuennadi Liakhovetski int err;
409f70abd75SBard liao
4105f706c5eSBrent Lu if (ctx->amp_type == CODEC_MAX98373) {
411371a3f01SYong Zhi /* Disable Left and Right Spk pin after boot */
412371a3f01SYong Zhi snd_soc_dapm_disable_pin(dapm, "Left Spk");
413371a3f01SYong Zhi snd_soc_dapm_disable_pin(dapm, "Right Spk");
414371a3f01SYong Zhi err = snd_soc_dapm_sync(dapm);
415371a3f01SYong Zhi if (err < 0)
416371a3f01SYong Zhi return err;
417371a3f01SYong Zhi }
418371a3f01SYong Zhi
41989cadbd8SBrent Lu return sof_intel_board_card_late_probe(card);
42098ff5c26SGuennadi Liakhovetski }
42159bbd703SKai Vehmanen
422f70abd75SBard liao static const struct snd_kcontrol_new sof_controls[] = {
423f70abd75SBard liao SOC_DAPM_PIN_SWITCH("Headphone Jack"),
424f70abd75SBard liao SOC_DAPM_PIN_SWITCH("Headset Mic"),
425f70abd75SBard liao };
426f70abd75SBard liao
427f70abd75SBard liao static const struct snd_soc_dapm_widget sof_widgets[] = {
428f70abd75SBard liao SND_SOC_DAPM_HP("Headphone Jack", NULL),
429f70abd75SBard liao SND_SOC_DAPM_MIC("Headset Mic", NULL),
4304413adc4SBard Liao };
4314413adc4SBard Liao
432f70abd75SBard liao static const struct snd_soc_dapm_route sof_map[] = {
433f70abd75SBard liao /* HP jack connectors - unknown if we have jack detection */
434f70abd75SBard liao { "Headphone Jack", NULL, "HPOL" },
435f70abd75SBard liao { "Headphone Jack", NULL, "HPOR" },
436f70abd75SBard liao
437f70abd75SBard liao /* other jacks */
438f70abd75SBard liao { "IN1P", NULL, "Headset Mic" },
439f70abd75SBard liao };
440f70abd75SBard liao
441d2d377fcSBrent Lu static const struct snd_kcontrol_new rt5650_spk_kcontrols[] = {
442d2d377fcSBrent Lu SOC_DAPM_PIN_SWITCH("Left Spk"),
443d2d377fcSBrent Lu SOC_DAPM_PIN_SWITCH("Right Spk"),
444d2d377fcSBrent Lu
445d2d377fcSBrent Lu };
446d2d377fcSBrent Lu
447d2d377fcSBrent Lu static const struct snd_soc_dapm_widget rt5650_spk_widgets[] = {
448d2d377fcSBrent Lu SND_SOC_DAPM_SPK("Left Spk", NULL),
449d2d377fcSBrent Lu SND_SOC_DAPM_SPK("Right Spk", NULL),
450d2d377fcSBrent Lu };
451d2d377fcSBrent Lu
4526657fcc9SBrent Lu static const struct snd_soc_dapm_route rt5650_spk_dapm_routes[] = {
4536657fcc9SBrent Lu /* speaker */
4546657fcc9SBrent Lu { "Left Spk", NULL, "SPOL" },
4556657fcc9SBrent Lu { "Right Spk", NULL, "SPOR" },
4566657fcc9SBrent Lu };
4576657fcc9SBrent Lu
rt5650_spk_init(struct snd_soc_pcm_runtime * rtd)4586657fcc9SBrent Lu static int rt5650_spk_init(struct snd_soc_pcm_runtime *rtd)
4596657fcc9SBrent Lu {
4606657fcc9SBrent Lu struct snd_soc_card *card = rtd->card;
4616657fcc9SBrent Lu int ret;
4626657fcc9SBrent Lu
463d2d377fcSBrent Lu ret = snd_soc_dapm_new_controls(&card->dapm, rt5650_spk_widgets,
464d2d377fcSBrent Lu ARRAY_SIZE(rt5650_spk_widgets));
465d2d377fcSBrent Lu if (ret) {
466d2d377fcSBrent Lu dev_err(rtd->dev, "fail to add rt5650 spk widgets, ret %d\n",
467d2d377fcSBrent Lu ret);
468d2d377fcSBrent Lu return ret;
469d2d377fcSBrent Lu }
470d2d377fcSBrent Lu
471d2d377fcSBrent Lu ret = snd_soc_add_card_controls(card, rt5650_spk_kcontrols,
472d2d377fcSBrent Lu ARRAY_SIZE(rt5650_spk_kcontrols));
473d2d377fcSBrent Lu if (ret) {
474d2d377fcSBrent Lu dev_err(rtd->dev, "fail to add rt5650 spk kcontrols, ret %d\n",
475d2d377fcSBrent Lu ret);
476d2d377fcSBrent Lu return ret;
477d2d377fcSBrent Lu }
478d2d377fcSBrent Lu
4796657fcc9SBrent Lu ret = snd_soc_dapm_add_routes(&card->dapm, rt5650_spk_dapm_routes,
4806657fcc9SBrent Lu ARRAY_SIZE(rt5650_spk_dapm_routes));
4816657fcc9SBrent Lu if (ret)
4826657fcc9SBrent Lu dev_err(rtd->dev, "fail to add dapm routes, ret=%d\n", ret);
4836657fcc9SBrent Lu
4846657fcc9SBrent Lu return ret;
4856657fcc9SBrent Lu }
4866657fcc9SBrent Lu
487f70abd75SBard liao /* sof audio machine driver for rt5682 codec */
488f70abd75SBard liao static struct snd_soc_card sof_audio_card_rt5682 = {
489d745cc1aSJaroslav Kysela .name = "rt5682", /* the sof- prefix is added by the core */
490f70abd75SBard liao .owner = THIS_MODULE,
491f70abd75SBard liao .controls = sof_controls,
492f70abd75SBard liao .num_controls = ARRAY_SIZE(sof_controls),
493f70abd75SBard liao .dapm_widgets = sof_widgets,
494f70abd75SBard liao .num_dapm_widgets = ARRAY_SIZE(sof_widgets),
495f70abd75SBard liao .dapm_routes = sof_map,
496f70abd75SBard liao .num_dapm_routes = ARRAY_SIZE(sof_map),
497f70abd75SBard liao .fully_routed = true,
498f70abd75SBard liao .late_probe = sof_card_late_probe,
499f70abd75SBard liao };
500f70abd75SBard liao
501f70abd75SBard liao static struct snd_soc_dai_link_component rt5682_component[] = {
502f70abd75SBard liao {
503f70abd75SBard liao .name = "i2c-10EC5682:00",
504f70abd75SBard liao .dai_name = "rt5682-aif1",
505f70abd75SBard liao }
506f70abd75SBard liao };
507f70abd75SBard liao
5089a50d609SBrent Lu static struct snd_soc_dai_link_component rt5682s_component[] = {
5099a50d609SBrent Lu {
5109a50d609SBrent Lu .name = "i2c-RTL5682:00",
5119a50d609SBrent Lu .dai_name = "rt5682s-aif1",
5129a50d609SBrent Lu }
5139a50d609SBrent Lu };
5149a50d609SBrent Lu
5156657fcc9SBrent Lu static struct snd_soc_dai_link_component rt5650_components[] = {
5166657fcc9SBrent Lu {
5176657fcc9SBrent Lu .name = "i2c-10EC5650:00",
5186657fcc9SBrent Lu .dai_name = "rt5645-aif1",
5196657fcc9SBrent Lu },
5206657fcc9SBrent Lu {
5216657fcc9SBrent Lu .name = "i2c-10EC5650:00",
5226657fcc9SBrent Lu .dai_name = "rt5645-aif2",
5236657fcc9SBrent Lu }
5246657fcc9SBrent Lu };
5256657fcc9SBrent Lu
5268fa1116eSBrent Lu static int
sof_card_dai_links_create(struct device * dev,struct snd_soc_card * card,struct sof_card_private * ctx)5278fa1116eSBrent Lu sof_card_dai_links_create(struct device *dev, struct snd_soc_card *card,
5288fa1116eSBrent Lu struct sof_card_private *ctx)
529f70abd75SBard liao {
53089cadbd8SBrent Lu int ret;
531f70abd75SBard liao
5328fa1116eSBrent Lu ret = sof_intel_board_set_dai_link(dev, card, ctx);
53384c280afSBrent Lu if (ret)
5348fa1116eSBrent Lu return ret;
535f70abd75SBard liao
5368fa1116eSBrent Lu if (!ctx->codec_link) {
5378fa1116eSBrent Lu dev_err(dev, "codec link not available");
5388fa1116eSBrent Lu return -EINVAL;
5399a50d609SBrent Lu }
5405f706c5eSBrent Lu
5418fa1116eSBrent Lu /* codec-specific fields for headphone codec */
5428fa1116eSBrent Lu switch (ctx->codec_type) {
5438fa1116eSBrent Lu case CODEC_RT5650:
5448fa1116eSBrent Lu ctx->codec_link->codecs = &rt5650_components[0];
5458fa1116eSBrent Lu ctx->codec_link->num_codecs = 1;
5468fa1116eSBrent Lu break;
5478fa1116eSBrent Lu case CODEC_RT5682:
5488fa1116eSBrent Lu ctx->codec_link->codecs = rt5682_component;
5498fa1116eSBrent Lu ctx->codec_link->num_codecs = ARRAY_SIZE(rt5682_component);
5508fa1116eSBrent Lu break;
5518fa1116eSBrent Lu case CODEC_RT5682S:
5528fa1116eSBrent Lu ctx->codec_link->codecs = rt5682s_component;
5538fa1116eSBrent Lu ctx->codec_link->num_codecs = ARRAY_SIZE(rt5682s_component);
5548fa1116eSBrent Lu break;
5558fa1116eSBrent Lu default:
5568fa1116eSBrent Lu dev_err(dev, "invalid codec type %d\n", ctx->codec_type);
5578fa1116eSBrent Lu return -EINVAL;
5588fa1116eSBrent Lu }
55984c280afSBrent Lu
5608fa1116eSBrent Lu ctx->codec_link->init = sof_rt5682_codec_init;
5618fa1116eSBrent Lu ctx->codec_link->exit = sof_rt5682_codec_exit;
5628fa1116eSBrent Lu ctx->codec_link->ops = &sof_rt5682_ops;
5638fa1116eSBrent Lu
5648fa1116eSBrent Lu if (!ctx->rt5682.is_legacy_cpu) {
565f70abd75SBard liao /*
566f70abd75SBard liao * Currently, On SKL+ platforms MCLK will be turned off in sof
567f70abd75SBard liao * runtime suspended, and it will go into runtime suspended
568f70abd75SBard liao * right after playback is stop. However, rt5682 will output
569f70abd75SBard liao * static noise if sysclk turns off during playback. Set
570f70abd75SBard liao * ignore_pmdown_time to power down rt5682 immediately and
571f70abd75SBard liao * avoid the noise.
572f70abd75SBard liao * It can be removed once we can control MCLK by driver.
573f70abd75SBard liao */
5748fa1116eSBrent Lu ctx->codec_link->ignore_pmdown_time = 1;
575e711223aSKeyon Jie }
576f70abd75SBard liao
5778fa1116eSBrent Lu if (ctx->amp_type == CODEC_NONE)
5788fa1116eSBrent Lu return 0;
579c51fc25dSBrent Lu
5808fa1116eSBrent Lu if (!ctx->amp_link) {
5818fa1116eSBrent Lu dev_err(dev, "amp link not available");
5828fa1116eSBrent Lu return -EINVAL;
583f70abd75SBard liao }
584f70abd75SBard liao
5858fa1116eSBrent Lu /* codec-specific fields for speaker amplifier */
5868fa1116eSBrent Lu switch (ctx->amp_type) {
5875f706c5eSBrent Lu case CODEC_MAX98357A:
5888fa1116eSBrent Lu max_98357a_dai_link(ctx->amp_link);
5895f706c5eSBrent Lu break;
5905f706c5eSBrent Lu case CODEC_MAX98360A:
5918fa1116eSBrent Lu max_98360a_dai_link(ctx->amp_link);
5925f706c5eSBrent Lu break;
5935f706c5eSBrent Lu case CODEC_MAX98373:
594834c4f95SBrent Lu max_98373_dai_link(dev, ctx->amp_link);
5955f706c5eSBrent Lu break;
5965f706c5eSBrent Lu case CODEC_MAX98390:
5978fa1116eSBrent Lu max_98390_dai_link(dev, ctx->amp_link);
5985f706c5eSBrent Lu break;
5995f706c5eSBrent Lu case CODEC_RT1011:
600551fb559SBrent Lu sof_rt1011_dai_link(dev, ctx->amp_link);
6015f706c5eSBrent Lu break;
6025f706c5eSBrent Lu case CODEC_RT1015:
6038fa1116eSBrent Lu sof_rt1015_dai_link(ctx->amp_link);
6045f706c5eSBrent Lu break;
6055f706c5eSBrent Lu case CODEC_RT1015P:
6068fa1116eSBrent Lu sof_rt1015p_dai_link(ctx->amp_link);
6075f706c5eSBrent Lu break;
6085f706c5eSBrent Lu case CODEC_RT1019P:
6098fa1116eSBrent Lu sof_rt1019p_dai_link(ctx->amp_link);
6105f706c5eSBrent Lu break;
6115f706c5eSBrent Lu case CODEC_RT5650:
6125f706c5eSBrent Lu /* use AIF2 to support speaker pipeline */
6138fa1116eSBrent Lu ctx->amp_link->codecs = &rt5650_components[1];
6148fa1116eSBrent Lu ctx->amp_link->num_codecs = 1;
6158fa1116eSBrent Lu ctx->amp_link->init = rt5650_spk_init;
6168fa1116eSBrent Lu ctx->amp_link->ops = &sof_rt5682_ops;
6175f706c5eSBrent Lu break;
6185f706c5eSBrent Lu default:
6198fa1116eSBrent Lu dev_err(dev, "invalid amp type %d\n", ctx->amp_type);
6208fa1116eSBrent Lu return -EINVAL;
621a79ae0f6SYong Zhi }
6225f706c5eSBrent Lu
6238fa1116eSBrent Lu return 0;
624f70abd75SBard liao }
625f70abd75SBard liao
62644567d3dSBrent Lu #define GLK_LINK_ORDER SOF_LINK_ORDER(SOF_LINK_AMP, \
62744567d3dSBrent Lu SOF_LINK_CODEC, \
62844567d3dSBrent Lu SOF_LINK_DMIC01, \
62944567d3dSBrent Lu SOF_LINK_IDISP_HDMI, \
63044567d3dSBrent Lu SOF_LINK_NONE, \
63144567d3dSBrent Lu SOF_LINK_NONE, \
63244567d3dSBrent Lu SOF_LINK_NONE)
63344567d3dSBrent Lu
sof_audio_probe(struct platform_device * pdev)634f70abd75SBard liao static int sof_audio_probe(struct platform_device *pdev)
635f70abd75SBard liao {
6363de206a4SBrent Lu struct snd_soc_acpi_mach *mach = pdev->dev.platform_data;
637f70abd75SBard liao struct sof_card_private *ctx;
6386136d879SBrent Lu char *card_name;
639e45cd972SBrent Lu int ret;
640f70abd75SBard liao
6416605f0caSSathyanarayana Nujella if (pdev->id_entry && pdev->id_entry->driver_data)
6426605f0caSSathyanarayana Nujella sof_rt5682_quirk = (unsigned long)pdev->id_entry->driver_data;
6436605f0caSSathyanarayana Nujella
644c68e0797SSathyanarayana Nujella dmi_check_system(sof_rt5682_quirk_table);
645c68e0797SSathyanarayana Nujella
6468efcd486SBrent Lu dev_dbg(&pdev->dev, "sof_rt5682_quirk = %lx\n", sof_rt5682_quirk);
6478efcd486SBrent Lu
6488efcd486SBrent Lu /* initialize ctx with board quirk */
6498efcd486SBrent Lu ctx = sof_intel_board_get_ctx(&pdev->dev, sof_rt5682_quirk);
6508efcd486SBrent Lu if (!ctx)
6518efcd486SBrent Lu return -ENOMEM;
652d4b74e21SSam McNally
6535f706c5eSBrent Lu if (ctx->codec_type == CODEC_RT5650) {
6546136d879SBrent Lu card_name = devm_kstrdup(&pdev->dev, "rt5650", GFP_KERNEL);
6556136d879SBrent Lu if (!card_name)
6566136d879SBrent Lu return -ENOMEM;
6576136d879SBrent Lu
6586136d879SBrent Lu sof_audio_card_rt5682.name = card_name;
6595f706c5eSBrent Lu
6605f706c5eSBrent Lu /* create speaker dai link also */
6615f706c5eSBrent Lu if (ctx->amp_type == CODEC_NONE)
6625f706c5eSBrent Lu ctx->amp_type = CODEC_RT5650;
6636657fcc9SBrent Lu }
6648fe6ec03SBrent Lu
66544567d3dSBrent Lu if (mach->mach_params.codec_mask & IDISP_CODEC_MASK)
66644567d3dSBrent Lu ctx->hdmi.idisp_codec = true;
6676136d879SBrent Lu
66876f33e2fSBrent Lu if (soc_intel_is_byt() || soc_intel_is_cht()) {
66989cadbd8SBrent Lu ctx->rt5682.is_legacy_cpu = true;
670c51fc25dSBrent Lu ctx->dmic_be_num = 0;
67189cadbd8SBrent Lu /* HDMI is not supported by SOF on Baytrail/CherryTrail */
67289cadbd8SBrent Lu ctx->hdmi_num = 0;
67344567d3dSBrent Lu } else if (soc_intel_is_glk()) {
67444567d3dSBrent Lu /* dmic16k not support */
67544567d3dSBrent Lu ctx->dmic_be_num = 1;
67644567d3dSBrent Lu
67744567d3dSBrent Lu /* overwrite the DAI link order for GLK boards */
67844567d3dSBrent Lu ctx->link_order_overwrite = GLK_LINK_ORDER;
6795498a4edSBrent Lu
6805498a4edSBrent Lu /* backward-compatible with existing devices */
6815498a4edSBrent Lu switch (ctx->amp_type) {
6825498a4edSBrent Lu case CODEC_MAX98357A:
6835498a4edSBrent Lu card_name = devm_kstrdup(&pdev->dev, "glkrt5682max",
6845498a4edSBrent Lu GFP_KERNEL);
6855498a4edSBrent Lu if (!card_name)
6865498a4edSBrent Lu return -ENOMEM;
6875498a4edSBrent Lu
6885498a4edSBrent Lu sof_audio_card_rt5682.name = card_name;
6895498a4edSBrent Lu break;
6905498a4edSBrent Lu default:
6915498a4edSBrent Lu break;
6925498a4edSBrent Lu }
69344567d3dSBrent Lu } else if (soc_intel_is_cml()) {
69444567d3dSBrent Lu /* backward-compatible with existing devices */
69544567d3dSBrent Lu switch (ctx->amp_type) {
69644567d3dSBrent Lu case CODEC_RT1011:
69744567d3dSBrent Lu card_name = devm_kstrdup(&pdev->dev, "cml_rt1011_rt5682",
69844567d3dSBrent Lu GFP_KERNEL);
69944567d3dSBrent Lu if (!card_name)
70044567d3dSBrent Lu return -ENOMEM;
70144567d3dSBrent Lu
70244567d3dSBrent Lu sof_audio_card_rt5682.name = card_name;
70344567d3dSBrent Lu break;
70444567d3dSBrent Lu default:
70544567d3dSBrent Lu break;
70644567d3dSBrent Lu }
707f70abd75SBard liao }
708f70abd75SBard liao
709207255f3SBrent Lu if (sof_rt5682_quirk & SOF_RT5682_MCLK_EN) {
710e91d54f8SBrent Lu ctx->rt5682.mclk_en = true;
711e91d54f8SBrent Lu
7121eed6bc0SXun Zhang /* need to get main clock from pmc */
713207255f3SBrent Lu if (ctx->rt5682.is_legacy_cpu) {
71489cadbd8SBrent Lu ctx->rt5682.mclk = devm_clk_get(&pdev->dev, "pmc_plt_clk_3");
71589cadbd8SBrent Lu if (IS_ERR(ctx->rt5682.mclk)) {
71689cadbd8SBrent Lu ret = PTR_ERR(ctx->rt5682.mclk);
717e5f0d490SChuhong Yuan
718e5f0d490SChuhong Yuan dev_err(&pdev->dev,
719e5f0d490SChuhong Yuan "Failed to get MCLK from pmc_plt_clk_3: %d\n",
720e5f0d490SChuhong Yuan ret);
721e5f0d490SChuhong Yuan return ret;
722e5f0d490SChuhong Yuan }
723e5f0d490SChuhong Yuan
72489cadbd8SBrent Lu ret = clk_prepare_enable(ctx->rt5682.mclk);
7251eed6bc0SXun Zhang if (ret < 0) {
7261eed6bc0SXun Zhang dev_err(&pdev->dev,
7271eed6bc0SXun Zhang "could not configure MCLK state");
7281eed6bc0SXun Zhang return ret;
7291eed6bc0SXun Zhang }
7301eed6bc0SXun Zhang }
731207255f3SBrent Lu }
7321eed6bc0SXun Zhang
7338fa1116eSBrent Lu /* update dai_link */
7348fa1116eSBrent Lu ret = sof_card_dai_links_create(&pdev->dev, &sof_audio_card_rt5682, ctx);
7358fa1116eSBrent Lu if (ret)
7368fa1116eSBrent Lu return ret;
737f70abd75SBard liao
7385f706c5eSBrent Lu /* update codec_conf */
7395f706c5eSBrent Lu switch (ctx->amp_type) {
7405f706c5eSBrent Lu case CODEC_MAX98373:
7415f706c5eSBrent Lu max_98373_set_codec_conf(&sof_audio_card_rt5682);
7425f706c5eSBrent Lu break;
7435f706c5eSBrent Lu case CODEC_MAX98390:
7445f706c5eSBrent Lu max_98390_set_codec_conf(&pdev->dev, &sof_audio_card_rt5682);
7455f706c5eSBrent Lu break;
7465f706c5eSBrent Lu case CODEC_RT1011:
747551fb559SBrent Lu sof_rt1011_codec_conf(&pdev->dev, &sof_audio_card_rt5682);
7485f706c5eSBrent Lu break;
7495f706c5eSBrent Lu case CODEC_RT1015:
75077659872SYong Zhi sof_rt1015_codec_conf(&sof_audio_card_rt5682);
7515f706c5eSBrent Lu break;
7525f706c5eSBrent Lu case CODEC_RT1015P:
7535f706c5eSBrent Lu sof_rt1015p_codec_conf(&sof_audio_card_rt5682);
7545f706c5eSBrent Lu break;
7555f706c5eSBrent Lu case CODEC_MAX98357A:
7565f706c5eSBrent Lu case CODEC_MAX98360A:
7575f706c5eSBrent Lu case CODEC_RT1019P:
7585f706c5eSBrent Lu case CODEC_RT5650:
759b497654fSBrent Lu case CODEC_NONE:
7605f706c5eSBrent Lu /* no codec conf required */
7615f706c5eSBrent Lu break;
7625f706c5eSBrent Lu default:
7635f706c5eSBrent Lu dev_err(&pdev->dev, "invalid amp type %d\n", ctx->amp_type);
7645f706c5eSBrent Lu return -EINVAL;
7655f706c5eSBrent Lu }
766a79ae0f6SYong Zhi
767f70abd75SBard liao sof_audio_card_rt5682.dev = &pdev->dev;
768f70abd75SBard liao
769f70abd75SBard liao /* set platform name for each dailink */
770f70abd75SBard liao ret = snd_soc_fixup_dai_links_platform_name(&sof_audio_card_rt5682,
771f70abd75SBard liao mach->mach_params.platform);
772f70abd75SBard liao if (ret)
773f70abd75SBard liao return ret;
774f70abd75SBard liao
775f70abd75SBard liao snd_soc_card_set_drvdata(&sof_audio_card_rt5682, ctx);
776f70abd75SBard liao
777f70abd75SBard liao return devm_snd_soc_register_card(&pdev->dev,
778f70abd75SBard liao &sof_audio_card_rt5682);
779f70abd75SBard liao }
780f70abd75SBard liao
7816605f0caSSathyanarayana Nujella static const struct platform_device_id board_ids[] = {
7826605f0caSSathyanarayana Nujella {
7836605f0caSSathyanarayana Nujella .name = "sof_rt5682",
78476f33e2fSBrent Lu .driver_data = (kernel_ulong_t)(SOF_RT5682_MCLK_EN |
78576f33e2fSBrent Lu SOF_SSP_PORT_CODEC(2)),
7866605f0caSSathyanarayana Nujella },
7876605f0caSSathyanarayana Nujella {
78844567d3dSBrent Lu .name = "glk_rt5682_def",
78944567d3dSBrent Lu .driver_data = (kernel_ulong_t)(SOF_RT5682_MCLK_EN |
79044567d3dSBrent Lu SOF_SSP_PORT_CODEC(2) |
79144567d3dSBrent Lu SOF_SSP_PORT_AMP(1)),
79244567d3dSBrent Lu },
79344567d3dSBrent Lu {
79476fb0d32SBrent Lu .name = "icl_rt5682_def",
79576fb0d32SBrent Lu .driver_data = (kernel_ulong_t)(SOF_RT5682_MCLK_EN |
79676fb0d32SBrent Lu SOF_SSP_PORT_CODEC(0)),
79776fb0d32SBrent Lu },
79876fb0d32SBrent Lu {
79961cafaeaSBrent Lu .name = "cml_rt5682_def",
8006605f0caSSathyanarayana Nujella .driver_data = (kernel_ulong_t)(SOF_RT5682_MCLK_EN |
8018efcd486SBrent Lu SOF_SSP_PORT_CODEC(0) |
8028efcd486SBrent Lu SOF_SSP_PORT_AMP(1)),
8036605f0caSSathyanarayana Nujella },
804a79ae0f6SYong Zhi {
8059be229ffSBrent Lu .name = "jsl_rt5682_def",
806db31e3a1SBrent Lu .driver_data = (kernel_ulong_t)(SOF_RT5682_MCLK_EN |
8078efcd486SBrent Lu SOF_SSP_PORT_CODEC(0) |
8088efcd486SBrent Lu SOF_SSP_PORT_AMP(1)),
809db31e3a1SBrent Lu },
810db31e3a1SBrent Lu {
811dbda8647SBrent Lu .name = "tgl_rt5682_def",
812ad83b1adSBrent Lu .driver_data = (kernel_ulong_t)(SOF_RT5682_MCLK_EN |
8138efcd486SBrent Lu SOF_SSP_PORT_CODEC(0) |
8148efcd486SBrent Lu SOF_SSP_PORT_AMP(1) |
8158efcd486SBrent Lu SOF_NUM_IDISP_HDMI(4) |
8168efcd486SBrent Lu SOF_SSP_PORT_BT_OFFLOAD(2) |
8178efcd486SBrent Lu SOF_BT_OFFLOAD_PRESENT),
818ad83b1adSBrent Lu },
8192e4dba57SVamshi Krishna Gopal {
82041333c35SBrent Lu .name = "adl_rt5682_def",
8212e4dba57SVamshi Krishna Gopal .driver_data = (kernel_ulong_t)(SOF_RT5682_MCLK_EN |
8228efcd486SBrent Lu SOF_SSP_PORT_CODEC(0) |
8238efcd486SBrent Lu SOF_SSP_PORT_AMP(1) |
8248efcd486SBrent Lu SOF_NUM_IDISP_HDMI(4) |
8258efcd486SBrent Lu SOF_SSP_PORT_BT_OFFLOAD(2) |
8268efcd486SBrent Lu SOF_BT_OFFLOAD_PRESENT),
8272e4dba57SVamshi Krishna Gopal },
8282e4dba57SVamshi Krishna Gopal {
8293c561a09SBrent Lu .name = "adl_mx98357_rt5682",
8302e4dba57SVamshi Krishna Gopal .driver_data = (kernel_ulong_t)(SOF_RT5682_MCLK_EN |
8318efcd486SBrent Lu SOF_SSP_PORT_CODEC(0) |
8328efcd486SBrent Lu SOF_SSP_PORT_AMP(2) |
8338efcd486SBrent Lu SOF_NUM_IDISP_HDMI(4)),
8342e4dba57SVamshi Krishna Gopal },
83546414bc3SBrent Lu {
836f3c37847Sapoorv .name = "adl_rt5682_c1_h02",
837f3c37847Sapoorv .driver_data = (kernel_ulong_t)(SOF_RT5682_MCLK_EN |
8388efcd486SBrent Lu SOF_SSP_PORT_CODEC(1) |
839f3c37847Sapoorv /* SSP 0 and SSP 2 are used for HDMI IN */
8408efcd486SBrent Lu SOF_SSP_MASK_HDMI_CAPTURE(0x5)),
841f3c37847Sapoorv },
842f3c37847Sapoorv {
84326d9726fSTerry Cheong .name = "rpl_mx98357_rt5682",
84426d9726fSTerry Cheong .driver_data = (kernel_ulong_t)(SOF_RT5682_MCLK_EN |
8458efcd486SBrent Lu SOF_SSP_PORT_CODEC(0) |
8468efcd486SBrent Lu SOF_SSP_PORT_AMP(2) |
8478efcd486SBrent Lu SOF_NUM_IDISP_HDMI(4)),
84826d9726fSTerry Cheong },
84926d9726fSTerry Cheong {
85019ec6b2eSBrent Lu .name = "rpl_rt5682_def",
8515dc51e50STerry Cheong .driver_data = (kernel_ulong_t)(SOF_RT5682_MCLK_EN |
8528efcd486SBrent Lu SOF_SSP_PORT_CODEC(0) |
8538efcd486SBrent Lu SOF_SSP_PORT_AMP(1) |
8548efcd486SBrent Lu SOF_NUM_IDISP_HDMI(4) |
8558efcd486SBrent Lu SOF_SSP_PORT_BT_OFFLOAD(2) |
8568efcd486SBrent Lu SOF_BT_OFFLOAD_PRESENT),
8575dc51e50STerry Cheong },
8585dc51e50STerry Cheong {
85914b7ed66SBalamurugan C .name = "rpl_rt5682_c1_h02",
86014b7ed66SBalamurugan C .driver_data = (kernel_ulong_t)(SOF_RT5682_MCLK_EN |
8618efcd486SBrent Lu SOF_SSP_PORT_CODEC(1) |
86214b7ed66SBalamurugan C /* SSP 0 and SSP 2 are used for HDMI IN */
8638efcd486SBrent Lu SOF_SSP_MASK_HDMI_CAPTURE(0x5)),
86414b7ed66SBalamurugan C },
86514b7ed66SBalamurugan C {
866f1a5cb6aSBrent Lu .name = "mtl_rt5682_def",
8671f6645b1SYong Zhi .driver_data = (kernel_ulong_t)(SOF_RT5682_MCLK_EN |
8688efcd486SBrent Lu SOF_SSP_PORT_CODEC(0) |
8698efcd486SBrent Lu SOF_SSP_PORT_AMP(1) |
8708efcd486SBrent Lu SOF_SSP_PORT_BT_OFFLOAD(2) |
8718efcd486SBrent Lu SOF_BT_OFFLOAD_PRESENT),
8721f6645b1SYong Zhi },
873*47d94c13SBalamurugan C {
874*47d94c13SBalamurugan C .name = "arl_rt5682_c1_h02",
875*47d94c13SBalamurugan C .driver_data = (kernel_ulong_t)(SOF_RT5682_MCLK_EN |
876*47d94c13SBalamurugan C SOF_SSP_PORT_CODEC(1) |
877*47d94c13SBalamurugan C /* SSP 0 and SSP 2 are used for HDMI IN */
878*47d94c13SBalamurugan C SOF_SSP_MASK_HDMI_CAPTURE(0x5)),
879*47d94c13SBalamurugan C },
8806605f0caSSathyanarayana Nujella { }
8816605f0caSSathyanarayana Nujella };
882a75e5cdfSZou Wei MODULE_DEVICE_TABLE(platform, board_ids);
8836605f0caSSathyanarayana Nujella
884f70abd75SBard liao static struct platform_driver sof_audio = {
885f70abd75SBard liao .probe = sof_audio_probe,
886f70abd75SBard liao .driver = {
887f70abd75SBard liao .name = "sof_rt5682",
888f70abd75SBard liao .pm = &snd_soc_pm_ops,
889f70abd75SBard liao },
8906605f0caSSathyanarayana Nujella .id_table = board_ids,
891f70abd75SBard liao };
892f70abd75SBard liao module_platform_driver(sof_audio)
893f70abd75SBard liao
894f70abd75SBard liao /* Module information */
895f70abd75SBard liao MODULE_DESCRIPTION("SOF Audio Machine driver");
896f70abd75SBard liao MODULE_AUTHOR("Bard Liao <bard.liao@intel.com>");
897f70abd75SBard liao MODULE_AUTHOR("Sathya Prakash M R <sathya.prakash.m.r@intel.com>");
898aa6cc97cSBrent Lu MODULE_AUTHOR("Brent Lu <brent.lu@intel.com>");
899f316c9d9SMac Chiang MODULE_AUTHOR("Mac Chiang <mac.chiang@intel.com>");
900f70abd75SBard liao MODULE_LICENSE("GPL v2");
90189cadbd8SBrent Lu MODULE_IMPORT_NS(SND_SOC_INTEL_SOF_BOARD_HELPERS);
9029c5046e4SPierre-Louis Bossart MODULE_IMPORT_NS(SND_SOC_INTEL_SOF_MAXIM_COMMON);
903e1d5e133SBrent Lu MODULE_IMPORT_NS(SND_SOC_INTEL_SOF_REALTEK_COMMON);
904