xref: /linux/sound/soc/intel/boards/sof_rt5682.c (revision 8b6d678fede700db6466d73f11fcbad496fa515e)
1 // SPDX-License-Identifier: GPL-2.0-only
2 // Copyright(c) 2019-2020 Intel Corporation.
3 
4 /*
5  * Intel SOF Machine Driver with Realtek rt5682 Codec
6  * and speaker codec MAX98357A or RT1015.
7  */
8 #include <linux/i2c.h>
9 #include <linux/input.h>
10 #include <linux/module.h>
11 #include <linux/platform_device.h>
12 #include <linux/clk.h>
13 #include <linux/dmi.h>
14 #include <sound/core.h>
15 #include <sound/jack.h>
16 #include <sound/pcm.h>
17 #include <sound/pcm_params.h>
18 #include <sound/soc.h>
19 #include <sound/sof.h>
20 #include <sound/rt5682.h>
21 #include <sound/rt5682s.h>
22 #include <sound/soc-acpi.h>
23 #include "../../codecs/rt5682.h"
24 #include "../../codecs/rt5682s.h"
25 #include "../../codecs/rt5645.h"
26 #include "../common/soc-intel-quirks.h"
27 #include "sof_board_helpers.h"
28 #include "sof_maxim_common.h"
29 #include "sof_realtek_common.h"
30 
31 /* Driver-specific board quirks: from bit 0 to 7 */
32 #define SOF_RT5682_MCLK_EN			BIT(0)
33 #define SOF_RT5682_MCLK_BYTCHT_EN		BIT(1)
34 
35 /* Default: MCLK on, MCLK 19.2M, SSP0  */
36 static unsigned long sof_rt5682_quirk = SOF_RT5682_MCLK_EN |
37 					SOF_SSP_PORT_CODEC(0);
38 
39 static int sof_rt5682_quirk_cb(const struct dmi_system_id *id)
40 {
41 	sof_rt5682_quirk = (unsigned long)id->driver_data;
42 	return 1;
43 }
44 
45 static const struct dmi_system_id sof_rt5682_quirk_table[] = {
46 	{
47 		.callback = sof_rt5682_quirk_cb,
48 		.matches = {
49 			DMI_MATCH(DMI_SYS_VENDOR, "Circuitco"),
50 			DMI_MATCH(DMI_PRODUCT_NAME, "Minnowboard Max"),
51 		},
52 		.driver_data = (void *)(SOF_SSP_PORT_CODEC(2)),
53 	},
54 	{
55 		.callback = sof_rt5682_quirk_cb,
56 		.matches = {
57 			DMI_MATCH(DMI_SYS_VENDOR, "AAEON"),
58 			DMI_MATCH(DMI_PRODUCT_NAME, "UP-CHT01"),
59 		},
60 		.driver_data = (void *)(SOF_SSP_PORT_CODEC(2)),
61 	},
62 	{
63 		.callback = sof_rt5682_quirk_cb,
64 		.matches = {
65 			DMI_MATCH(DMI_SYS_VENDOR, "Intel Corporation"),
66 			DMI_MATCH(DMI_PRODUCT_NAME, "WhiskeyLake Client"),
67 		},
68 		.driver_data = (void *)(SOF_RT5682_MCLK_EN |
69 					SOF_SSP_PORT_CODEC(1)),
70 	},
71 	{
72 		.callback = sof_rt5682_quirk_cb,
73 		.matches = {
74 			DMI_MATCH(DMI_PRODUCT_FAMILY, "Google_Hatch"),
75 		},
76 		.driver_data = (void *)(SOF_RT5682_MCLK_EN |
77 					SOF_SSP_PORT_CODEC(0) |
78 					SOF_SSP_PORT_AMP(1)),
79 	},
80 	{
81 		.callback = sof_rt5682_quirk_cb,
82 		.matches = {
83 			DMI_MATCH(DMI_SYS_VENDOR, "Intel Corporation"),
84 			DMI_MATCH(DMI_PRODUCT_NAME, "Ice Lake Client"),
85 		},
86 		.driver_data = (void *)(SOF_RT5682_MCLK_EN |
87 					SOF_SSP_PORT_CODEC(0)),
88 	},
89 	{
90 		.callback = sof_rt5682_quirk_cb,
91 		.matches = {
92 			DMI_MATCH(DMI_PRODUCT_FAMILY, "Google_Volteer"),
93 			DMI_MATCH(DMI_OEM_STRING, "AUDIO-MAX98373_ALC5682I_I2S_UP4"),
94 		},
95 		.driver_data = (void *)(SOF_RT5682_MCLK_EN |
96 					SOF_SSP_PORT_CODEC(0) |
97 					SOF_SSP_PORT_AMP(2) |
98 					SOF_NUM_IDISP_HDMI(4)),
99 	},
100 	{
101 		.callback = sof_rt5682_quirk_cb,
102 		.matches = {
103 			DMI_MATCH(DMI_SYS_VENDOR, "Intel Corporation"),
104 			DMI_MATCH(DMI_PRODUCT_NAME, "Alder Lake Client Platform"),
105 			DMI_MATCH(DMI_OEM_STRING, "AUDIO-ADL_MAX98373_ALC5682I_I2S"),
106 		},
107 		.driver_data = (void *)(SOF_RT5682_MCLK_EN |
108 					SOF_SSP_PORT_CODEC(0) |
109 					SOF_SSP_PORT_AMP(2) |
110 					SOF_NUM_IDISP_HDMI(4)),
111 	},
112 	{
113 		.callback = sof_rt5682_quirk_cb,
114 		.matches = {
115 			DMI_MATCH(DMI_PRODUCT_FAMILY, "Google_Brya"),
116 			DMI_MATCH(DMI_OEM_STRING, "AUDIO-MAX98390_ALC5682I_I2S"),
117 		},
118 		.driver_data = (void *)(SOF_RT5682_MCLK_EN |
119 					SOF_SSP_PORT_CODEC(0) |
120 					SOF_SSP_PORT_AMP(2) |
121 					SOF_NUM_IDISP_HDMI(4)),
122 	},
123 	{
124 		.callback = sof_rt5682_quirk_cb,
125 		.matches = {
126 			DMI_MATCH(DMI_PRODUCT_FAMILY, "Google_Brya"),
127 			DMI_MATCH(DMI_OEM_STRING, "AUDIO-MAX98360_ALC5682I_I2S_AMP_SSP2"),
128 		},
129 		.driver_data = (void *)(SOF_RT5682_MCLK_EN |
130 					SOF_SSP_PORT_CODEC(0) |
131 					SOF_SSP_PORT_AMP(2) |
132 					SOF_NUM_IDISP_HDMI(4)),
133 	},
134 	{
135 		.callback = sof_rt5682_quirk_cb,
136 		.matches = {
137 			DMI_MATCH(DMI_PRODUCT_FAMILY, "Google_Rex"),
138 		},
139 		.driver_data = (void *)(SOF_RT5682_MCLK_EN |
140 					SOF_SSP_PORT_CODEC(2) |
141 					SOF_SSP_PORT_AMP(0) |
142 					SOF_SSP_PORT_BT_OFFLOAD(1) |
143 					SOF_BT_OFFLOAD_PRESENT
144 					),
145 	},
146 	{}
147 };
148 
149 static struct snd_soc_jack_pin jack_pins[] = {
150 	{
151 		.pin    = "Headphone Jack",
152 		.mask   = SND_JACK_HEADPHONE,
153 	},
154 	{
155 		.pin    = "Headset Mic",
156 		.mask   = SND_JACK_MICROPHONE,
157 	},
158 };
159 
160 static int sof_rt5682_codec_init(struct snd_soc_pcm_runtime *rtd)
161 {
162 	struct sof_card_private *ctx = snd_soc_card_get_drvdata(rtd->card);
163 	struct snd_soc_component *component = snd_soc_rtd_to_codec(rtd, 0)->component;
164 	struct snd_soc_jack *jack = &ctx->headset_jack;
165 	int extra_jack_data;
166 	int ret, mclk_freq;
167 
168 	if (sof_rt5682_quirk & SOF_RT5682_MCLK_EN) {
169 		mclk_freq = sof_dai_get_mclk(rtd);
170 		if (mclk_freq <= 0) {
171 			dev_err(rtd->dev, "invalid mclk freq %d\n", mclk_freq);
172 			return -EINVAL;
173 		}
174 
175 		/* need to enable ASRC function for 24MHz mclk rate */
176 		if (mclk_freq == 24000000) {
177 			dev_info(rtd->dev, "enable ASRC\n");
178 
179 			switch (ctx->codec_type) {
180 			case CODEC_RT5650:
181 				rt5645_sel_asrc_clk_src(component,
182 							RT5645_DA_STEREO_FILTER |
183 							RT5645_AD_STEREO_FILTER,
184 							RT5645_CLK_SEL_I2S1_ASRC);
185 				rt5645_sel_asrc_clk_src(component,
186 							RT5645_DA_MONO_L_FILTER |
187 							RT5645_DA_MONO_R_FILTER,
188 							RT5645_CLK_SEL_I2S2_ASRC);
189 				break;
190 			case CODEC_RT5682:
191 				rt5682_sel_asrc_clk_src(component,
192 							RT5682_DA_STEREO1_FILTER |
193 							RT5682_AD_STEREO1_FILTER,
194 							RT5682_CLK_SEL_I2S1_ASRC);
195 				break;
196 			case CODEC_RT5682S:
197 				rt5682s_sel_asrc_clk_src(component,
198 							 RT5682S_DA_STEREO1_FILTER |
199 							 RT5682S_AD_STEREO1_FILTER,
200 							 RT5682S_CLK_SEL_I2S1_ASRC);
201 				break;
202 			default:
203 				dev_err(rtd->dev, "invalid codec type %d\n",
204 					ctx->codec_type);
205 				return -EINVAL;
206 			}
207 		}
208 
209 		if (sof_rt5682_quirk & SOF_RT5682_MCLK_BYTCHT_EN) {
210 			/*
211 			 * The firmware might enable the clock at
212 			 * boot (this information may or may not
213 			 * be reflected in the enable clock register).
214 			 * To change the rate we must disable the clock
215 			 * first to cover these cases. Due to common
216 			 * clock framework restrictions that do not allow
217 			 * to disable a clock that has not been enabled,
218 			 * we need to enable the clock first.
219 			 */
220 			ret = clk_prepare_enable(ctx->rt5682.mclk);
221 			if (!ret)
222 				clk_disable_unprepare(ctx->rt5682.mclk);
223 
224 			ret = clk_set_rate(ctx->rt5682.mclk, 19200000);
225 
226 			if (ret)
227 				dev_err(rtd->dev, "unable to set MCLK rate\n");
228 		}
229 	}
230 
231 	/*
232 	 * Headset buttons map to the google Reference headset.
233 	 * These can be configured by userspace.
234 	 */
235 	ret = snd_soc_card_jack_new_pins(rtd->card, "Headset Jack",
236 					 SND_JACK_HEADSET | SND_JACK_BTN_0 |
237 					 SND_JACK_BTN_1 | SND_JACK_BTN_2 |
238 					 SND_JACK_BTN_3,
239 					 jack,
240 					 jack_pins,
241 					 ARRAY_SIZE(jack_pins));
242 	if (ret) {
243 		dev_err(rtd->dev, "Headset Jack creation failed: %d\n", ret);
244 		return ret;
245 	}
246 
247 	snd_jack_set_key(jack->jack, SND_JACK_BTN_0, KEY_PLAYPAUSE);
248 	snd_jack_set_key(jack->jack, SND_JACK_BTN_1, KEY_VOICECOMMAND);
249 	snd_jack_set_key(jack->jack, SND_JACK_BTN_2, KEY_VOLUMEUP);
250 	snd_jack_set_key(jack->jack, SND_JACK_BTN_3, KEY_VOLUMEDOWN);
251 
252 	if (ctx->codec_type == CODEC_RT5650) {
253 		extra_jack_data = SND_JACK_MICROPHONE | SND_JACK_BTN_0;
254 		ret = snd_soc_component_set_jack(component, jack, &extra_jack_data);
255 	} else
256 		ret = snd_soc_component_set_jack(component, jack, NULL);
257 
258 	if (ret) {
259 		dev_err(rtd->dev, "Headset Jack call-back failed: %d\n", ret);
260 		return ret;
261 	}
262 
263 	return ret;
264 };
265 
266 static void sof_rt5682_codec_exit(struct snd_soc_pcm_runtime *rtd)
267 {
268 	struct snd_soc_component *component = snd_soc_rtd_to_codec(rtd, 0)->component;
269 
270 	snd_soc_component_set_jack(component, NULL, NULL);
271 }
272 
273 static int sof_rt5682_hw_params(struct snd_pcm_substream *substream,
274 				struct snd_pcm_hw_params *params)
275 {
276 	struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream);
277 	struct sof_card_private *ctx = snd_soc_card_get_drvdata(rtd->card);
278 	struct snd_soc_dai *codec_dai = snd_soc_rtd_to_codec(rtd, 0);
279 	int pll_id, pll_source, pll_in, pll_out, clk_id, ret;
280 
281 	if (sof_rt5682_quirk & SOF_RT5682_MCLK_EN) {
282 		if (sof_rt5682_quirk & SOF_RT5682_MCLK_BYTCHT_EN) {
283 			ret = clk_prepare_enable(ctx->rt5682.mclk);
284 			if (ret < 0) {
285 				dev_err(rtd->dev,
286 					"could not configure MCLK state");
287 				return ret;
288 			}
289 		}
290 
291 		switch (ctx->codec_type) {
292 		case CODEC_RT5650:
293 			pll_source = RT5645_PLL1_S_MCLK;
294 			break;
295 		case CODEC_RT5682:
296 			pll_source = RT5682_PLL1_S_MCLK;
297 			break;
298 		case CODEC_RT5682S:
299 			pll_source = RT5682S_PLL_S_MCLK;
300 			break;
301 		default:
302 			dev_err(rtd->dev, "invalid codec type %d\n",
303 				ctx->codec_type);
304 			return -EINVAL;
305 		}
306 
307 		/* get the tplg configured mclk. */
308 		pll_in = sof_dai_get_mclk(rtd);
309 		if (pll_in <= 0) {
310 			dev_err(rtd->dev, "invalid mclk freq %d\n", pll_in);
311 			return -EINVAL;
312 		}
313 	} else {
314 		switch (ctx->codec_type) {
315 		case CODEC_RT5650:
316 			pll_source = RT5645_PLL1_S_BCLK1;
317 			break;
318 		case CODEC_RT5682:
319 			pll_source = RT5682_PLL1_S_BCLK1;
320 			break;
321 		case CODEC_RT5682S:
322 			pll_source = RT5682S_PLL_S_BCLK1;
323 			break;
324 		default:
325 			dev_err(rtd->dev, "invalid codec type %d\n",
326 				ctx->codec_type);
327 			return -EINVAL;
328 		}
329 
330 		pll_in = params_rate(params) * 50;
331 	}
332 
333 	switch (ctx->codec_type) {
334 	case CODEC_RT5650:
335 		pll_id = 0; /* not used in codec driver */
336 		clk_id = RT5645_SCLK_S_PLL1;
337 		break;
338 	case CODEC_RT5682:
339 		pll_id = RT5682_PLL1;
340 		clk_id = RT5682_SCLK_S_PLL1;
341 		break;
342 	case CODEC_RT5682S:
343 		/*
344 		 * For MCLK = 24.576MHz and sample rate = 96KHz case, use PLL1  We don't test
345 		 * pll_out or params_rate() here since rt5682s PLL2 doesn't support 24.576MHz
346 		 * input, so we have no choice but to use PLL1. Besides, we will not use PLL at
347 		 * all if pll_in == pll_out. ex, MCLK = 24.576Mhz and sample rate = 48KHz
348 		 */
349 		if (pll_in == 24576000) {
350 			pll_id = RT5682S_PLL1;
351 			clk_id = RT5682S_SCLK_S_PLL1;
352 		} else {
353 			pll_id = RT5682S_PLL2;
354 			clk_id = RT5682S_SCLK_S_PLL2;
355 		}
356 		break;
357 	default:
358 		dev_err(rtd->dev, "invalid codec type %d\n", ctx->codec_type);
359 		return -EINVAL;
360 	}
361 
362 	pll_out = params_rate(params) * 512;
363 
364 	/* when MCLK is 512FS, no need to set PLL configuration additionally. */
365 	if (pll_in == pll_out) {
366 		switch (ctx->codec_type) {
367 		case CODEC_RT5650:
368 			clk_id = RT5645_SCLK_S_MCLK;
369 			break;
370 		case CODEC_RT5682:
371 			clk_id = RT5682_SCLK_S_MCLK;
372 			break;
373 		case CODEC_RT5682S:
374 			clk_id = RT5682S_SCLK_S_MCLK;
375 			break;
376 		default:
377 			dev_err(rtd->dev, "invalid codec type %d\n",
378 				ctx->codec_type);
379 			return -EINVAL;
380 		}
381 	} else {
382 		/* Configure pll for codec */
383 		ret = snd_soc_dai_set_pll(codec_dai, pll_id, pll_source, pll_in,
384 					  pll_out);
385 		if (ret < 0)
386 			dev_err(rtd->dev, "snd_soc_dai_set_pll err = %d\n", ret);
387 	}
388 
389 	/* Configure sysclk for codec */
390 	ret = snd_soc_dai_set_sysclk(codec_dai, clk_id,
391 				     pll_out, SND_SOC_CLOCK_IN);
392 	if (ret < 0)
393 		dev_err(rtd->dev, "snd_soc_dai_set_sysclk err = %d\n", ret);
394 
395 	/*
396 	 * slot_width should equal or large than data length, set them
397 	 * be the same
398 	 */
399 	ret = snd_soc_dai_set_tdm_slot(codec_dai, 0x0, 0x0, 2,
400 				       params_width(params));
401 	if (ret < 0) {
402 		dev_err(rtd->dev, "set TDM slot err:%d\n", ret);
403 		return ret;
404 	}
405 
406 	return ret;
407 }
408 
409 static struct snd_soc_ops sof_rt5682_ops = {
410 	.hw_params = sof_rt5682_hw_params,
411 };
412 
413 static int sof_card_late_probe(struct snd_soc_card *card)
414 {
415 	struct sof_card_private *ctx = snd_soc_card_get_drvdata(card);
416 	struct snd_soc_dapm_context *dapm = &card->dapm;
417 	int err;
418 
419 	if (ctx->amp_type == CODEC_MAX98373) {
420 		/* Disable Left and Right Spk pin after boot */
421 		snd_soc_dapm_disable_pin(dapm, "Left Spk");
422 		snd_soc_dapm_disable_pin(dapm, "Right Spk");
423 		err = snd_soc_dapm_sync(dapm);
424 		if (err < 0)
425 			return err;
426 	}
427 
428 	return sof_intel_board_card_late_probe(card);
429 }
430 
431 static const struct snd_kcontrol_new sof_controls[] = {
432 	SOC_DAPM_PIN_SWITCH("Headphone Jack"),
433 	SOC_DAPM_PIN_SWITCH("Headset Mic"),
434 	SOC_DAPM_PIN_SWITCH("Left Spk"),
435 	SOC_DAPM_PIN_SWITCH("Right Spk"),
436 
437 };
438 
439 static const struct snd_soc_dapm_widget sof_widgets[] = {
440 	SND_SOC_DAPM_HP("Headphone Jack", NULL),
441 	SND_SOC_DAPM_MIC("Headset Mic", NULL),
442 	SND_SOC_DAPM_SPK("Left Spk", NULL),
443 	SND_SOC_DAPM_SPK("Right Spk", NULL),
444 };
445 
446 static const struct snd_soc_dapm_route sof_map[] = {
447 	/* HP jack connectors - unknown if we have jack detection */
448 	{ "Headphone Jack", NULL, "HPOL" },
449 	{ "Headphone Jack", NULL, "HPOR" },
450 
451 	/* other jacks */
452 	{ "IN1P", NULL, "Headset Mic" },
453 };
454 
455 static const struct snd_soc_dapm_route rt5650_spk_dapm_routes[] = {
456 	/* speaker */
457 	{ "Left Spk", NULL, "SPOL" },
458 	{ "Right Spk", NULL, "SPOR" },
459 };
460 
461 static int rt5650_spk_init(struct snd_soc_pcm_runtime *rtd)
462 {
463 	struct snd_soc_card *card = rtd->card;
464 	int ret;
465 
466 	ret = snd_soc_dapm_add_routes(&card->dapm, rt5650_spk_dapm_routes,
467 				      ARRAY_SIZE(rt5650_spk_dapm_routes));
468 	if (ret)
469 		dev_err(rtd->dev, "fail to add dapm routes, ret=%d\n", ret);
470 
471 	return ret;
472 }
473 
474 /* sof audio machine driver for rt5682 codec */
475 static struct snd_soc_card sof_audio_card_rt5682 = {
476 	.name = "rt5682", /* the sof- prefix is added by the core */
477 	.owner = THIS_MODULE,
478 	.controls = sof_controls,
479 	.num_controls = ARRAY_SIZE(sof_controls),
480 	.dapm_widgets = sof_widgets,
481 	.num_dapm_widgets = ARRAY_SIZE(sof_widgets),
482 	.dapm_routes = sof_map,
483 	.num_dapm_routes = ARRAY_SIZE(sof_map),
484 	.fully_routed = true,
485 	.late_probe = sof_card_late_probe,
486 };
487 
488 static struct snd_soc_dai_link_component rt5682_component[] = {
489 	{
490 		.name = "i2c-10EC5682:00",
491 		.dai_name = "rt5682-aif1",
492 	}
493 };
494 
495 static struct snd_soc_dai_link_component rt5682s_component[] = {
496 	{
497 		.name = "i2c-RTL5682:00",
498 		.dai_name = "rt5682s-aif1",
499 	}
500 };
501 
502 static struct snd_soc_dai_link_component rt5650_components[] = {
503 	{
504 		.name = "i2c-10EC5650:00",
505 		.dai_name = "rt5645-aif1",
506 	},
507 	{
508 		.name = "i2c-10EC5650:00",
509 		.dai_name = "rt5645-aif2",
510 	}
511 };
512 
513 static int
514 sof_card_dai_links_create(struct device *dev, struct snd_soc_card *card,
515 			  struct sof_card_private *ctx)
516 {
517 	int ret;
518 
519 	ret = sof_intel_board_set_dai_link(dev, card, ctx);
520 	if (ret)
521 		return ret;
522 
523 	if (!ctx->codec_link) {
524 		dev_err(dev, "codec link not available");
525 		return -EINVAL;
526 	}
527 
528 	/* codec-specific fields for headphone codec */
529 	switch (ctx->codec_type) {
530 	case CODEC_RT5650:
531 		ctx->codec_link->codecs = &rt5650_components[0];
532 		ctx->codec_link->num_codecs = 1;
533 		break;
534 	case CODEC_RT5682:
535 		ctx->codec_link->codecs = rt5682_component;
536 		ctx->codec_link->num_codecs = ARRAY_SIZE(rt5682_component);
537 		break;
538 	case CODEC_RT5682S:
539 		ctx->codec_link->codecs = rt5682s_component;
540 		ctx->codec_link->num_codecs = ARRAY_SIZE(rt5682s_component);
541 		break;
542 	default:
543 		dev_err(dev, "invalid codec type %d\n", ctx->codec_type);
544 		return -EINVAL;
545 	}
546 
547 	ctx->codec_link->init = sof_rt5682_codec_init;
548 	ctx->codec_link->exit = sof_rt5682_codec_exit;
549 	ctx->codec_link->ops = &sof_rt5682_ops;
550 
551 	if (!ctx->rt5682.is_legacy_cpu) {
552 		/*
553 		 * Currently, On SKL+ platforms MCLK will be turned off in sof
554 		 * runtime suspended, and it will go into runtime suspended
555 		 * right after playback is stop. However, rt5682 will output
556 		 * static noise if sysclk turns off during playback. Set
557 		 * ignore_pmdown_time to power down rt5682 immediately and
558 		 * avoid the noise.
559 		 * It can be removed once we can control MCLK by driver.
560 		 */
561 		ctx->codec_link->ignore_pmdown_time = 1;
562 	}
563 
564 	if (ctx->amp_type == CODEC_NONE)
565 		return 0;
566 
567 	if (!ctx->amp_link) {
568 		dev_err(dev, "amp link not available");
569 		return -EINVAL;
570 	}
571 
572 	/* codec-specific fields for speaker amplifier */
573 	switch (ctx->amp_type) {
574 	case CODEC_MAX98357A:
575 		max_98357a_dai_link(ctx->amp_link);
576 		break;
577 	case CODEC_MAX98360A:
578 		max_98360a_dai_link(ctx->amp_link);
579 		break;
580 	case CODEC_MAX98373:
581 		ctx->amp_link->codecs = max_98373_components;
582 		ctx->amp_link->num_codecs = ARRAY_SIZE(max_98373_components);
583 		ctx->amp_link->init = max_98373_spk_codec_init;
584 		ctx->amp_link->ops = &max_98373_ops;
585 		break;
586 	case CODEC_MAX98390:
587 		max_98390_dai_link(dev, ctx->amp_link);
588 		break;
589 	case CODEC_RT1011:
590 		sof_rt1011_dai_link(dev, ctx->amp_link);
591 		break;
592 	case CODEC_RT1015:
593 		sof_rt1015_dai_link(ctx->amp_link);
594 		break;
595 	case CODEC_RT1015P:
596 		sof_rt1015p_dai_link(ctx->amp_link);
597 		break;
598 	case CODEC_RT1019P:
599 		sof_rt1019p_dai_link(ctx->amp_link);
600 		break;
601 	case CODEC_RT5650:
602 		/* use AIF2 to support speaker pipeline */
603 		ctx->amp_link->codecs = &rt5650_components[1];
604 		ctx->amp_link->num_codecs = 1;
605 		ctx->amp_link->init = rt5650_spk_init;
606 		ctx->amp_link->ops = &sof_rt5682_ops;
607 		break;
608 	default:
609 		dev_err(dev, "invalid amp type %d\n", ctx->amp_type);
610 		return -EINVAL;
611 	}
612 
613 	return 0;
614 }
615 
616 static int sof_audio_probe(struct platform_device *pdev)
617 {
618 	struct snd_soc_acpi_mach *mach = pdev->dev.platform_data;
619 	struct sof_card_private *ctx;
620 	char *card_name;
621 	bool is_legacy_cpu = false;
622 	int ret;
623 
624 	if (pdev->id_entry && pdev->id_entry->driver_data)
625 		sof_rt5682_quirk = (unsigned long)pdev->id_entry->driver_data;
626 
627 	dmi_check_system(sof_rt5682_quirk_table);
628 
629 	if (soc_intel_is_byt() || soc_intel_is_cht()) {
630 		is_legacy_cpu = true;
631 
632 		/* default quirk for legacy cpu */
633 		sof_rt5682_quirk = SOF_RT5682_MCLK_EN |
634 				   SOF_RT5682_MCLK_BYTCHT_EN |
635 				   SOF_SSP_PORT_CODEC(2);
636 	}
637 
638 	dev_dbg(&pdev->dev, "sof_rt5682_quirk = %lx\n", sof_rt5682_quirk);
639 
640 	/* initialize ctx with board quirk */
641 	ctx = sof_intel_board_get_ctx(&pdev->dev, sof_rt5682_quirk);
642 	if (!ctx)
643 		return -ENOMEM;
644 
645 	if (ctx->codec_type == CODEC_RT5650) {
646 		card_name = devm_kstrdup(&pdev->dev, "rt5650", GFP_KERNEL);
647 		if (!card_name)
648 			return -ENOMEM;
649 
650 		sof_audio_card_rt5682.name = card_name;
651 
652 		/* create speaker dai link also */
653 		if (ctx->amp_type == CODEC_NONE)
654 			ctx->amp_type = CODEC_RT5650;
655 	}
656 
657 	if (ctx->amp_type == CODEC_RT1011 && soc_intel_is_cml()) {
658 		/* backward-compatible with existing cml devices */
659 		card_name = devm_kstrdup(&pdev->dev, "cml_rt1011_rt5682",
660 					 GFP_KERNEL);
661 		if (!card_name)
662 			return -ENOMEM;
663 
664 		sof_audio_card_rt5682.name = card_name;
665 	}
666 
667 	if (is_legacy_cpu) {
668 		ctx->rt5682.is_legacy_cpu = true;
669 		ctx->dmic_be_num = 0;
670 		/* HDMI is not supported by SOF on Baytrail/CherryTrail */
671 		ctx->hdmi_num = 0;
672 	} else {
673 		if (mach->mach_params.codec_mask & IDISP_CODEC_MASK)
674 			ctx->hdmi.idisp_codec = true;
675 	}
676 
677 	/* need to get main clock from pmc */
678 	if (sof_rt5682_quirk & SOF_RT5682_MCLK_BYTCHT_EN) {
679 		ctx->rt5682.mclk = devm_clk_get(&pdev->dev, "pmc_plt_clk_3");
680 		if (IS_ERR(ctx->rt5682.mclk)) {
681 			ret = PTR_ERR(ctx->rt5682.mclk);
682 
683 			dev_err(&pdev->dev,
684 				"Failed to get MCLK from pmc_plt_clk_3: %d\n",
685 				ret);
686 			return ret;
687 		}
688 
689 		ret = clk_prepare_enable(ctx->rt5682.mclk);
690 		if (ret < 0) {
691 			dev_err(&pdev->dev,
692 				"could not configure MCLK state");
693 			return ret;
694 		}
695 	}
696 
697 	/* update dai_link */
698 	ret = sof_card_dai_links_create(&pdev->dev, &sof_audio_card_rt5682, ctx);
699 	if (ret)
700 		return ret;
701 
702 	/* update codec_conf */
703 	switch (ctx->amp_type) {
704 	case CODEC_MAX98373:
705 		max_98373_set_codec_conf(&sof_audio_card_rt5682);
706 		break;
707 	case CODEC_MAX98390:
708 		max_98390_set_codec_conf(&pdev->dev, &sof_audio_card_rt5682);
709 		break;
710 	case CODEC_RT1011:
711 		sof_rt1011_codec_conf(&pdev->dev, &sof_audio_card_rt5682);
712 		break;
713 	case CODEC_RT1015:
714 		sof_rt1015_codec_conf(&sof_audio_card_rt5682);
715 		break;
716 	case CODEC_RT1015P:
717 		sof_rt1015p_codec_conf(&sof_audio_card_rt5682);
718 		break;
719 	case CODEC_MAX98357A:
720 	case CODEC_MAX98360A:
721 	case CODEC_RT1019P:
722 	case CODEC_RT5650:
723 	case CODEC_NONE:
724 		/* no codec conf required */
725 		break;
726 	default:
727 		dev_err(&pdev->dev, "invalid amp type %d\n", ctx->amp_type);
728 		return -EINVAL;
729 	}
730 
731 	sof_audio_card_rt5682.dev = &pdev->dev;
732 
733 	/* set platform name for each dailink */
734 	ret = snd_soc_fixup_dai_links_platform_name(&sof_audio_card_rt5682,
735 						    mach->mach_params.platform);
736 	if (ret)
737 		return ret;
738 
739 	snd_soc_card_set_drvdata(&sof_audio_card_rt5682, ctx);
740 
741 	return devm_snd_soc_register_card(&pdev->dev,
742 					  &sof_audio_card_rt5682);
743 }
744 
745 static const struct platform_device_id board_ids[] = {
746 	{
747 		.name = "sof_rt5682",
748 	},
749 	{
750 		.name = "cml_rt5682_def",
751 		.driver_data = (kernel_ulong_t)(SOF_RT5682_MCLK_EN |
752 					SOF_SSP_PORT_CODEC(0) |
753 					SOF_SSP_PORT_AMP(1)),
754 	},
755 	{
756 		.name = "jsl_rt5682_def",
757 		.driver_data = (kernel_ulong_t)(SOF_RT5682_MCLK_EN |
758 					SOF_SSP_PORT_CODEC(0) |
759 					SOF_SSP_PORT_AMP(1)),
760 	},
761 	{
762 		.name = "tgl_rt5682_def",
763 		.driver_data = (kernel_ulong_t)(SOF_RT5682_MCLK_EN |
764 					SOF_SSP_PORT_CODEC(0) |
765 					SOF_SSP_PORT_AMP(1) |
766 					SOF_NUM_IDISP_HDMI(4) |
767 					SOF_SSP_PORT_BT_OFFLOAD(2) |
768 					SOF_BT_OFFLOAD_PRESENT),
769 	},
770 	{
771 		.name = "adl_rt5682_def",
772 		.driver_data = (kernel_ulong_t)(SOF_RT5682_MCLK_EN |
773 					SOF_SSP_PORT_CODEC(0) |
774 					SOF_SSP_PORT_AMP(1) |
775 					SOF_NUM_IDISP_HDMI(4) |
776 					SOF_SSP_PORT_BT_OFFLOAD(2) |
777 					SOF_BT_OFFLOAD_PRESENT),
778 	},
779 	{
780 		.name = "adl_mx98357_rt5682",
781 		.driver_data = (kernel_ulong_t)(SOF_RT5682_MCLK_EN |
782 					SOF_SSP_PORT_CODEC(0) |
783 					SOF_SSP_PORT_AMP(2) |
784 					SOF_NUM_IDISP_HDMI(4)),
785 	},
786 	{
787 		.name = "adl_rt5682_c1_h02",
788 		.driver_data = (kernel_ulong_t)(SOF_RT5682_MCLK_EN |
789 					SOF_SSP_PORT_CODEC(1) |
790 					/* SSP 0 and SSP 2 are used for HDMI IN */
791 					SOF_SSP_MASK_HDMI_CAPTURE(0x5)),
792 	},
793 	{
794 		.name = "rpl_mx98357_rt5682",
795 		.driver_data = (kernel_ulong_t)(SOF_RT5682_MCLK_EN |
796 					SOF_SSP_PORT_CODEC(0) |
797 					SOF_SSP_PORT_AMP(2) |
798 					SOF_NUM_IDISP_HDMI(4)),
799 	},
800 	{
801 		.name = "rpl_rt5682_def",
802 		.driver_data = (kernel_ulong_t)(SOF_RT5682_MCLK_EN |
803 					SOF_SSP_PORT_CODEC(0) |
804 					SOF_SSP_PORT_AMP(1) |
805 					SOF_NUM_IDISP_HDMI(4) |
806 					SOF_SSP_PORT_BT_OFFLOAD(2) |
807 					SOF_BT_OFFLOAD_PRESENT),
808 	},
809 	{
810 		.name = "rpl_rt5682_c1_h02",
811 		.driver_data = (kernel_ulong_t)(SOF_RT5682_MCLK_EN |
812 					SOF_SSP_PORT_CODEC(1) |
813 					/* SSP 0 and SSP 2 are used for HDMI IN */
814 					SOF_SSP_MASK_HDMI_CAPTURE(0x5)),
815 	},
816 	{
817 		.name = "mtl_mx98357_rt5682",
818 		.driver_data = (kernel_ulong_t)(SOF_RT5682_MCLK_EN |
819 					SOF_SSP_PORT_CODEC(0) |
820 					SOF_SSP_PORT_AMP(1) |
821 					SOF_SSP_PORT_BT_OFFLOAD(2) |
822 					SOF_BT_OFFLOAD_PRESENT),
823 	},
824 	{
825 		.name = "mtl_mx98360_rt5682",
826 		.driver_data = (kernel_ulong_t)(SOF_RT5682_MCLK_EN |
827 					SOF_SSP_PORT_CODEC(0) |
828 					SOF_SSP_PORT_AMP(1)),
829 	},
830 	{
831 		.name = "mtl_rt5682_def",
832 		.driver_data = (kernel_ulong_t)(SOF_RT5682_MCLK_EN |
833 					SOF_SSP_PORT_CODEC(2) |
834 					SOF_SSP_PORT_AMP(0) |
835 					SOF_SSP_PORT_BT_OFFLOAD(1) |
836 					SOF_BT_OFFLOAD_PRESENT),
837 	},
838 	{ }
839 };
840 MODULE_DEVICE_TABLE(platform, board_ids);
841 
842 static struct platform_driver sof_audio = {
843 	.probe = sof_audio_probe,
844 	.driver = {
845 		.name = "sof_rt5682",
846 		.pm = &snd_soc_pm_ops,
847 	},
848 	.id_table = board_ids,
849 };
850 module_platform_driver(sof_audio)
851 
852 /* Module information */
853 MODULE_DESCRIPTION("SOF Audio Machine driver");
854 MODULE_AUTHOR("Bard Liao <bard.liao@intel.com>");
855 MODULE_AUTHOR("Sathya Prakash M R <sathya.prakash.m.r@intel.com>");
856 MODULE_AUTHOR("Brent Lu <brent.lu@intel.com>");
857 MODULE_AUTHOR("Mac Chiang <mac.chiang@intel.com>");
858 MODULE_LICENSE("GPL v2");
859 MODULE_IMPORT_NS(SND_SOC_INTEL_SOF_BOARD_HELPERS);
860 MODULE_IMPORT_NS(SND_SOC_INTEL_SOF_MAXIM_COMMON);
861 MODULE_IMPORT_NS(SND_SOC_INTEL_SOF_REALTEK_COMMON);
862