1 // SPDX-License-Identifier: GPL-2.0
2 /*
3  * mt8188-mt6359.c  --  MT8188-MT6359 ALSA SoC machine driver
4  *
5  * Copyright (c) 2022 MediaTek Inc.
6  * Author: Trevor Wu <trevor.wu@mediatek.com>
7  */
8 
9 #include <linux/module.h>
10 #include <linux/of_device.h>
11 #include <linux/pm_runtime.h>
12 #include <sound/jack.h>
13 #include <sound/pcm_params.h>
14 #include <sound/soc.h>
15 #include "mt8188-afe-common.h"
16 #include "../../codecs/mt6359.h"
17 #include "../common/mtk-afe-platform-driver.h"
18 #include "../common/mtk-soundcard-driver.h"
19 
20 /* FE */
21 SND_SOC_DAILINK_DEFS(playback2,
22 		     DAILINK_COMP_ARRAY(COMP_CPU("DL2")),
23 		     DAILINK_COMP_ARRAY(COMP_DUMMY()),
24 		     DAILINK_COMP_ARRAY(COMP_EMPTY()));
25 
26 SND_SOC_DAILINK_DEFS(playback3,
27 		     DAILINK_COMP_ARRAY(COMP_CPU("DL3")),
28 		     DAILINK_COMP_ARRAY(COMP_DUMMY()),
29 		     DAILINK_COMP_ARRAY(COMP_EMPTY()));
30 
31 SND_SOC_DAILINK_DEFS(playback6,
32 		     DAILINK_COMP_ARRAY(COMP_CPU("DL6")),
33 		     DAILINK_COMP_ARRAY(COMP_DUMMY()),
34 		     DAILINK_COMP_ARRAY(COMP_EMPTY()));
35 
36 SND_SOC_DAILINK_DEFS(playback7,
37 		     DAILINK_COMP_ARRAY(COMP_CPU("DL7")),
38 		     DAILINK_COMP_ARRAY(COMP_DUMMY()),
39 		     DAILINK_COMP_ARRAY(COMP_EMPTY()));
40 
41 SND_SOC_DAILINK_DEFS(playback8,
42 		     DAILINK_COMP_ARRAY(COMP_CPU("DL8")),
43 		     DAILINK_COMP_ARRAY(COMP_DUMMY()),
44 		     DAILINK_COMP_ARRAY(COMP_EMPTY()));
45 
46 SND_SOC_DAILINK_DEFS(playback10,
47 		     DAILINK_COMP_ARRAY(COMP_CPU("DL10")),
48 		     DAILINK_COMP_ARRAY(COMP_DUMMY()),
49 		     DAILINK_COMP_ARRAY(COMP_EMPTY()));
50 
51 SND_SOC_DAILINK_DEFS(playback11,
52 		     DAILINK_COMP_ARRAY(COMP_CPU("DL11")),
53 		     DAILINK_COMP_ARRAY(COMP_DUMMY()),
54 		     DAILINK_COMP_ARRAY(COMP_EMPTY()));
55 
56 SND_SOC_DAILINK_DEFS(capture1,
57 		     DAILINK_COMP_ARRAY(COMP_CPU("UL1")),
58 		     DAILINK_COMP_ARRAY(COMP_DUMMY()),
59 		     DAILINK_COMP_ARRAY(COMP_EMPTY()));
60 
61 SND_SOC_DAILINK_DEFS(capture2,
62 		     DAILINK_COMP_ARRAY(COMP_CPU("UL2")),
63 		     DAILINK_COMP_ARRAY(COMP_DUMMY()),
64 		     DAILINK_COMP_ARRAY(COMP_EMPTY()));
65 
66 SND_SOC_DAILINK_DEFS(capture3,
67 		     DAILINK_COMP_ARRAY(COMP_CPU("UL3")),
68 		     DAILINK_COMP_ARRAY(COMP_DUMMY()),
69 		     DAILINK_COMP_ARRAY(COMP_EMPTY()));
70 
71 SND_SOC_DAILINK_DEFS(capture4,
72 		     DAILINK_COMP_ARRAY(COMP_CPU("UL4")),
73 		     DAILINK_COMP_ARRAY(COMP_DUMMY()),
74 		     DAILINK_COMP_ARRAY(COMP_EMPTY()));
75 
76 SND_SOC_DAILINK_DEFS(capture5,
77 		     DAILINK_COMP_ARRAY(COMP_CPU("UL5")),
78 		     DAILINK_COMP_ARRAY(COMP_DUMMY()),
79 		     DAILINK_COMP_ARRAY(COMP_EMPTY()));
80 
81 SND_SOC_DAILINK_DEFS(capture6,
82 		     DAILINK_COMP_ARRAY(COMP_CPU("UL6")),
83 		     DAILINK_COMP_ARRAY(COMP_DUMMY()),
84 		     DAILINK_COMP_ARRAY(COMP_EMPTY()));
85 
86 SND_SOC_DAILINK_DEFS(capture8,
87 		     DAILINK_COMP_ARRAY(COMP_CPU("UL8")),
88 		     DAILINK_COMP_ARRAY(COMP_DUMMY()),
89 		     DAILINK_COMP_ARRAY(COMP_EMPTY()));
90 
91 SND_SOC_DAILINK_DEFS(capture9,
92 		     DAILINK_COMP_ARRAY(COMP_CPU("UL9")),
93 		     DAILINK_COMP_ARRAY(COMP_DUMMY()),
94 		     DAILINK_COMP_ARRAY(COMP_EMPTY()));
95 
96 SND_SOC_DAILINK_DEFS(capture10,
97 		     DAILINK_COMP_ARRAY(COMP_CPU("UL10")),
98 		     DAILINK_COMP_ARRAY(COMP_DUMMY()),
99 		     DAILINK_COMP_ARRAY(COMP_EMPTY()));
100 
101 /* BE */
102 SND_SOC_DAILINK_DEFS(adda,
103 		     DAILINK_COMP_ARRAY(COMP_CPU("ADDA")),
104 		     DAILINK_COMP_ARRAY(COMP_CODEC("mt6359-sound",
105 						   "mt6359-snd-codec-aif1")),
106 		     DAILINK_COMP_ARRAY(COMP_EMPTY()));
107 
108 SND_SOC_DAILINK_DEFS(dptx,
109 		     DAILINK_COMP_ARRAY(COMP_CPU("DPTX")),
110 		     DAILINK_COMP_ARRAY(COMP_DUMMY()),
111 		     DAILINK_COMP_ARRAY(COMP_EMPTY()));
112 
113 SND_SOC_DAILINK_DEFS(etdm1_in,
114 		     DAILINK_COMP_ARRAY(COMP_CPU("ETDM1_IN")),
115 		     DAILINK_COMP_ARRAY(COMP_DUMMY()),
116 		     DAILINK_COMP_ARRAY(COMP_EMPTY()));
117 
118 SND_SOC_DAILINK_DEFS(etdm2_in,
119 		     DAILINK_COMP_ARRAY(COMP_CPU("ETDM2_IN")),
120 		     DAILINK_COMP_ARRAY(COMP_DUMMY()),
121 		     DAILINK_COMP_ARRAY(COMP_EMPTY()));
122 
123 SND_SOC_DAILINK_DEFS(etdm1_out,
124 		     DAILINK_COMP_ARRAY(COMP_CPU("ETDM1_OUT")),
125 		     DAILINK_COMP_ARRAY(COMP_DUMMY()),
126 		     DAILINK_COMP_ARRAY(COMP_EMPTY()));
127 
128 SND_SOC_DAILINK_DEFS(etdm2_out,
129 		     DAILINK_COMP_ARRAY(COMP_CPU("ETDM2_OUT")),
130 		     DAILINK_COMP_ARRAY(COMP_DUMMY()),
131 		     DAILINK_COMP_ARRAY(COMP_EMPTY()));
132 
133 SND_SOC_DAILINK_DEFS(etdm3_out,
134 		     DAILINK_COMP_ARRAY(COMP_CPU("ETDM3_OUT")),
135 		     DAILINK_COMP_ARRAY(COMP_DUMMY()),
136 		     DAILINK_COMP_ARRAY(COMP_EMPTY()));
137 
138 SND_SOC_DAILINK_DEFS(pcm1,
139 		     DAILINK_COMP_ARRAY(COMP_CPU("PCM1")),
140 		     DAILINK_COMP_ARRAY(COMP_DUMMY()),
141 		     DAILINK_COMP_ARRAY(COMP_EMPTY()));
142 
143 struct mt8188_mt6359_priv {
144 	struct snd_soc_jack dp_jack;
145 	struct snd_soc_jack hdmi_jack;
146 };
147 
148 struct mt8188_card_data {
149 	const char *name;
150 	unsigned long quirk;
151 };
152 
153 static const struct snd_soc_dapm_widget mt8188_mt6359_widgets[] = {
154 	SND_SOC_DAPM_HP("Headphone", NULL),
155 	SND_SOC_DAPM_MIC("Headset Mic", NULL),
156 };
157 
158 static const struct snd_kcontrol_new mt8188_mt6359_controls[] = {
159 	SOC_DAPM_PIN_SWITCH("Headphone"),
160 	SOC_DAPM_PIN_SWITCH("Headset Mic"),
161 };
162 
163 #define CKSYS_AUD_TOP_CFG 0x032c
164 #define CKSYS_AUD_TOP_MON 0x0330
165 
166 static int mt8188_mt6359_mtkaif_calibration(struct snd_soc_pcm_runtime *rtd)
167 {
168 	struct snd_soc_component *cmpnt_afe =
169 		snd_soc_rtdcom_lookup(rtd, AFE_PCM_NAME);
170 	struct snd_soc_component *cmpnt_codec =
171 		asoc_rtd_to_codec(rtd, 0)->component;
172 	struct mtk_base_afe *afe;
173 	struct mt8188_afe_private *afe_priv;
174 	struct mtkaif_param *param;
175 	int chosen_phase_1, chosen_phase_2;
176 	int prev_cycle_1, prev_cycle_2;
177 	int test_done_1, test_done_2;
178 	int cycle_1, cycle_2;
179 	int mtkaif_chosen_phase[MT8188_MTKAIF_MISO_NUM];
180 	int mtkaif_phase_cycle[MT8188_MTKAIF_MISO_NUM];
181 	int mtkaif_calibration_num_phase;
182 	bool mtkaif_calibration_ok;
183 	unsigned int monitor = 0;
184 	int counter;
185 	int phase;
186 	int i;
187 
188 	if (!cmpnt_afe)
189 		return -EINVAL;
190 
191 	afe = snd_soc_component_get_drvdata(cmpnt_afe);
192 	afe_priv = afe->platform_priv;
193 	param = &afe_priv->mtkaif_params;
194 
195 	dev_dbg(afe->dev, "%s(), start\n", __func__);
196 
197 	param->mtkaif_calibration_ok = false;
198 	for (i = 0; i < MT8188_MTKAIF_MISO_NUM; i++) {
199 		param->mtkaif_chosen_phase[i] = -1;
200 		param->mtkaif_phase_cycle[i] = 0;
201 		mtkaif_chosen_phase[i] = -1;
202 		mtkaif_phase_cycle[i] = 0;
203 	}
204 
205 	if (IS_ERR(afe_priv->topckgen)) {
206 		dev_info(afe->dev, "%s() Cannot find topckgen controller\n",
207 			 __func__);
208 		return 0;
209 	}
210 
211 	pm_runtime_get_sync(afe->dev);
212 	mt6359_mtkaif_calibration_enable(cmpnt_codec);
213 
214 	/* set test type to synchronizer pulse */
215 	regmap_update_bits(afe_priv->topckgen,
216 			   CKSYS_AUD_TOP_CFG, 0xffff, 0x4);
217 	mtkaif_calibration_num_phase = 42;	/* mt6359: 0 ~ 42 */
218 	mtkaif_calibration_ok = true;
219 
220 	for (phase = 0;
221 	     phase <= mtkaif_calibration_num_phase && mtkaif_calibration_ok;
222 	     phase++) {
223 		mt6359_set_mtkaif_calibration_phase(cmpnt_codec,
224 						    phase, phase, phase);
225 
226 		regmap_set_bits(afe_priv->topckgen, CKSYS_AUD_TOP_CFG, 0x1);
227 
228 		test_done_1 = 0;
229 		test_done_2 = 0;
230 
231 		cycle_1 = -1;
232 		cycle_2 = -1;
233 
234 		counter = 0;
235 		while (!(test_done_1 & test_done_2)) {
236 			regmap_read(afe_priv->topckgen,
237 				    CKSYS_AUD_TOP_MON, &monitor);
238 			test_done_1 = (monitor >> 28) & 0x1;
239 			test_done_2 = (monitor >> 29) & 0x1;
240 
241 			if (test_done_1 == 1)
242 				cycle_1 = monitor & 0xf;
243 
244 			if (test_done_2 == 1)
245 				cycle_2 = (monitor >> 4) & 0xf;
246 
247 			/* handle if never test done */
248 			if (++counter > 10000) {
249 				dev_info(afe->dev, "%s(), test fail, cycle_1 %d, cycle_2 %d, monitor 0x%x\n",
250 					 __func__,
251 					 cycle_1, cycle_2, monitor);
252 				mtkaif_calibration_ok = false;
253 				break;
254 			}
255 		}
256 
257 		if (phase == 0) {
258 			prev_cycle_1 = cycle_1;
259 			prev_cycle_2 = cycle_2;
260 		}
261 
262 		if (cycle_1 != prev_cycle_1 &&
263 		    mtkaif_chosen_phase[MT8188_MTKAIF_MISO_0] < 0) {
264 			mtkaif_chosen_phase[MT8188_MTKAIF_MISO_0] = phase - 1;
265 			mtkaif_phase_cycle[MT8188_MTKAIF_MISO_0] = prev_cycle_1;
266 		}
267 
268 		if (cycle_2 != prev_cycle_2 &&
269 		    mtkaif_chosen_phase[MT8188_MTKAIF_MISO_1] < 0) {
270 			mtkaif_chosen_phase[MT8188_MTKAIF_MISO_1] = phase - 1;
271 			mtkaif_phase_cycle[MT8188_MTKAIF_MISO_1] = prev_cycle_2;
272 		}
273 
274 		regmap_clear_bits(afe_priv->topckgen, CKSYS_AUD_TOP_CFG, 0x1);
275 
276 		if (mtkaif_chosen_phase[MT8188_MTKAIF_MISO_0] >= 0 &&
277 		    mtkaif_chosen_phase[MT8188_MTKAIF_MISO_1] >= 0)
278 			break;
279 	}
280 
281 	if (mtkaif_chosen_phase[MT8188_MTKAIF_MISO_0] < 0) {
282 		mtkaif_calibration_ok = false;
283 		chosen_phase_1 = 0;
284 	} else {
285 		chosen_phase_1 = mtkaif_chosen_phase[MT8188_MTKAIF_MISO_0];
286 	}
287 
288 	if (mtkaif_chosen_phase[MT8188_MTKAIF_MISO_1] < 0) {
289 		mtkaif_calibration_ok = false;
290 		chosen_phase_2 = 0;
291 	} else {
292 		chosen_phase_2 = mtkaif_chosen_phase[MT8188_MTKAIF_MISO_1];
293 	}
294 
295 	mt6359_set_mtkaif_calibration_phase(cmpnt_codec,
296 					    chosen_phase_1,
297 					    chosen_phase_2,
298 					    0);
299 
300 	mt6359_mtkaif_calibration_disable(cmpnt_codec);
301 	pm_runtime_put(afe->dev);
302 
303 	param->mtkaif_calibration_ok = mtkaif_calibration_ok;
304 	param->mtkaif_chosen_phase[MT8188_MTKAIF_MISO_0] = chosen_phase_1;
305 	param->mtkaif_chosen_phase[MT8188_MTKAIF_MISO_1] = chosen_phase_2;
306 
307 	for (i = 0; i < MT8188_MTKAIF_MISO_NUM; i++)
308 		param->mtkaif_phase_cycle[i] = mtkaif_phase_cycle[i];
309 
310 	dev_info(afe->dev, "%s(), end, calibration ok %d\n",
311 		 __func__, param->mtkaif_calibration_ok);
312 
313 	return 0;
314 }
315 
316 static int mt8188_mt6359_init(struct snd_soc_pcm_runtime *rtd)
317 {
318 	struct snd_soc_component *cmpnt_codec =
319 		asoc_rtd_to_codec(rtd, 0)->component;
320 
321 	/* set mtkaif protocol */
322 	mt6359_set_mtkaif_protocol(cmpnt_codec,
323 				   MT6359_MTKAIF_PROTOCOL_2_CLK_P2);
324 
325 	/* mtkaif calibration */
326 	mt8188_mt6359_mtkaif_calibration(rtd);
327 
328 	return 0;
329 }
330 
331 enum {
332 	DAI_LINK_DL2_FE,
333 	DAI_LINK_DL3_FE,
334 	DAI_LINK_DL6_FE,
335 	DAI_LINK_DL7_FE,
336 	DAI_LINK_DL8_FE,
337 	DAI_LINK_DL10_FE,
338 	DAI_LINK_DL11_FE,
339 	DAI_LINK_UL1_FE,
340 	DAI_LINK_UL2_FE,
341 	DAI_LINK_UL3_FE,
342 	DAI_LINK_UL4_FE,
343 	DAI_LINK_UL5_FE,
344 	DAI_LINK_UL6_FE,
345 	DAI_LINK_UL8_FE,
346 	DAI_LINK_UL9_FE,
347 	DAI_LINK_UL10_FE,
348 	DAI_LINK_ADDA_BE,
349 	DAI_LINK_DPTX_BE,
350 	DAI_LINK_ETDM1_IN_BE,
351 	DAI_LINK_ETDM2_IN_BE,
352 	DAI_LINK_ETDM1_OUT_BE,
353 	DAI_LINK_ETDM2_OUT_BE,
354 	DAI_LINK_ETDM3_OUT_BE,
355 	DAI_LINK_PCM1_BE,
356 };
357 
358 static int mt8188_dptx_hw_params(struct snd_pcm_substream *substream,
359 				 struct snd_pcm_hw_params *params)
360 {
361 	struct snd_soc_pcm_runtime *rtd = substream->private_data;
362 	unsigned int rate = params_rate(params);
363 	unsigned int mclk_fs_ratio = 256;
364 	unsigned int mclk_fs = rate * mclk_fs_ratio;
365 	struct snd_soc_dai *dai = asoc_rtd_to_cpu(rtd, 0);
366 
367 	return snd_soc_dai_set_sysclk(dai, 0, mclk_fs, SND_SOC_CLOCK_OUT);
368 }
369 
370 static const struct snd_soc_ops mt8188_dptx_ops = {
371 	.hw_params = mt8188_dptx_hw_params,
372 };
373 
374 static int mt8188_dptx_hw_params_fixup(struct snd_soc_pcm_runtime *rtd,
375 				       struct snd_pcm_hw_params *params)
376 {
377 	/* fix BE i2s format to 32bit, clean param mask first */
378 	snd_mask_reset_range(hw_param_mask(params, SNDRV_PCM_HW_PARAM_FORMAT),
379 			     0, (__force unsigned int)SNDRV_PCM_FORMAT_LAST);
380 
381 	params_set_format(params, SNDRV_PCM_FORMAT_S32_LE);
382 
383 	return 0;
384 }
385 
386 static int mt8188_hdmi_codec_init(struct snd_soc_pcm_runtime *rtd)
387 {
388 	struct mt8188_mt6359_priv *priv = snd_soc_card_get_drvdata(rtd->card);
389 	struct snd_soc_component *component = asoc_rtd_to_codec(rtd, 0)->component;
390 	int ret = 0;
391 
392 	ret = snd_soc_card_jack_new(rtd->card, "HDMI Jack", SND_JACK_LINEOUT,
393 				    &priv->hdmi_jack);
394 	if (ret) {
395 		dev_info(rtd->dev, "%s, new jack failed: %d\n", __func__, ret);
396 		return ret;
397 	}
398 
399 	ret = snd_soc_component_set_jack(component, &priv->hdmi_jack, NULL);
400 	if (ret)
401 		dev_info(rtd->dev, "%s, set jack failed on %s (ret=%d)\n",
402 			 __func__, component->name, ret);
403 
404 	return ret;
405 }
406 
407 static int mt8188_dptx_codec_init(struct snd_soc_pcm_runtime *rtd)
408 {
409 	struct mt8188_mt6359_priv *priv = snd_soc_card_get_drvdata(rtd->card);
410 	struct snd_soc_component *component = asoc_rtd_to_codec(rtd, 0)->component;
411 	int ret = 0;
412 
413 	ret = snd_soc_card_jack_new(rtd->card, "DP Jack", SND_JACK_LINEOUT,
414 				    &priv->dp_jack);
415 	if (ret) {
416 		dev_info(rtd->dev, "%s, new jack failed: %d\n", __func__, ret);
417 		return ret;
418 	}
419 
420 	ret = snd_soc_component_set_jack(component, &priv->dp_jack, NULL);
421 	if (ret)
422 		dev_info(rtd->dev, "%s, set jack failed on %s (ret=%d)\n",
423 			 __func__, component->name, ret);
424 
425 	return ret;
426 }
427 
428 static struct snd_soc_dai_link mt8188_mt6359_dai_links[] = {
429 	/* FE */
430 	[DAI_LINK_DL2_FE] = {
431 		.name = "DL2_FE",
432 		.stream_name = "DL2 Playback",
433 		.trigger = {
434 			SND_SOC_DPCM_TRIGGER_POST,
435 			SND_SOC_DPCM_TRIGGER_POST,
436 		},
437 		.dynamic = 1,
438 		.dpcm_playback = 1,
439 		SND_SOC_DAILINK_REG(playback2),
440 	},
441 	[DAI_LINK_DL3_FE] = {
442 		.name = "DL3_FE",
443 		.stream_name = "DL3 Playback",
444 		.trigger = {
445 			SND_SOC_DPCM_TRIGGER_POST,
446 			SND_SOC_DPCM_TRIGGER_POST,
447 		},
448 		.dynamic = 1,
449 		.dpcm_playback = 1,
450 		SND_SOC_DAILINK_REG(playback3),
451 	},
452 	[DAI_LINK_DL6_FE] = {
453 		.name = "DL6_FE",
454 		.stream_name = "DL6 Playback",
455 		.trigger = {
456 			SND_SOC_DPCM_TRIGGER_POST,
457 			SND_SOC_DPCM_TRIGGER_POST,
458 		},
459 		.dynamic = 1,
460 		.dpcm_playback = 1,
461 		SND_SOC_DAILINK_REG(playback6),
462 	},
463 	[DAI_LINK_DL7_FE] = {
464 		.name = "DL7_FE",
465 		.stream_name = "DL7 Playback",
466 		.trigger = {
467 			SND_SOC_DPCM_TRIGGER_PRE,
468 			SND_SOC_DPCM_TRIGGER_PRE,
469 		},
470 		.dynamic = 1,
471 		.dpcm_playback = 1,
472 		SND_SOC_DAILINK_REG(playback7),
473 	},
474 	[DAI_LINK_DL8_FE] = {
475 		.name = "DL8_FE",
476 		.stream_name = "DL8 Playback",
477 		.trigger = {
478 			SND_SOC_DPCM_TRIGGER_POST,
479 			SND_SOC_DPCM_TRIGGER_POST,
480 		},
481 		.dynamic = 1,
482 		.dpcm_playback = 1,
483 		SND_SOC_DAILINK_REG(playback8),
484 	},
485 	[DAI_LINK_DL10_FE] = {
486 		.name = "DL10_FE",
487 		.stream_name = "DL10 Playback",
488 		.trigger = {
489 			SND_SOC_DPCM_TRIGGER_POST,
490 			SND_SOC_DPCM_TRIGGER_POST,
491 		},
492 		.dynamic = 1,
493 		.dpcm_playback = 1,
494 		SND_SOC_DAILINK_REG(playback10),
495 	},
496 	[DAI_LINK_DL11_FE] = {
497 		.name = "DL11_FE",
498 		.stream_name = "DL11 Playback",
499 		.trigger = {
500 			SND_SOC_DPCM_TRIGGER_POST,
501 			SND_SOC_DPCM_TRIGGER_POST,
502 		},
503 		.dynamic = 1,
504 		.dpcm_playback = 1,
505 		SND_SOC_DAILINK_REG(playback11),
506 	},
507 	[DAI_LINK_UL1_FE] = {
508 		.name = "UL1_FE",
509 		.stream_name = "UL1 Capture",
510 		.trigger = {
511 			SND_SOC_DPCM_TRIGGER_PRE,
512 			SND_SOC_DPCM_TRIGGER_PRE,
513 		},
514 		.dynamic = 1,
515 		.dpcm_capture = 1,
516 		SND_SOC_DAILINK_REG(capture1),
517 	},
518 	[DAI_LINK_UL2_FE] = {
519 		.name = "UL2_FE",
520 		.stream_name = "UL2 Capture",
521 		.trigger = {
522 			SND_SOC_DPCM_TRIGGER_POST,
523 			SND_SOC_DPCM_TRIGGER_POST,
524 		},
525 		.dynamic = 1,
526 		.dpcm_capture = 1,
527 		SND_SOC_DAILINK_REG(capture2),
528 	},
529 	[DAI_LINK_UL3_FE] = {
530 		.name = "UL3_FE",
531 		.stream_name = "UL3 Capture",
532 		.trigger = {
533 			SND_SOC_DPCM_TRIGGER_POST,
534 			SND_SOC_DPCM_TRIGGER_POST,
535 		},
536 		.dynamic = 1,
537 		.dpcm_capture = 1,
538 		SND_SOC_DAILINK_REG(capture3),
539 	},
540 	[DAI_LINK_UL4_FE] = {
541 		.name = "UL4_FE",
542 		.stream_name = "UL4 Capture",
543 		.trigger = {
544 			SND_SOC_DPCM_TRIGGER_POST,
545 			SND_SOC_DPCM_TRIGGER_POST,
546 		},
547 		.dynamic = 1,
548 		.dpcm_capture = 1,
549 		SND_SOC_DAILINK_REG(capture4),
550 	},
551 	[DAI_LINK_UL5_FE] = {
552 		.name = "UL5_FE",
553 		.stream_name = "UL5 Capture",
554 		.trigger = {
555 			SND_SOC_DPCM_TRIGGER_POST,
556 			SND_SOC_DPCM_TRIGGER_POST,
557 		},
558 		.dynamic = 1,
559 		.dpcm_capture = 1,
560 		SND_SOC_DAILINK_REG(capture5),
561 	},
562 	[DAI_LINK_UL6_FE] = {
563 		.name = "UL6_FE",
564 		.stream_name = "UL6 Capture",
565 		.trigger = {
566 			SND_SOC_DPCM_TRIGGER_PRE,
567 			SND_SOC_DPCM_TRIGGER_PRE,
568 		},
569 		.dynamic = 1,
570 		.dpcm_capture = 1,
571 		SND_SOC_DAILINK_REG(capture6),
572 	},
573 	[DAI_LINK_UL8_FE] = {
574 		.name = "UL8_FE",
575 		.stream_name = "UL8 Capture",
576 		.trigger = {
577 			SND_SOC_DPCM_TRIGGER_POST,
578 			SND_SOC_DPCM_TRIGGER_POST,
579 		},
580 		.dynamic = 1,
581 		.dpcm_capture = 1,
582 		SND_SOC_DAILINK_REG(capture8),
583 	},
584 	[DAI_LINK_UL9_FE] = {
585 		.name = "UL9_FE",
586 		.stream_name = "UL9 Capture",
587 		.trigger = {
588 			SND_SOC_DPCM_TRIGGER_POST,
589 			SND_SOC_DPCM_TRIGGER_POST,
590 		},
591 		.dynamic = 1,
592 		.dpcm_capture = 1,
593 		SND_SOC_DAILINK_REG(capture9),
594 	},
595 	[DAI_LINK_UL10_FE] = {
596 		.name = "UL10_FE",
597 		.stream_name = "UL10 Capture",
598 		.trigger = {
599 			SND_SOC_DPCM_TRIGGER_POST,
600 			SND_SOC_DPCM_TRIGGER_POST,
601 		},
602 		.dynamic = 1,
603 		.dpcm_capture = 1,
604 		SND_SOC_DAILINK_REG(capture10),
605 	},
606 	/* BE */
607 	[DAI_LINK_ADDA_BE] = {
608 		.name = "ADDA_BE",
609 		.no_pcm = 1,
610 		.dpcm_playback = 1,
611 		.dpcm_capture = 1,
612 		.init = mt8188_mt6359_init,
613 		SND_SOC_DAILINK_REG(adda),
614 	},
615 	[DAI_LINK_DPTX_BE] = {
616 		.name = "DPTX_BE",
617 		.ops = &mt8188_dptx_ops,
618 		.be_hw_params_fixup = mt8188_dptx_hw_params_fixup,
619 		.no_pcm = 1,
620 		.dpcm_playback = 1,
621 		SND_SOC_DAILINK_REG(dptx),
622 	},
623 	[DAI_LINK_ETDM1_IN_BE] = {
624 		.name = "ETDM1_IN_BE",
625 		.no_pcm = 1,
626 		.dai_fmt = SND_SOC_DAIFMT_I2S |
627 			SND_SOC_DAIFMT_NB_NF |
628 			SND_SOC_DAIFMT_CBP_CFP,
629 		.dpcm_capture = 1,
630 		.ignore_suspend = 1,
631 		SND_SOC_DAILINK_REG(etdm1_in),
632 	},
633 	[DAI_LINK_ETDM2_IN_BE] = {
634 		.name = "ETDM2_IN_BE",
635 		.no_pcm = 1,
636 		.dai_fmt = SND_SOC_DAIFMT_I2S |
637 			SND_SOC_DAIFMT_NB_NF |
638 			SND_SOC_DAIFMT_CBP_CFP,
639 		.dpcm_capture = 1,
640 		SND_SOC_DAILINK_REG(etdm2_in),
641 	},
642 	[DAI_LINK_ETDM1_OUT_BE] = {
643 		.name = "ETDM1_OUT_BE",
644 		.no_pcm = 1,
645 		.dai_fmt = SND_SOC_DAIFMT_I2S |
646 			SND_SOC_DAIFMT_NB_NF |
647 			SND_SOC_DAIFMT_CBC_CFC,
648 		.dpcm_playback = 1,
649 		SND_SOC_DAILINK_REG(etdm1_out),
650 	},
651 	[DAI_LINK_ETDM2_OUT_BE] = {
652 		.name = "ETDM2_OUT_BE",
653 		.no_pcm = 1,
654 		.dai_fmt = SND_SOC_DAIFMT_I2S |
655 			SND_SOC_DAIFMT_NB_NF |
656 			SND_SOC_DAIFMT_CBC_CFC,
657 		.dpcm_playback = 1,
658 		SND_SOC_DAILINK_REG(etdm2_out),
659 	},
660 	[DAI_LINK_ETDM3_OUT_BE] = {
661 		.name = "ETDM3_OUT_BE",
662 		.no_pcm = 1,
663 		.dai_fmt = SND_SOC_DAIFMT_I2S |
664 			SND_SOC_DAIFMT_NB_NF |
665 			SND_SOC_DAIFMT_CBC_CFC,
666 		.dpcm_playback = 1,
667 		SND_SOC_DAILINK_REG(etdm3_out),
668 	},
669 	[DAI_LINK_PCM1_BE] = {
670 		.name = "PCM1_BE",
671 		.no_pcm = 1,
672 		.dai_fmt = SND_SOC_DAIFMT_I2S |
673 			SND_SOC_DAIFMT_NB_NF |
674 			SND_SOC_DAIFMT_CBC_CFC,
675 		.dpcm_playback = 1,
676 		.dpcm_capture = 1,
677 		SND_SOC_DAILINK_REG(pcm1),
678 	},
679 };
680 
681 static struct snd_soc_card mt8188_mt6359_soc_card = {
682 	.owner = THIS_MODULE,
683 	.dai_link = mt8188_mt6359_dai_links,
684 	.num_links = ARRAY_SIZE(mt8188_mt6359_dai_links),
685 	.dapm_widgets = mt8188_mt6359_widgets,
686 	.num_dapm_widgets = ARRAY_SIZE(mt8188_mt6359_widgets),
687 	.controls = mt8188_mt6359_controls,
688 	.num_controls = ARRAY_SIZE(mt8188_mt6359_controls),
689 };
690 
691 static int mt8188_mt6359_dev_probe(struct platform_device *pdev)
692 {
693 	struct snd_soc_card *card = &mt8188_mt6359_soc_card;
694 	struct device_node *platform_node;
695 	struct mt8188_mt6359_priv *priv;
696 	struct mt8188_card_data *card_data;
697 	struct snd_soc_dai_link *dai_link;
698 	int ret, i;
699 
700 	card_data = (struct mt8188_card_data *)of_device_get_match_data(&pdev->dev);
701 	card->dev = &pdev->dev;
702 
703 	ret = snd_soc_of_parse_card_name(card, "model");
704 	if (ret)
705 		return dev_err_probe(&pdev->dev, ret, "%s new card name parsing error\n",
706 				     __func__);
707 
708 	if (!card->name)
709 		card->name = card_data->name;
710 
711 	priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL);
712 	if (!priv)
713 		return  -ENOMEM;
714 
715 	if (of_property_read_bool(pdev->dev.of_node, "audio-routing")) {
716 		ret = snd_soc_of_parse_audio_routing(card, "audio-routing");
717 		if (ret)
718 			return ret;
719 	}
720 
721 	platform_node = of_parse_phandle(pdev->dev.of_node,
722 					 "mediatek,platform", 0);
723 	if (!platform_node) {
724 		ret = -EINVAL;
725 		return dev_err_probe(&pdev->dev, ret, "Property 'platform' missing or invalid\n");
726 	}
727 
728 	ret = parse_dai_link_info(card);
729 	if (ret)
730 		goto err;
731 
732 	for_each_card_prelinks(card, i, dai_link) {
733 		if (!dai_link->platforms->name)
734 			dai_link->platforms->of_node = platform_node;
735 
736 		if (strcmp(dai_link->name, "DPTX_BE") == 0) {
737 			if (strcmp(dai_link->codecs->dai_name, "snd-soc-dummy-dai"))
738 				dai_link->init = mt8188_dptx_codec_init;
739 		} else if (strcmp(dai_link->name, "ETDM3_OUT_BE") == 0) {
740 			if (strcmp(dai_link->codecs->dai_name, "snd-soc-dummy-dai"))
741 				dai_link->init = mt8188_hdmi_codec_init;
742 		}
743 	}
744 
745 	snd_soc_card_set_drvdata(card, priv);
746 
747 	ret = devm_snd_soc_register_card(&pdev->dev, card);
748 	if (ret)
749 		dev_err_probe(&pdev->dev, ret, "%s snd_soc_register_card fail\n",
750 			      __func__);
751 err:
752 	of_node_put(platform_node);
753 	clean_card_reference(card);
754 	return ret;
755 }
756 
757 static struct mt8188_card_data mt8188_evb_card = {
758 	.name = "mt8188_mt6359",
759 };
760 
761 static const struct of_device_id mt8188_mt6359_dt_match[] = {
762 	{
763 		.compatible = "mediatek,mt8188-mt6359-evb",
764 		.data = &mt8188_evb_card,
765 	},
766 	{},
767 };
768 MODULE_DEVICE_TABLE(of, mt8188_mt6359_dt_match);
769 
770 static struct platform_driver mt8188_mt6359_driver = {
771 	.driver = {
772 		.name = "mt8188_mt6359",
773 		.of_match_table = mt8188_mt6359_dt_match,
774 		.pm = &snd_soc_pm_ops,
775 	},
776 	.probe = mt8188_mt6359_dev_probe,
777 };
778 
779 module_platform_driver(mt8188_mt6359_driver);
780 
781 /* Module information */
782 MODULE_DESCRIPTION("MT8188-MT6359 ALSA SoC machine driver");
783 MODULE_AUTHOR("Trevor Wu <trevor.wu@mediatek.com>");
784 MODULE_LICENSE("GPL");
785 MODULE_ALIAS("mt8188 mt6359 soc card");
786