1 // SPDX-License-Identifier: GPL-2.0-only
2 // Copyright(c) 2021 Intel Corporation.
3 // Copyright(c) 2021 Nuvoton Corporation.
4 
5 /*
6  * Intel SOF Machine Driver with Nuvoton headphone codec NAU8825
7  * and speaker codec RT1019P MAX98360a or MAX98373
8  */
9 #include <linux/i2c.h>
10 #include <linux/input.h>
11 #include <linux/module.h>
12 #include <linux/platform_device.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/soc-acpi.h>
21 #include "../../codecs/nau8825.h"
22 #include "../common/soc-intel-quirks.h"
23 #include "hda_dsp_common.h"
24 #include "sof_realtek_common.h"
25 #include "sof_maxim_common.h"
26 
27 #define NAME_SIZE 32
28 
29 #define SOF_NAU8825_SSP_CODEC(quirk)		((quirk) & GENMASK(2, 0))
30 #define SOF_NAU8825_SSP_CODEC_MASK		(GENMASK(2, 0))
31 #define SOF_SPEAKER_AMP_PRESENT		BIT(3)
32 #define SOF_NAU8825_SSP_AMP_SHIFT		4
33 #define SOF_NAU8825_SSP_AMP_MASK		(GENMASK(6, 4))
34 #define SOF_NAU8825_SSP_AMP(quirk)	\
35 	(((quirk) << SOF_NAU8825_SSP_AMP_SHIFT) & SOF_NAU8825_SSP_AMP_MASK)
36 #define SOF_NAU8825_NUM_HDMIDEV_SHIFT		7
37 #define SOF_NAU8825_NUM_HDMIDEV_MASK		(GENMASK(9, 7))
38 #define SOF_NAU8825_NUM_HDMIDEV(quirk)	\
39 	(((quirk) << SOF_NAU8825_NUM_HDMIDEV_SHIFT) & SOF_NAU8825_NUM_HDMIDEV_MASK)
40 
41 /* BT audio offload: reserve 3 bits for future */
42 #define SOF_BT_OFFLOAD_SSP_SHIFT		10
43 #define SOF_BT_OFFLOAD_SSP_MASK		(GENMASK(12, 10))
44 #define SOF_BT_OFFLOAD_SSP(quirk)	\
45 	(((quirk) << SOF_BT_OFFLOAD_SSP_SHIFT) & SOF_BT_OFFLOAD_SSP_MASK)
46 #define SOF_SSP_BT_OFFLOAD_PRESENT		BIT(13)
47 #define SOF_RT1019P_SPEAKER_AMP_PRESENT	BIT(14)
48 #define SOF_MAX98373_SPEAKER_AMP_PRESENT	BIT(15)
49 #define SOF_MAX98360A_SPEAKER_AMP_PRESENT	BIT(16)
50 
51 static unsigned long sof_nau8825_quirk = SOF_NAU8825_SSP_CODEC(0);
52 
53 struct sof_hdmi_pcm {
54 	struct list_head head;
55 	struct snd_soc_dai *codec_dai;
56 	int device;
57 };
58 
59 struct sof_card_private {
60 	struct clk *mclk;
61 	struct snd_soc_jack sof_headset;
62 	struct list_head hdmi_pcm_list;
63 };
64 
65 static int sof_hdmi_init(struct snd_soc_pcm_runtime *rtd)
66 {
67 	struct sof_card_private *ctx = snd_soc_card_get_drvdata(rtd->card);
68 	struct snd_soc_dai *dai = asoc_rtd_to_codec(rtd, 0);
69 	struct sof_hdmi_pcm *pcm;
70 
71 	pcm = devm_kzalloc(rtd->card->dev, sizeof(*pcm), GFP_KERNEL);
72 	if (!pcm)
73 		return -ENOMEM;
74 
75 	/* dai_link id is 1:1 mapped to the PCM device */
76 	pcm->device = rtd->dai_link->id;
77 	pcm->codec_dai = dai;
78 
79 	list_add_tail(&pcm->head, &ctx->hdmi_pcm_list);
80 
81 	return 0;
82 }
83 
84 static struct snd_soc_jack_pin jack_pins[] = {
85 	{
86 		.pin    = "Headphone Jack",
87 		.mask   = SND_JACK_HEADPHONE,
88 	},
89 	{
90 		.pin    = "Headset Mic",
91 		.mask   = SND_JACK_MICROPHONE,
92 	},
93 };
94 
95 static int sof_nau8825_codec_init(struct snd_soc_pcm_runtime *rtd)
96 {
97 	struct sof_card_private *ctx = snd_soc_card_get_drvdata(rtd->card);
98 	struct snd_soc_component *component = asoc_rtd_to_codec(rtd, 0)->component;
99 
100 	struct snd_soc_jack *jack;
101 	int ret;
102 
103 	/*
104 	 * Headset buttons map to the google Reference headset.
105 	 * These can be configured by userspace.
106 	 */
107 	ret = snd_soc_card_jack_new_pins(rtd->card, "Headset Jack",
108 					 SND_JACK_HEADSET | SND_JACK_BTN_0 |
109 					 SND_JACK_BTN_1 | SND_JACK_BTN_2 |
110 					 SND_JACK_BTN_3,
111 					 &ctx->sof_headset,
112 					 jack_pins,
113 					 ARRAY_SIZE(jack_pins));
114 	if (ret) {
115 		dev_err(rtd->dev, "Headset Jack creation failed: %d\n", ret);
116 		return ret;
117 	}
118 
119 	jack = &ctx->sof_headset;
120 
121 	snd_jack_set_key(jack->jack, SND_JACK_BTN_0, KEY_PLAYPAUSE);
122 	snd_jack_set_key(jack->jack, SND_JACK_BTN_1, KEY_VOICECOMMAND);
123 	snd_jack_set_key(jack->jack, SND_JACK_BTN_2, KEY_VOLUMEUP);
124 	snd_jack_set_key(jack->jack, SND_JACK_BTN_3, KEY_VOLUMEDOWN);
125 	ret = snd_soc_component_set_jack(component, jack, NULL);
126 
127 	if (ret) {
128 		dev_err(rtd->dev, "Headset Jack call-back failed: %d\n", ret);
129 		return ret;
130 	}
131 
132 	return ret;
133 };
134 
135 static void sof_nau8825_codec_exit(struct snd_soc_pcm_runtime *rtd)
136 {
137 	struct snd_soc_component *component = asoc_rtd_to_codec(rtd, 0)->component;
138 
139 	snd_soc_component_set_jack(component, NULL, NULL);
140 }
141 
142 static int sof_nau8825_hw_params(struct snd_pcm_substream *substream,
143 				 struct snd_pcm_hw_params *params)
144 {
145 	struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
146 	struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0);
147 	int clk_freq, ret;
148 
149 	clk_freq = sof_dai_get_bclk(rtd); /* BCLK freq */
150 
151 	if (clk_freq <= 0) {
152 		dev_err(rtd->dev, "get bclk freq failed: %d\n", clk_freq);
153 		return -EINVAL;
154 	}
155 
156 	/* Configure clock for codec */
157 	ret = snd_soc_dai_set_sysclk(codec_dai, NAU8825_CLK_FLL_BLK, 0,
158 				     SND_SOC_CLOCK_IN);
159 	if (ret < 0) {
160 		dev_err(codec_dai->dev, "can't set BCLK clock %d\n", ret);
161 		return ret;
162 	}
163 
164 	/* Configure pll for codec */
165 	ret = snd_soc_dai_set_pll(codec_dai, 0, 0, clk_freq,
166 				  params_rate(params) * 256);
167 	if (ret < 0) {
168 		dev_err(codec_dai->dev, "can't set BCLK: %d\n", ret);
169 		return ret;
170 	}
171 
172 	return ret;
173 }
174 
175 static struct snd_soc_ops sof_nau8825_ops = {
176 	.hw_params = sof_nau8825_hw_params,
177 };
178 
179 static struct snd_soc_dai_link_component platform_component[] = {
180 	{
181 		/* name might be overridden during probe */
182 		.name = "0000:00:1f.3"
183 	}
184 };
185 
186 static int sof_card_late_probe(struct snd_soc_card *card)
187 {
188 	struct sof_card_private *ctx = snd_soc_card_get_drvdata(card);
189 	struct snd_soc_dapm_context *dapm = &card->dapm;
190 	struct sof_hdmi_pcm *pcm;
191 	int err;
192 
193 	if (sof_nau8825_quirk & SOF_MAX98373_SPEAKER_AMP_PRESENT) {
194 		/* Disable Left and Right Spk pin after boot */
195 		snd_soc_dapm_disable_pin(dapm, "Left Spk");
196 		snd_soc_dapm_disable_pin(dapm, "Right Spk");
197 		err = snd_soc_dapm_sync(dapm);
198 		if (err < 0)
199 			return err;
200 	}
201 
202 	if (list_empty(&ctx->hdmi_pcm_list))
203 		return -EINVAL;
204 
205 	pcm = list_first_entry(&ctx->hdmi_pcm_list, struct sof_hdmi_pcm, head);
206 
207 	return hda_dsp_hdmi_build_controls(card, pcm->codec_dai->component);
208 }
209 
210 static const struct snd_kcontrol_new sof_controls[] = {
211 	SOC_DAPM_PIN_SWITCH("Headphone Jack"),
212 	SOC_DAPM_PIN_SWITCH("Headset Mic"),
213 	SOC_DAPM_PIN_SWITCH("Left Spk"),
214 	SOC_DAPM_PIN_SWITCH("Right Spk"),
215 };
216 
217 static const struct snd_kcontrol_new speaker_controls[] = {
218 	SOC_DAPM_PIN_SWITCH("Spk"),
219 };
220 
221 static const struct snd_soc_dapm_widget sof_widgets[] = {
222 	SND_SOC_DAPM_HP("Headphone Jack", NULL),
223 	SND_SOC_DAPM_MIC("Headset Mic", NULL),
224 	SND_SOC_DAPM_SPK("Left Spk", NULL),
225 	SND_SOC_DAPM_SPK("Right Spk", NULL),
226 };
227 
228 static const struct snd_soc_dapm_widget speaker_widgets[] = {
229 	SND_SOC_DAPM_SPK("Spk", NULL),
230 };
231 
232 static const struct snd_soc_dapm_widget dmic_widgets[] = {
233 	SND_SOC_DAPM_MIC("SoC DMIC", NULL),
234 };
235 
236 static const struct snd_soc_dapm_route sof_map[] = {
237 	/* HP jack connectors - unknown if we have jack detection */
238 	{ "Headphone Jack", NULL, "HPOL" },
239 	{ "Headphone Jack", NULL, "HPOR" },
240 
241 	/* other jacks */
242 	{ "MIC", NULL, "Headset Mic" },
243 };
244 
245 static const struct snd_soc_dapm_route speaker_map[] = {
246 	/* speaker */
247 	{ "Spk", NULL, "Speaker" },
248 };
249 
250 static const struct snd_soc_dapm_route dmic_map[] = {
251 	/* digital mics */
252 	{"DMic", NULL, "SoC DMIC"},
253 };
254 
255 static int speaker_codec_init(struct snd_soc_pcm_runtime *rtd)
256 {
257 	struct snd_soc_card *card = rtd->card;
258 	int ret;
259 
260 	ret = snd_soc_dapm_new_controls(&card->dapm, speaker_widgets,
261 					ARRAY_SIZE(speaker_widgets));
262 	if (ret) {
263 		dev_err(rtd->dev, "unable to add dapm controls, ret %d\n", ret);
264 		/* Don't need to add routes if widget addition failed */
265 		return ret;
266 	}
267 
268 	ret = snd_soc_add_card_controls(card, speaker_controls,
269 					ARRAY_SIZE(speaker_controls));
270 	if (ret) {
271 		dev_err(rtd->dev, "unable to add card controls, ret %d\n", ret);
272 		return ret;
273 	}
274 
275 	ret = snd_soc_dapm_add_routes(&card->dapm, speaker_map,
276 				      ARRAY_SIZE(speaker_map));
277 
278 	if (ret)
279 		dev_err(rtd->dev, "Speaker map addition failed: %d\n", ret);
280 	return ret;
281 }
282 
283 static int dmic_init(struct snd_soc_pcm_runtime *rtd)
284 {
285 	struct snd_soc_card *card = rtd->card;
286 	int ret;
287 
288 	ret = snd_soc_dapm_new_controls(&card->dapm, dmic_widgets,
289 					ARRAY_SIZE(dmic_widgets));
290 	if (ret) {
291 		dev_err(card->dev, "DMic widget addition failed: %d\n", ret);
292 		/* Don't need to add routes if widget addition failed */
293 		return ret;
294 	}
295 
296 	ret = snd_soc_dapm_add_routes(&card->dapm, dmic_map,
297 				      ARRAY_SIZE(dmic_map));
298 
299 	if (ret)
300 		dev_err(card->dev, "DMic map addition failed: %d\n", ret);
301 
302 	return ret;
303 }
304 
305 /* sof audio machine driver for nau8825 codec */
306 static struct snd_soc_card sof_audio_card_nau8825 = {
307 	.name = "nau8825", /* the sof- prefix is added by the core */
308 	.owner = THIS_MODULE,
309 	.controls = sof_controls,
310 	.num_controls = ARRAY_SIZE(sof_controls),
311 	.dapm_widgets = sof_widgets,
312 	.num_dapm_widgets = ARRAY_SIZE(sof_widgets),
313 	.dapm_routes = sof_map,
314 	.num_dapm_routes = ARRAY_SIZE(sof_map),
315 	.fully_routed = true,
316 	.late_probe = sof_card_late_probe,
317 };
318 
319 static struct snd_soc_dai_link_component nau8825_component[] = {
320 	{
321 		.name = "i2c-10508825:00",
322 		.dai_name = "nau8825-hifi",
323 	}
324 };
325 
326 static struct snd_soc_dai_link_component dmic_component[] = {
327 	{
328 		.name = "dmic-codec",
329 		.dai_name = "dmic-hifi",
330 	}
331 };
332 
333 static struct snd_soc_dai_link_component rt1019p_component[] = {
334 	{
335 		.name = "RTL1019:00",
336 		.dai_name = "HiFi",
337 	}
338 };
339 
340 static struct snd_soc_dai_link_component dummy_component[] = {
341 	{
342 		.name = "snd-soc-dummy",
343 		.dai_name = "snd-soc-dummy-dai",
344 	}
345 };
346 
347 static struct snd_soc_dai_link *sof_card_dai_links_create(struct device *dev,
348 							  int ssp_codec,
349 							  int ssp_amp,
350 							  int dmic_be_num,
351 							  int hdmi_num)
352 {
353 	struct snd_soc_dai_link_component *idisp_components;
354 	struct snd_soc_dai_link_component *cpus;
355 	struct snd_soc_dai_link *links;
356 	int i, id = 0;
357 
358 	links = devm_kcalloc(dev, sof_audio_card_nau8825.num_links,
359 			    sizeof(struct snd_soc_dai_link), GFP_KERNEL);
360 	cpus = devm_kcalloc(dev, sof_audio_card_nau8825.num_links,
361 			    sizeof(struct snd_soc_dai_link_component), GFP_KERNEL);
362 	if (!links || !cpus)
363 		goto devm_err;
364 
365 	/* codec SSP */
366 	links[id].name = devm_kasprintf(dev, GFP_KERNEL,
367 					"SSP%d-Codec", ssp_codec);
368 	if (!links[id].name)
369 		goto devm_err;
370 
371 	links[id].id = id;
372 	links[id].codecs = nau8825_component;
373 	links[id].num_codecs = ARRAY_SIZE(nau8825_component);
374 	links[id].platforms = platform_component;
375 	links[id].num_platforms = ARRAY_SIZE(platform_component);
376 	links[id].init = sof_nau8825_codec_init;
377 	links[id].exit = sof_nau8825_codec_exit;
378 	links[id].ops = &sof_nau8825_ops;
379 	links[id].dpcm_playback = 1;
380 	links[id].dpcm_capture = 1;
381 	links[id].no_pcm = 1;
382 	links[id].cpus = &cpus[id];
383 	links[id].num_cpus = 1;
384 
385 	links[id].cpus->dai_name = devm_kasprintf(dev, GFP_KERNEL,
386 						  "SSP%d Pin",
387 						  ssp_codec);
388 	if (!links[id].cpus->dai_name)
389 		goto devm_err;
390 
391 	id++;
392 
393 	/* dmic */
394 	if (dmic_be_num > 0) {
395 		/* at least we have dmic01 */
396 		links[id].name = "dmic01";
397 		links[id].cpus = &cpus[id];
398 		links[id].cpus->dai_name = "DMIC01 Pin";
399 		links[id].init = dmic_init;
400 		if (dmic_be_num > 1) {
401 			/* set up 2 BE links at most */
402 			links[id + 1].name = "dmic16k";
403 			links[id + 1].cpus = &cpus[id + 1];
404 			links[id + 1].cpus->dai_name = "DMIC16k Pin";
405 			dmic_be_num = 2;
406 		}
407 	}
408 
409 	for (i = 0; i < dmic_be_num; i++) {
410 		links[id].id = id;
411 		links[id].num_cpus = 1;
412 		links[id].codecs = dmic_component;
413 		links[id].num_codecs = ARRAY_SIZE(dmic_component);
414 		links[id].platforms = platform_component;
415 		links[id].num_platforms = ARRAY_SIZE(platform_component);
416 		links[id].ignore_suspend = 1;
417 		links[id].dpcm_capture = 1;
418 		links[id].no_pcm = 1;
419 		id++;
420 	}
421 
422 	/* HDMI */
423 	if (hdmi_num > 0) {
424 		idisp_components = devm_kcalloc(dev,
425 						hdmi_num,
426 						sizeof(struct snd_soc_dai_link_component),
427 						GFP_KERNEL);
428 		if (!idisp_components)
429 			goto devm_err;
430 	}
431 	for (i = 1; i <= hdmi_num; i++) {
432 		links[id].name = devm_kasprintf(dev, GFP_KERNEL,
433 						"iDisp%d", i);
434 		if (!links[id].name)
435 			goto devm_err;
436 
437 		links[id].id = id;
438 		links[id].cpus = &cpus[id];
439 		links[id].num_cpus = 1;
440 		links[id].cpus->dai_name = devm_kasprintf(dev, GFP_KERNEL,
441 							  "iDisp%d Pin", i);
442 		if (!links[id].cpus->dai_name)
443 			goto devm_err;
444 
445 		idisp_components[i - 1].name = "ehdaudio0D2";
446 		idisp_components[i - 1].dai_name = devm_kasprintf(dev,
447 								  GFP_KERNEL,
448 								  "intel-hdmi-hifi%d",
449 								  i);
450 		if (!idisp_components[i - 1].dai_name)
451 			goto devm_err;
452 
453 		links[id].codecs = &idisp_components[i - 1];
454 		links[id].num_codecs = 1;
455 		links[id].platforms = platform_component;
456 		links[id].num_platforms = ARRAY_SIZE(platform_component);
457 		links[id].init = sof_hdmi_init;
458 		links[id].dpcm_playback = 1;
459 		links[id].no_pcm = 1;
460 		id++;
461 	}
462 
463 	/* speaker amp */
464 	if (sof_nau8825_quirk & SOF_SPEAKER_AMP_PRESENT) {
465 		links[id].name = devm_kasprintf(dev, GFP_KERNEL,
466 						"SSP%d-Codec", ssp_amp);
467 		if (!links[id].name)
468 			goto devm_err;
469 
470 		links[id].id = id;
471 		if (sof_nau8825_quirk & SOF_RT1019P_SPEAKER_AMP_PRESENT) {
472 			links[id].codecs = rt1019p_component;
473 			links[id].num_codecs = ARRAY_SIZE(rt1019p_component);
474 			links[id].init = speaker_codec_init;
475 		} else if (sof_nau8825_quirk &
476 				SOF_MAX98373_SPEAKER_AMP_PRESENT) {
477 			links[id].codecs = max_98373_components;
478 			links[id].num_codecs = ARRAY_SIZE(max_98373_components);
479 			links[id].init = max_98373_spk_codec_init;
480 			links[id].ops = &max_98373_ops;
481 			/* feedback stream */
482 			links[id].dpcm_capture = 1;
483 		} else if (sof_nau8825_quirk &
484 				SOF_MAX98360A_SPEAKER_AMP_PRESENT) {
485 			max_98360a_dai_link(&links[id]);
486 		} else {
487 			goto devm_err;
488 		}
489 
490 		links[id].platforms = platform_component;
491 		links[id].num_platforms = ARRAY_SIZE(platform_component);
492 		links[id].dpcm_playback = 1;
493 		links[id].no_pcm = 1;
494 		links[id].cpus = &cpus[id];
495 		links[id].num_cpus = 1;
496 		links[id].cpus->dai_name = devm_kasprintf(dev, GFP_KERNEL,
497 							  "SSP%d Pin",
498 							  ssp_amp);
499 		if (!links[id].cpus->dai_name)
500 			goto devm_err;
501 		id++;
502 	}
503 
504 	/* BT audio offload */
505 	if (sof_nau8825_quirk & SOF_SSP_BT_OFFLOAD_PRESENT) {
506 		int port = (sof_nau8825_quirk & SOF_BT_OFFLOAD_SSP_MASK) >>
507 				SOF_BT_OFFLOAD_SSP_SHIFT;
508 
509 		links[id].id = id;
510 		links[id].cpus = &cpus[id];
511 		links[id].cpus->dai_name = devm_kasprintf(dev, GFP_KERNEL,
512 							  "SSP%d Pin", port);
513 		if (!links[id].cpus->dai_name)
514 			goto devm_err;
515 		links[id].name = devm_kasprintf(dev, GFP_KERNEL, "SSP%d-BT", port);
516 		if (!links[id].name)
517 			goto devm_err;
518 		links[id].codecs = dummy_component;
519 		links[id].num_codecs = ARRAY_SIZE(dummy_component);
520 		links[id].platforms = platform_component;
521 		links[id].num_platforms = ARRAY_SIZE(platform_component);
522 		links[id].dpcm_playback = 1;
523 		links[id].dpcm_capture = 1;
524 		links[id].no_pcm = 1;
525 		links[id].num_cpus = 1;
526 	}
527 
528 	return links;
529 devm_err:
530 	return NULL;
531 }
532 
533 static int sof_audio_probe(struct platform_device *pdev)
534 {
535 	struct snd_soc_dai_link *dai_links;
536 	struct snd_soc_acpi_mach *mach;
537 	struct sof_card_private *ctx;
538 	int dmic_be_num, hdmi_num;
539 	int ret, ssp_amp, ssp_codec;
540 
541 	ctx = devm_kzalloc(&pdev->dev, sizeof(*ctx), GFP_KERNEL);
542 	if (!ctx)
543 		return -ENOMEM;
544 
545 	if (pdev->id_entry && pdev->id_entry->driver_data)
546 		sof_nau8825_quirk = (unsigned long)pdev->id_entry->driver_data;
547 
548 	mach = pdev->dev.platform_data;
549 
550 	/* A speaker amp might not be present when the quirk claims one is.
551 	 * Detect this via whether the machine driver match includes quirk_data.
552 	 */
553 	if ((sof_nau8825_quirk & SOF_SPEAKER_AMP_PRESENT) && !mach->quirk_data)
554 		sof_nau8825_quirk &= ~SOF_SPEAKER_AMP_PRESENT;
555 
556 	dev_dbg(&pdev->dev, "sof_nau8825_quirk = %lx\n", sof_nau8825_quirk);
557 
558 	/* default number of DMIC DAI's */
559 	dmic_be_num = 2;
560 	hdmi_num = (sof_nau8825_quirk & SOF_NAU8825_NUM_HDMIDEV_MASK) >>
561 			SOF_NAU8825_NUM_HDMIDEV_SHIFT;
562 	/* default number of HDMI DAI's */
563 	if (!hdmi_num)
564 		hdmi_num = 3;
565 
566 	ssp_amp = (sof_nau8825_quirk & SOF_NAU8825_SSP_AMP_MASK) >>
567 			SOF_NAU8825_SSP_AMP_SHIFT;
568 
569 	ssp_codec = sof_nau8825_quirk & SOF_NAU8825_SSP_CODEC_MASK;
570 
571 	/* compute number of dai links */
572 	sof_audio_card_nau8825.num_links = 1 + dmic_be_num + hdmi_num;
573 
574 	if (sof_nau8825_quirk & SOF_SPEAKER_AMP_PRESENT)
575 		sof_audio_card_nau8825.num_links++;
576 
577 	if (sof_nau8825_quirk & SOF_MAX98373_SPEAKER_AMP_PRESENT)
578 		max_98373_set_codec_conf(&sof_audio_card_nau8825);
579 
580 	if (sof_nau8825_quirk & SOF_SSP_BT_OFFLOAD_PRESENT)
581 		sof_audio_card_nau8825.num_links++;
582 
583 	dai_links = sof_card_dai_links_create(&pdev->dev, ssp_codec, ssp_amp,
584 					      dmic_be_num, hdmi_num);
585 	if (!dai_links)
586 		return -ENOMEM;
587 
588 	sof_audio_card_nau8825.dai_link = dai_links;
589 
590 	INIT_LIST_HEAD(&ctx->hdmi_pcm_list);
591 
592 	sof_audio_card_nau8825.dev = &pdev->dev;
593 
594 	/* set platform name for each dailink */
595 	ret = snd_soc_fixup_dai_links_platform_name(&sof_audio_card_nau8825,
596 						    mach->mach_params.platform);
597 	if (ret)
598 		return ret;
599 
600 	snd_soc_card_set_drvdata(&sof_audio_card_nau8825, ctx);
601 
602 	return devm_snd_soc_register_card(&pdev->dev,
603 					  &sof_audio_card_nau8825);
604 }
605 
606 static const struct platform_device_id board_ids[] = {
607 	{
608 		.name = "sof_nau8825",
609 		.driver_data = (kernel_ulong_t)(SOF_NAU8825_SSP_CODEC(0) |
610 					SOF_NAU8825_NUM_HDMIDEV(4) |
611 					SOF_BT_OFFLOAD_SSP(2) |
612 					SOF_SSP_BT_OFFLOAD_PRESENT),
613 
614 	},
615 	{
616 		.name = "adl_rt1019p_nau8825",
617 		.driver_data = (kernel_ulong_t)(SOF_NAU8825_SSP_CODEC(0) |
618 					SOF_SPEAKER_AMP_PRESENT |
619 					SOF_RT1019P_SPEAKER_AMP_PRESENT |
620 					SOF_NAU8825_SSP_AMP(2) |
621 					SOF_NAU8825_NUM_HDMIDEV(4)),
622 	},
623 	{
624 		.name = "adl_max98373_nau8825",
625 		.driver_data = (kernel_ulong_t)(SOF_NAU8825_SSP_CODEC(0) |
626 					SOF_SPEAKER_AMP_PRESENT |
627 					SOF_MAX98373_SPEAKER_AMP_PRESENT |
628 					SOF_NAU8825_SSP_AMP(1) |
629 					SOF_NAU8825_NUM_HDMIDEV(4) |
630 					SOF_BT_OFFLOAD_SSP(2) |
631 					SOF_SSP_BT_OFFLOAD_PRESENT),
632 	},
633 	{
634 		/* The limitation of length of char array, shorten the name */
635 		.name = "adl_mx98360a_nau8825",
636 		.driver_data = (kernel_ulong_t)(SOF_NAU8825_SSP_CODEC(0) |
637 					SOF_SPEAKER_AMP_PRESENT |
638 					SOF_MAX98360A_SPEAKER_AMP_PRESENT |
639 					SOF_NAU8825_SSP_AMP(1) |
640 					SOF_NAU8825_NUM_HDMIDEV(4) |
641 					SOF_BT_OFFLOAD_SSP(2) |
642 					SOF_SSP_BT_OFFLOAD_PRESENT),
643 
644 	},
645 	{ }
646 };
647 MODULE_DEVICE_TABLE(platform, board_ids);
648 
649 static struct platform_driver sof_audio = {
650 	.probe = sof_audio_probe,
651 	.driver = {
652 		.name = "sof_nau8825",
653 		.pm = &snd_soc_pm_ops,
654 	},
655 	.id_table = board_ids,
656 };
657 module_platform_driver(sof_audio)
658 
659 /* Module information */
660 MODULE_DESCRIPTION("SOF Audio Machine driver for NAU8825");
661 MODULE_AUTHOR("David Lin <ctlin0@nuvoton.com>");
662 MODULE_AUTHOR("Mac Chiang <mac.chiang@intel.com>");
663 MODULE_LICENSE("GPL");
664 MODULE_IMPORT_NS(SND_SOC_INTEL_HDA_DSP_COMMON);
665 MODULE_IMPORT_NS(SND_SOC_INTEL_SOF_MAXIM_COMMON);
666