1 // SPDX-License-Identifier: GPL-2.0
2 // Copyright(c) 2019 Intel Corporation.
3 
4 /*
5  * Intel SOF Machine Driver with Realtek rt5682 Codec
6  * and speaker codec MAX98357A
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/rt5682.h>
20 #include <sound/soc-acpi.h>
21 #include "../../codecs/rt5682.h"
22 #include "../../codecs/hdac_hdmi.h"
23 #include "../common/soc-intel-quirks.h"
24 #include "hda_dsp_common.h"
25 
26 #define NAME_SIZE 32
27 
28 #define SOF_RT5682_SSP_CODEC(quirk)		((quirk) & GENMASK(2, 0))
29 #define SOF_RT5682_SSP_CODEC_MASK			(GENMASK(2, 0))
30 #define SOF_RT5682_MCLK_EN			BIT(3)
31 #define SOF_RT5682_MCLK_24MHZ			BIT(4)
32 #define SOF_SPEAKER_AMP_PRESENT		BIT(5)
33 #define SOF_RT5682_SSP_AMP_SHIFT		6
34 #define SOF_RT5682_SSP_AMP_MASK                 (GENMASK(8, 6))
35 #define SOF_RT5682_SSP_AMP(quirk)	\
36 	(((quirk) << SOF_RT5682_SSP_AMP_SHIFT) & SOF_RT5682_SSP_AMP_MASK)
37 #define SOF_RT5682_MCLK_BYTCHT_EN		BIT(9)
38 #define SOF_RT5682_NUM_HDMIDEV_SHIFT		10
39 #define SOF_RT5682_NUM_HDMIDEV_MASK		(GENMASK(12, 10))
40 #define SOF_RT5682_NUM_HDMIDEV(quirk)	\
41 	((quirk << SOF_RT5682_NUM_HDMIDEV_SHIFT) & SOF_RT5682_NUM_HDMIDEV_MASK)
42 
43 /* Default: MCLK on, MCLK 19.2M, SSP0  */
44 static unsigned long sof_rt5682_quirk = SOF_RT5682_MCLK_EN |
45 					SOF_RT5682_SSP_CODEC(0);
46 
47 static int is_legacy_cpu;
48 
49 static struct snd_soc_jack sof_hdmi[3];
50 
51 struct sof_hdmi_pcm {
52 	struct list_head head;
53 	struct snd_soc_dai *codec_dai;
54 	int device;
55 };
56 
57 struct sof_card_private {
58 	struct clk *mclk;
59 	struct snd_soc_jack sof_headset;
60 	struct list_head hdmi_pcm_list;
61 	bool common_hdmi_codec_drv;
62 };
63 
64 static int sof_rt5682_quirk_cb(const struct dmi_system_id *id)
65 {
66 	sof_rt5682_quirk = (unsigned long)id->driver_data;
67 	return 1;
68 }
69 
70 static const struct dmi_system_id sof_rt5682_quirk_table[] = {
71 	{
72 		.callback = sof_rt5682_quirk_cb,
73 		.matches = {
74 			DMI_MATCH(DMI_SYS_VENDOR, "Circuitco"),
75 			DMI_MATCH(DMI_PRODUCT_NAME, "Minnowboard Max"),
76 		},
77 		.driver_data = (void *)(SOF_RT5682_SSP_CODEC(2)),
78 	},
79 	{
80 		.callback = sof_rt5682_quirk_cb,
81 		.matches = {
82 			DMI_MATCH(DMI_SYS_VENDOR, "AAEON"),
83 			DMI_MATCH(DMI_PRODUCT_NAME, "UP-CHT01"),
84 		},
85 		.driver_data = (void *)(SOF_RT5682_SSP_CODEC(2)),
86 	},
87 	{
88 		.callback = sof_rt5682_quirk_cb,
89 		.matches = {
90 			DMI_MATCH(DMI_SYS_VENDOR, "Intel Corporation"),
91 			DMI_MATCH(DMI_PRODUCT_NAME, "WhiskeyLake Client"),
92 		},
93 		.driver_data = (void *)(SOF_RT5682_MCLK_EN |
94 					SOF_RT5682_MCLK_24MHZ |
95 					SOF_RT5682_SSP_CODEC(1)),
96 	},
97 	{
98 		.callback = sof_rt5682_quirk_cb,
99 		.matches = {
100 			DMI_MATCH(DMI_PRODUCT_FAMILY, "Google_Hatch"),
101 		},
102 		.driver_data = (void *)(SOF_RT5682_MCLK_EN |
103 					SOF_RT5682_MCLK_24MHZ |
104 					SOF_RT5682_SSP_CODEC(0) |
105 					SOF_SPEAKER_AMP_PRESENT |
106 					SOF_RT5682_SSP_AMP(1)),
107 	},
108 	{
109 		.callback = sof_rt5682_quirk_cb,
110 		.matches = {
111 			DMI_MATCH(DMI_SYS_VENDOR, "Intel Corporation"),
112 			DMI_MATCH(DMI_PRODUCT_NAME, "Ice Lake Client"),
113 		},
114 		.driver_data = (void *)(SOF_RT5682_MCLK_EN |
115 					SOF_RT5682_SSP_CODEC(0)),
116 	},
117 	{}
118 };
119 
120 static int sof_hdmi_init(struct snd_soc_pcm_runtime *rtd)
121 {
122 	struct sof_card_private *ctx = snd_soc_card_get_drvdata(rtd->card);
123 	struct snd_soc_dai *dai = rtd->codec_dai;
124 	struct sof_hdmi_pcm *pcm;
125 
126 	pcm = devm_kzalloc(rtd->card->dev, sizeof(*pcm), GFP_KERNEL);
127 	if (!pcm)
128 		return -ENOMEM;
129 
130 	/* dai_link id is 1:1 mapped to the PCM device */
131 	pcm->device = rtd->dai_link->id;
132 	pcm->codec_dai = dai;
133 
134 	list_add_tail(&pcm->head, &ctx->hdmi_pcm_list);
135 
136 	return 0;
137 }
138 
139 static int sof_rt5682_codec_init(struct snd_soc_pcm_runtime *rtd)
140 {
141 	struct sof_card_private *ctx = snd_soc_card_get_drvdata(rtd->card);
142 	struct snd_soc_component *component = rtd->codec_dai->component;
143 	struct snd_soc_jack *jack;
144 	int ret;
145 
146 	/* need to enable ASRC function for 24MHz mclk rate */
147 	if ((sof_rt5682_quirk & SOF_RT5682_MCLK_EN) &&
148 	    (sof_rt5682_quirk & SOF_RT5682_MCLK_24MHZ)) {
149 		rt5682_sel_asrc_clk_src(component, RT5682_DA_STEREO1_FILTER |
150 					RT5682_AD_STEREO1_FILTER,
151 					RT5682_CLK_SEL_I2S1_ASRC);
152 	}
153 
154 	if (sof_rt5682_quirk & SOF_RT5682_MCLK_BYTCHT_EN) {
155 		/*
156 		 * The firmware might enable the clock at
157 		 * boot (this information may or may not
158 		 * be reflected in the enable clock register).
159 		 * To change the rate we must disable the clock
160 		 * first to cover these cases. Due to common
161 		 * clock framework restrictions that do not allow
162 		 * to disable a clock that has not been enabled,
163 		 * we need to enable the clock first.
164 		 */
165 		ret = clk_prepare_enable(ctx->mclk);
166 		if (!ret)
167 			clk_disable_unprepare(ctx->mclk);
168 
169 		ret = clk_set_rate(ctx->mclk, 19200000);
170 
171 		if (ret)
172 			dev_err(rtd->dev, "unable to set MCLK rate\n");
173 	}
174 
175 	/*
176 	 * Headset buttons map to the google Reference headset.
177 	 * These can be configured by userspace.
178 	 */
179 	ret = snd_soc_card_jack_new(rtd->card, "Headset Jack",
180 				    SND_JACK_HEADSET | SND_JACK_BTN_0 |
181 				    SND_JACK_BTN_1 | SND_JACK_BTN_2 |
182 				    SND_JACK_BTN_3,
183 				    &ctx->sof_headset, NULL, 0);
184 	if (ret) {
185 		dev_err(rtd->dev, "Headset Jack creation failed: %d\n", ret);
186 		return ret;
187 	}
188 
189 	jack = &ctx->sof_headset;
190 
191 	snd_jack_set_key(jack->jack, SND_JACK_BTN_0, KEY_PLAYPAUSE);
192 	snd_jack_set_key(jack->jack, SND_JACK_BTN_1, KEY_VOICECOMMAND);
193 	snd_jack_set_key(jack->jack, SND_JACK_BTN_2, KEY_VOLUMEUP);
194 	snd_jack_set_key(jack->jack, SND_JACK_BTN_3, KEY_VOLUMEDOWN);
195 	ret = snd_soc_component_set_jack(component, jack, NULL);
196 
197 	if (ret) {
198 		dev_err(rtd->dev, "Headset Jack call-back failed: %d\n", ret);
199 		return ret;
200 	}
201 
202 	return ret;
203 };
204 
205 static int sof_rt5682_hw_params(struct snd_pcm_substream *substream,
206 				struct snd_pcm_hw_params *params)
207 {
208 	struct snd_soc_pcm_runtime *rtd = substream->private_data;
209 	struct sof_card_private *ctx = snd_soc_card_get_drvdata(rtd->card);
210 	struct snd_soc_dai *codec_dai = rtd->codec_dai;
211 	int clk_id, clk_freq, pll_out, ret;
212 
213 	if (sof_rt5682_quirk & SOF_RT5682_MCLK_EN) {
214 		if (sof_rt5682_quirk & SOF_RT5682_MCLK_BYTCHT_EN) {
215 			ret = clk_prepare_enable(ctx->mclk);
216 			if (ret < 0) {
217 				dev_err(rtd->dev,
218 					"could not configure MCLK state");
219 				return ret;
220 			}
221 		}
222 
223 		clk_id = RT5682_PLL1_S_MCLK;
224 		if (sof_rt5682_quirk & SOF_RT5682_MCLK_24MHZ)
225 			clk_freq = 24000000;
226 		else
227 			clk_freq = 19200000;
228 	} else {
229 		clk_id = RT5682_PLL1_S_BCLK1;
230 		clk_freq = params_rate(params) * 50;
231 	}
232 
233 	pll_out = params_rate(params) * 512;
234 
235 	ret = snd_soc_dai_set_pll(codec_dai, 0, clk_id, clk_freq, pll_out);
236 	if (ret < 0)
237 		dev_err(rtd->dev, "snd_soc_dai_set_pll err = %d\n", ret);
238 
239 	/* Configure sysclk for codec */
240 	ret = snd_soc_dai_set_sysclk(codec_dai, RT5682_SCLK_S_PLL1,
241 				     pll_out, SND_SOC_CLOCK_IN);
242 	if (ret < 0)
243 		dev_err(rtd->dev, "snd_soc_dai_set_sysclk err = %d\n", ret);
244 
245 	/*
246 	 * slot_width should equal or large than data length, set them
247 	 * be the same
248 	 */
249 	ret = snd_soc_dai_set_tdm_slot(codec_dai, 0x0, 0x0, 2,
250 				       params_width(params));
251 	if (ret < 0) {
252 		dev_err(rtd->dev, "set TDM slot err:%d\n", ret);
253 		return ret;
254 	}
255 
256 	return ret;
257 }
258 
259 static struct snd_soc_ops sof_rt5682_ops = {
260 	.hw_params = sof_rt5682_hw_params,
261 };
262 
263 static struct snd_soc_dai_link_component platform_component[] = {
264 	{
265 		/* name might be overridden during probe */
266 		.name = "0000:00:1f.3"
267 	}
268 };
269 
270 static int sof_card_late_probe(struct snd_soc_card *card)
271 {
272 	struct sof_card_private *ctx = snd_soc_card_get_drvdata(card);
273 	struct snd_soc_component *component = NULL;
274 	char jack_name[NAME_SIZE];
275 	struct sof_hdmi_pcm *pcm;
276 	int err;
277 	int i = 0;
278 
279 	/* HDMI is not supported by SOF on Baytrail/CherryTrail */
280 	if (is_legacy_cpu)
281 		return 0;
282 
283 	if (list_empty(&ctx->hdmi_pcm_list))
284 		return -EINVAL;
285 
286 	if (ctx->common_hdmi_codec_drv) {
287 		pcm = list_first_entry(&ctx->hdmi_pcm_list, struct sof_hdmi_pcm,
288 				       head);
289 		component = pcm->codec_dai->component;
290 		return hda_dsp_hdmi_build_controls(card, component);
291 	}
292 
293 	list_for_each_entry(pcm, &ctx->hdmi_pcm_list, head) {
294 		component = pcm->codec_dai->component;
295 		snprintf(jack_name, sizeof(jack_name),
296 			 "HDMI/DP, pcm=%d Jack", pcm->device);
297 		err = snd_soc_card_jack_new(card, jack_name,
298 					    SND_JACK_AVOUT, &sof_hdmi[i],
299 					    NULL, 0);
300 
301 		if (err)
302 			return err;
303 
304 		err = hdac_hdmi_jack_init(pcm->codec_dai, pcm->device,
305 					  &sof_hdmi[i]);
306 		if (err < 0)
307 			return err;
308 
309 		i++;
310 	}
311 
312 	return hdac_hdmi_jack_port_init(component, &card->dapm);
313 }
314 
315 static const struct snd_kcontrol_new sof_controls[] = {
316 	SOC_DAPM_PIN_SWITCH("Headphone Jack"),
317 	SOC_DAPM_PIN_SWITCH("Headset Mic"),
318 	SOC_DAPM_PIN_SWITCH("Spk"),
319 };
320 
321 static const struct snd_soc_dapm_widget sof_widgets[] = {
322 	SND_SOC_DAPM_HP("Headphone Jack", NULL),
323 	SND_SOC_DAPM_MIC("Headset Mic", NULL),
324 	SND_SOC_DAPM_SPK("Spk", NULL),
325 };
326 
327 static const struct snd_soc_dapm_widget dmic_widgets[] = {
328 	SND_SOC_DAPM_MIC("SoC DMIC", NULL),
329 };
330 
331 static const struct snd_soc_dapm_route sof_map[] = {
332 	/* HP jack connectors - unknown if we have jack detection */
333 	{ "Headphone Jack", NULL, "HPOL" },
334 	{ "Headphone Jack", NULL, "HPOR" },
335 
336 	/* other jacks */
337 	{ "IN1P", NULL, "Headset Mic" },
338 };
339 
340 static const struct snd_soc_dapm_route speaker_map[] = {
341 	/* speaker */
342 	{ "Spk", NULL, "Speaker" },
343 };
344 
345 static const struct snd_soc_dapm_route dmic_map[] = {
346 	/* digital mics */
347 	{"DMic", NULL, "SoC DMIC"},
348 };
349 
350 static int speaker_codec_init(struct snd_soc_pcm_runtime *rtd)
351 {
352 	struct snd_soc_card *card = rtd->card;
353 	int ret;
354 
355 	ret = snd_soc_dapm_add_routes(&card->dapm, speaker_map,
356 				      ARRAY_SIZE(speaker_map));
357 
358 	if (ret)
359 		dev_err(rtd->dev, "Speaker map addition failed: %d\n", ret);
360 	return ret;
361 }
362 
363 static int dmic_init(struct snd_soc_pcm_runtime *rtd)
364 {
365 	struct snd_soc_card *card = rtd->card;
366 	int ret;
367 
368 	ret = snd_soc_dapm_new_controls(&card->dapm, dmic_widgets,
369 					ARRAY_SIZE(dmic_widgets));
370 	if (ret) {
371 		dev_err(card->dev, "DMic widget addition failed: %d\n", ret);
372 		/* Don't need to add routes if widget addition failed */
373 		return ret;
374 	}
375 
376 	ret = snd_soc_dapm_add_routes(&card->dapm, dmic_map,
377 				      ARRAY_SIZE(dmic_map));
378 
379 	if (ret)
380 		dev_err(card->dev, "DMic map addition failed: %d\n", ret);
381 
382 	return ret;
383 }
384 
385 /* sof audio machine driver for rt5682 codec */
386 static struct snd_soc_card sof_audio_card_rt5682 = {
387 	.name = "rt5682", /* the sof- prefix is added by the core */
388 	.owner = THIS_MODULE,
389 	.controls = sof_controls,
390 	.num_controls = ARRAY_SIZE(sof_controls),
391 	.dapm_widgets = sof_widgets,
392 	.num_dapm_widgets = ARRAY_SIZE(sof_widgets),
393 	.dapm_routes = sof_map,
394 	.num_dapm_routes = ARRAY_SIZE(sof_map),
395 	.fully_routed = true,
396 	.late_probe = sof_card_late_probe,
397 };
398 
399 static struct snd_soc_dai_link_component rt5682_component[] = {
400 	{
401 		.name = "i2c-10EC5682:00",
402 		.dai_name = "rt5682-aif1",
403 	}
404 };
405 
406 static struct snd_soc_dai_link_component dmic_component[] = {
407 	{
408 		.name = "dmic-codec",
409 		.dai_name = "dmic-hifi",
410 	}
411 };
412 
413 static struct snd_soc_dai_link_component max98357a_component[] = {
414 	{
415 		.name = "MX98357A:00",
416 		.dai_name = "HiFi",
417 	}
418 };
419 
420 static struct snd_soc_dai_link *sof_card_dai_links_create(struct device *dev,
421 							  int ssp_codec,
422 							  int ssp_amp,
423 							  int dmic_be_num,
424 							  int hdmi_num)
425 {
426 	struct snd_soc_dai_link_component *idisp_components;
427 	struct snd_soc_dai_link_component *cpus;
428 	struct snd_soc_dai_link *links;
429 	int i, id = 0;
430 
431 	links = devm_kzalloc(dev, sizeof(struct snd_soc_dai_link) *
432 			     sof_audio_card_rt5682.num_links, GFP_KERNEL);
433 	cpus = devm_kzalloc(dev, sizeof(struct snd_soc_dai_link_component) *
434 			     sof_audio_card_rt5682.num_links, GFP_KERNEL);
435 	if (!links || !cpus)
436 		goto devm_err;
437 
438 	/* codec SSP */
439 	links[id].name = devm_kasprintf(dev, GFP_KERNEL,
440 					"SSP%d-Codec", ssp_codec);
441 	if (!links[id].name)
442 		goto devm_err;
443 
444 	links[id].id = id;
445 	links[id].codecs = rt5682_component;
446 	links[id].num_codecs = ARRAY_SIZE(rt5682_component);
447 	links[id].platforms = platform_component;
448 	links[id].num_platforms = ARRAY_SIZE(platform_component);
449 	links[id].init = sof_rt5682_codec_init;
450 	links[id].ops = &sof_rt5682_ops;
451 	links[id].nonatomic = true;
452 	links[id].dpcm_playback = 1;
453 	links[id].dpcm_capture = 1;
454 	links[id].no_pcm = 1;
455 	links[id].cpus = &cpus[id];
456 	links[id].num_cpus = 1;
457 	if (is_legacy_cpu) {
458 		links[id].cpus->dai_name = devm_kasprintf(dev, GFP_KERNEL,
459 							  "ssp%d-port",
460 							  ssp_codec);
461 		if (!links[id].cpus->dai_name)
462 			goto devm_err;
463 	} else {
464 		/*
465 		 * Currently, On SKL+ platforms MCLK will be turned off in sof
466 		 * runtime suspended, and it will go into runtime suspended
467 		 * right after playback is stop. However, rt5682 will output
468 		 * static noise if sysclk turns off during playback. Set
469 		 * ignore_pmdown_time to power down rt5682 immediately and
470 		 * avoid the noise.
471 		 * It can be removed once we can control MCLK by driver.
472 		 */
473 		links[id].ignore_pmdown_time = 1;
474 		links[id].cpus->dai_name = devm_kasprintf(dev, GFP_KERNEL,
475 							  "SSP%d Pin",
476 							  ssp_codec);
477 		if (!links[id].cpus->dai_name)
478 			goto devm_err;
479 	}
480 	id++;
481 
482 	/* dmic */
483 	if (dmic_be_num > 0) {
484 		/* at least we have dmic01 */
485 		links[id].name = "dmic01";
486 		links[id].cpus = &cpus[id];
487 		links[id].cpus->dai_name = "DMIC01 Pin";
488 		links[id].init = dmic_init;
489 		if (dmic_be_num > 1) {
490 			/* set up 2 BE links at most */
491 			links[id + 1].name = "dmic16k";
492 			links[id + 1].cpus = &cpus[id + 1];
493 			links[id + 1].cpus->dai_name = "DMIC16k Pin";
494 			dmic_be_num = 2;
495 		}
496 	}
497 
498 	for (i = 0; i < dmic_be_num; i++) {
499 		links[id].id = id;
500 		links[id].num_cpus = 1;
501 		links[id].codecs = dmic_component;
502 		links[id].num_codecs = ARRAY_SIZE(dmic_component);
503 		links[id].platforms = platform_component;
504 		links[id].num_platforms = ARRAY_SIZE(platform_component);
505 		links[id].ignore_suspend = 1;
506 		links[id].dpcm_capture = 1;
507 		links[id].no_pcm = 1;
508 		id++;
509 	}
510 
511 	/* HDMI */
512 	if (hdmi_num > 0) {
513 		idisp_components = devm_kzalloc(dev,
514 				   sizeof(struct snd_soc_dai_link_component) *
515 				   hdmi_num, GFP_KERNEL);
516 		if (!idisp_components)
517 			goto devm_err;
518 	}
519 	for (i = 1; i <= hdmi_num; i++) {
520 		links[id].name = devm_kasprintf(dev, GFP_KERNEL,
521 						"iDisp%d", i);
522 		if (!links[id].name)
523 			goto devm_err;
524 
525 		links[id].id = id;
526 		links[id].cpus = &cpus[id];
527 		links[id].num_cpus = 1;
528 		links[id].cpus->dai_name = devm_kasprintf(dev, GFP_KERNEL,
529 							  "iDisp%d Pin", i);
530 		if (!links[id].cpus->dai_name)
531 			goto devm_err;
532 
533 		idisp_components[i - 1].name = "ehdaudio0D2";
534 		idisp_components[i - 1].dai_name = devm_kasprintf(dev,
535 								  GFP_KERNEL,
536 								  "intel-hdmi-hifi%d",
537 								  i);
538 		if (!idisp_components[i - 1].dai_name)
539 			goto devm_err;
540 
541 		links[id].codecs = &idisp_components[i - 1];
542 		links[id].num_codecs = 1;
543 		links[id].platforms = platform_component;
544 		links[id].num_platforms = ARRAY_SIZE(platform_component);
545 		links[id].init = sof_hdmi_init;
546 		links[id].dpcm_playback = 1;
547 		links[id].no_pcm = 1;
548 		id++;
549 	}
550 
551 	/* speaker amp */
552 	if (sof_rt5682_quirk & SOF_SPEAKER_AMP_PRESENT) {
553 		links[id].name = devm_kasprintf(dev, GFP_KERNEL,
554 						"SSP%d-Codec", ssp_amp);
555 		if (!links[id].name)
556 			goto devm_err;
557 
558 		links[id].id = id;
559 		links[id].codecs = max98357a_component;
560 		links[id].num_codecs = ARRAY_SIZE(max98357a_component);
561 		links[id].platforms = platform_component;
562 		links[id].num_platforms = ARRAY_SIZE(platform_component);
563 		links[id].init = speaker_codec_init,
564 		links[id].nonatomic = true;
565 		links[id].dpcm_playback = 1;
566 		links[id].no_pcm = 1;
567 		links[id].cpus = &cpus[id];
568 		links[id].num_cpus = 1;
569 		if (is_legacy_cpu) {
570 			links[id].cpus->dai_name = devm_kasprintf(dev, GFP_KERNEL,
571 								  "ssp%d-port",
572 								  ssp_amp);
573 			if (!links[id].cpus->dai_name)
574 				goto devm_err;
575 
576 		} else {
577 			links[id].cpus->dai_name = devm_kasprintf(dev, GFP_KERNEL,
578 								  "SSP%d Pin",
579 								  ssp_amp);
580 			if (!links[id].cpus->dai_name)
581 				goto devm_err;
582 		}
583 	}
584 
585 	return links;
586 devm_err:
587 	return NULL;
588 }
589 
590 static int sof_audio_probe(struct platform_device *pdev)
591 {
592 	struct snd_soc_dai_link *dai_links;
593 	struct snd_soc_acpi_mach *mach;
594 	struct sof_card_private *ctx;
595 	int dmic_be_num, hdmi_num;
596 	int ret, ssp_amp, ssp_codec;
597 
598 	ctx = devm_kzalloc(&pdev->dev, sizeof(*ctx), GFP_KERNEL);
599 	if (!ctx)
600 		return -ENOMEM;
601 
602 	if (pdev->id_entry && pdev->id_entry->driver_data)
603 		sof_rt5682_quirk = (unsigned long)pdev->id_entry->driver_data;
604 
605 	dmi_check_system(sof_rt5682_quirk_table);
606 
607 	mach = (&pdev->dev)->platform_data;
608 
609 	/* A speaker amp might not be present when the quirk claims one is.
610 	 * Detect this via whether the machine driver match includes quirk_data.
611 	 */
612 	if ((sof_rt5682_quirk & SOF_SPEAKER_AMP_PRESENT) && !mach->quirk_data)
613 		sof_rt5682_quirk &= ~SOF_SPEAKER_AMP_PRESENT;
614 
615 	if (soc_intel_is_byt() || soc_intel_is_cht()) {
616 		is_legacy_cpu = 1;
617 		dmic_be_num = 0;
618 		hdmi_num = 0;
619 		/* default quirk for legacy cpu */
620 		sof_rt5682_quirk = SOF_RT5682_MCLK_EN |
621 						SOF_RT5682_MCLK_BYTCHT_EN |
622 						SOF_RT5682_SSP_CODEC(2);
623 	} else {
624 		dmic_be_num = 2;
625 		hdmi_num = (sof_rt5682_quirk & SOF_RT5682_NUM_HDMIDEV_MASK) >>
626 			 SOF_RT5682_NUM_HDMIDEV_SHIFT;
627 		/* default number of HDMI DAI's */
628 		if (!hdmi_num)
629 			hdmi_num = 3;
630 	}
631 
632 	/* need to get main clock from pmc */
633 	if (sof_rt5682_quirk & SOF_RT5682_MCLK_BYTCHT_EN) {
634 		ctx->mclk = devm_clk_get(&pdev->dev, "pmc_plt_clk_3");
635 		if (IS_ERR(ctx->mclk)) {
636 			ret = PTR_ERR(ctx->mclk);
637 
638 			dev_err(&pdev->dev,
639 				"Failed to get MCLK from pmc_plt_clk_3: %d\n",
640 				ret);
641 			return ret;
642 		}
643 
644 		ret = clk_prepare_enable(ctx->mclk);
645 		if (ret < 0) {
646 			dev_err(&pdev->dev,
647 				"could not configure MCLK state");
648 			return ret;
649 		}
650 	}
651 
652 	dev_dbg(&pdev->dev, "sof_rt5682_quirk = %lx\n", sof_rt5682_quirk);
653 
654 	ssp_amp = (sof_rt5682_quirk & SOF_RT5682_SSP_AMP_MASK) >>
655 			SOF_RT5682_SSP_AMP_SHIFT;
656 
657 	ssp_codec = sof_rt5682_quirk & SOF_RT5682_SSP_CODEC_MASK;
658 
659 	/* compute number of dai links */
660 	sof_audio_card_rt5682.num_links = 1 + dmic_be_num + hdmi_num;
661 
662 	if (sof_rt5682_quirk & SOF_SPEAKER_AMP_PRESENT)
663 		sof_audio_card_rt5682.num_links++;
664 
665 	dai_links = sof_card_dai_links_create(&pdev->dev, ssp_codec, ssp_amp,
666 					      dmic_be_num, hdmi_num);
667 	if (!dai_links)
668 		return -ENOMEM;
669 
670 	sof_audio_card_rt5682.dai_link = dai_links;
671 
672 	INIT_LIST_HEAD(&ctx->hdmi_pcm_list);
673 
674 	sof_audio_card_rt5682.dev = &pdev->dev;
675 
676 	/* set platform name for each dailink */
677 	ret = snd_soc_fixup_dai_links_platform_name(&sof_audio_card_rt5682,
678 						    mach->mach_params.platform);
679 	if (ret)
680 		return ret;
681 
682 	ctx->common_hdmi_codec_drv = mach->mach_params.common_hdmi_codec_drv;
683 
684 	snd_soc_card_set_drvdata(&sof_audio_card_rt5682, ctx);
685 
686 	return devm_snd_soc_register_card(&pdev->dev,
687 					  &sof_audio_card_rt5682);
688 }
689 
690 static int sof_rt5682_remove(struct platform_device *pdev)
691 {
692 	struct snd_soc_card *card = platform_get_drvdata(pdev);
693 	struct snd_soc_component *component = NULL;
694 
695 	for_each_card_components(card, component) {
696 		if (!strcmp(component->name, rt5682_component[0].name)) {
697 			snd_soc_component_set_jack(component, NULL, NULL);
698 			break;
699 		}
700 	}
701 
702 	return 0;
703 }
704 
705 static const struct platform_device_id board_ids[] = {
706 	{
707 		.name = "sof_rt5682",
708 	},
709 	{
710 		.name = "tgl_max98357a_rt5682",
711 		.driver_data = (kernel_ulong_t)(SOF_RT5682_MCLK_EN |
712 					SOF_RT5682_SSP_CODEC(0) |
713 					SOF_SPEAKER_AMP_PRESENT |
714 					SOF_RT5682_SSP_AMP(1) |
715 					SOF_RT5682_NUM_HDMIDEV(4)),
716 	},
717 	{ }
718 };
719 
720 static struct platform_driver sof_audio = {
721 	.probe = sof_audio_probe,
722 	.remove = sof_rt5682_remove,
723 	.driver = {
724 		.name = "sof_rt5682",
725 		.pm = &snd_soc_pm_ops,
726 	},
727 	.id_table = board_ids,
728 };
729 module_platform_driver(sof_audio)
730 
731 /* Module information */
732 MODULE_DESCRIPTION("SOF Audio Machine driver");
733 MODULE_AUTHOR("Bard Liao <bard.liao@intel.com>");
734 MODULE_AUTHOR("Sathya Prakash M R <sathya.prakash.m.r@intel.com>");
735 MODULE_LICENSE("GPL v2");
736 MODULE_ALIAS("platform:sof_rt5682");
737 MODULE_ALIAS("platform:tgl_max98357a_rt5682");
738