xref: /linux/sound/soc/intel/boards/sof_rt5682.c (revision b5aaf6a56dcafc2aeefdc7da1f9f86fa5cfa8df7)
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