1 // SPDX-License-Identifier: GPL-2.0
2 //
3 // mt8186-mt6366-da7219-max98357.c
4 //	--  MT8186-MT6366-DA7219-MAX98357 ALSA SoC machine driver
5 //
6 // Copyright (c) 2022 MediaTek Inc.
7 // Author: Jiaxin Yu <jiaxin.yu@mediatek.com>
8 //
9 
10 #include <linux/input.h>
11 #include <linux/module.h>
12 #include <linux/of_device.h>
13 #include <linux/pm_runtime.h>
14 #include <sound/pcm_params.h>
15 #include <sound/soc.h>
16 
17 #include "../../codecs/da7219-aad.h"
18 #include "../../codecs/da7219.h"
19 #include "../../codecs/mt6358.h"
20 #include "../common/mtk-afe-platform-driver.h"
21 #include "mt8186-afe-common.h"
22 #include "mt8186-afe-clk.h"
23 #include "mt8186-afe-gpio.h"
24 #include "mt8186-mt6366-common.h"
25 
26 #define DA7219_CODEC_DAI "da7219-hifi"
27 #define DA7219_DEV_NAME "da7219.5-001a"
28 
29 struct mt8186_mt6366_da7219_max98357_priv {
30 	struct snd_soc_jack headset_jack, hdmi_jack;
31 };
32 
33 static struct snd_soc_codec_conf mt8186_mt6366_da7219_max98357_codec_conf[] = {
34 	{
35 		.dlc = COMP_CODEC_CONF("mt6358-sound"),
36 		.name_prefix = "Mt6366",
37 	},
38 	{
39 		.dlc = COMP_CODEC_CONF("bt-sco"),
40 		.name_prefix = "Mt8186 bt",
41 	},
42 	{
43 		.dlc = COMP_CODEC_CONF("hdmi-audio-codec"),
44 		.name_prefix = "Mt8186 hdmi",
45 	},
46 };
47 
48 static int mt8186_da7219_init(struct snd_soc_pcm_runtime *rtd)
49 {
50 	struct mt8186_mt6366_da7219_max98357_priv *priv =
51 		snd_soc_card_get_drvdata(rtd->card);
52 	struct snd_soc_jack *jack = &priv->headset_jack;
53 	struct snd_soc_component *cmpnt_codec =
54 		asoc_rtd_to_codec(rtd, 0)->component;
55 	int ret;
56 
57 	/* Enable Headset and 4 Buttons Jack detection */
58 	ret = snd_soc_card_jack_new(rtd->card, "Headset Jack",
59 				    SND_JACK_HEADSET | SND_JACK_BTN_0 |
60 				    SND_JACK_BTN_1 | SND_JACK_BTN_2 |
61 				    SND_JACK_BTN_3 | SND_JACK_LINEOUT,
62 				    jack);
63 	if (ret) {
64 		dev_err(rtd->dev, "Headset Jack creation failed: %d\n", ret);
65 		return ret;
66 	}
67 
68 	snd_jack_set_key(jack->jack, SND_JACK_BTN_0, KEY_PLAYPAUSE);
69 	snd_jack_set_key(jack->jack, SND_JACK_BTN_1, KEY_VOLUMEUP);
70 	snd_jack_set_key(jack->jack, SND_JACK_BTN_2, KEY_VOLUMEDOWN);
71 	snd_jack_set_key(jack->jack, SND_JACK_BTN_3, KEY_VOICECOMMAND);
72 
73 	da7219_aad_jack_det(cmpnt_codec, &priv->headset_jack);
74 
75 	return 0;
76 }
77 
78 static int mt8186_da7219_i2s_hw_params(struct snd_pcm_substream *substream,
79 				       struct snd_pcm_hw_params *params)
80 {
81 	struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
82 	struct snd_soc_dai *codec_dai;
83 	unsigned int rate = params_rate(params);
84 	unsigned int mclk_fs_ratio = 256;
85 	unsigned int mclk_fs = rate * mclk_fs_ratio;
86 	unsigned int freq;
87 	int ret, j;
88 
89 	ret = snd_soc_dai_set_sysclk(asoc_rtd_to_cpu(rtd, 0), 0,
90 				     mclk_fs, SND_SOC_CLOCK_OUT);
91 	if (ret < 0) {
92 		dev_err(rtd->dev, "failed to set cpu dai sysclk: %d\n", ret);
93 		return ret;
94 	}
95 
96 	for_each_rtd_codec_dais(rtd, j, codec_dai) {
97 		if (!strcmp(codec_dai->component->name, DA7219_DEV_NAME)) {
98 			ret = snd_soc_dai_set_sysclk(codec_dai,
99 						     DA7219_CLKSRC_MCLK,
100 						     mclk_fs,
101 						     SND_SOC_CLOCK_IN);
102 			if (ret < 0) {
103 				dev_err(rtd->dev, "failed to set sysclk: %d\n",
104 					ret);
105 				return ret;
106 			}
107 
108 			if ((rate % 8000) == 0)
109 				freq = DA7219_PLL_FREQ_OUT_98304;
110 			else
111 				freq = DA7219_PLL_FREQ_OUT_90316;
112 
113 			ret = snd_soc_dai_set_pll(codec_dai, 0,
114 						  DA7219_SYSCLK_PLL_SRM,
115 						  0, freq);
116 			if (ret) {
117 				dev_err(rtd->dev, "failed to start PLL: %d\n",
118 					ret);
119 				return ret;
120 			}
121 		}
122 	}
123 
124 	return 0;
125 }
126 
127 static int mt8186_da7219_i2s_hw_free(struct snd_pcm_substream *substream)
128 {
129 	struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
130 	struct snd_soc_dai *codec_dai;
131 	int ret = 0, j;
132 
133 	for_each_rtd_codec_dais(rtd, j, codec_dai) {
134 		if (!strcmp(codec_dai->component->name, DA7219_DEV_NAME)) {
135 			ret = snd_soc_dai_set_pll(codec_dai,
136 						  0, DA7219_SYSCLK_MCLK, 0, 0);
137 			if (ret < 0) {
138 				dev_err(rtd->dev, "failed to stop PLL: %d\n",
139 					ret);
140 				return ret;
141 			}
142 		}
143 	}
144 
145 	return 0;
146 }
147 
148 static const struct snd_soc_ops mt8186_da7219_i2s_ops = {
149 	.hw_params = mt8186_da7219_i2s_hw_params,
150 	.hw_free = mt8186_da7219_i2s_hw_free,
151 };
152 
153 static int mt8186_mt6366_da7219_max98357_hdmi_init(struct snd_soc_pcm_runtime *rtd)
154 {
155 	struct snd_soc_component *cmpnt_codec =
156 		asoc_rtd_to_codec(rtd, 0)->component;
157 	struct mt8186_mt6366_da7219_max98357_priv *priv =
158 		snd_soc_card_get_drvdata(rtd->card);
159 	int ret;
160 
161 	ret = snd_soc_card_jack_new(rtd->card, "HDMI Jack", SND_JACK_LINEOUT, &priv->hdmi_jack);
162 	if (ret) {
163 		dev_err(rtd->dev, "HDMI Jack creation failed: %d\n", ret);
164 		return ret;
165 	}
166 
167 	return snd_soc_component_set_jack(cmpnt_codec, &priv->hdmi_jack, NULL);
168 }
169 
170 static int mt8186_hw_params_fixup(struct snd_soc_pcm_runtime *rtd,
171 				  struct snd_pcm_hw_params *params,
172 				  snd_pcm_format_t fmt)
173 {
174 	struct snd_interval *channels = hw_param_interval(params,
175 		SNDRV_PCM_HW_PARAM_CHANNELS);
176 
177 	dev_dbg(rtd->dev, "%s(), fix format to %d\n", __func__, fmt);
178 
179 	/* fix BE i2s channel to 2 channel */
180 	channels->min = 2;
181 	channels->max = 2;
182 
183 	/* clean param mask first */
184 	snd_mask_reset_range(hw_param_mask(params, SNDRV_PCM_HW_PARAM_FORMAT),
185 			     0, (__force unsigned int)SNDRV_PCM_FORMAT_LAST);
186 
187 	params_set_format(params, fmt);
188 
189 	return 0;
190 }
191 
192 static int mt8186_i2s_hw_params_fixup(struct snd_soc_pcm_runtime *rtd,
193 				      struct snd_pcm_hw_params *params)
194 {
195 	return mt8186_hw_params_fixup(rtd, params, SNDRV_PCM_FORMAT_S32_LE);
196 }
197 
198 static int mt8186_anx7625_i2s_hw_params_fixup(struct snd_soc_pcm_runtime *rtd,
199 					      struct snd_pcm_hw_params *params)
200 {
201 	return mt8186_hw_params_fixup(rtd, params, SNDRV_PCM_FORMAT_S24_LE);
202 }
203 
204 static int mt8186_mt6366_da7219_max98357_playback_startup(struct snd_pcm_substream *substream)
205 {
206 	static const unsigned int rates[] = {
207 		48000
208 	};
209 	static const unsigned int channels[] = {
210 		2
211 	};
212 	static const struct snd_pcm_hw_constraint_list constraints_rates = {
213 		.count = ARRAY_SIZE(rates),
214 		.list  = rates,
215 		.mask = 0,
216 	};
217 	static const struct snd_pcm_hw_constraint_list constraints_channels = {
218 		.count = ARRAY_SIZE(channels),
219 		.list  = channels,
220 		.mask = 0,
221 	};
222 
223 	struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
224 	struct snd_pcm_runtime *runtime = substream->runtime;
225 	int ret;
226 
227 	ret = snd_pcm_hw_constraint_list(runtime, 0,
228 					 SNDRV_PCM_HW_PARAM_RATE,
229 					 &constraints_rates);
230 	if (ret < 0) {
231 		dev_err(rtd->dev, "hw_constraint_list rate failed\n");
232 		return ret;
233 	}
234 
235 	ret = snd_pcm_hw_constraint_list(runtime, 0,
236 					 SNDRV_PCM_HW_PARAM_CHANNELS,
237 					 &constraints_channels);
238 	if (ret < 0) {
239 		dev_err(rtd->dev, "hw_constraint_list channel failed\n");
240 		return ret;
241 	}
242 
243 	return 0;
244 }
245 
246 static const struct snd_soc_ops mt8186_mt6366_da7219_max98357_playback_ops = {
247 	.startup = mt8186_mt6366_da7219_max98357_playback_startup,
248 };
249 
250 static int mt8186_mt6366_da7219_max98357_capture_startup(struct snd_pcm_substream *substream)
251 {
252 	static const unsigned int rates[] = {
253 		48000
254 	};
255 	static const unsigned int channels[] = {
256 		1, 2
257 	};
258 	static const struct snd_pcm_hw_constraint_list constraints_rates = {
259 		.count = ARRAY_SIZE(rates),
260 		.list  = rates,
261 		.mask = 0,
262 	};
263 	static const struct snd_pcm_hw_constraint_list constraints_channels = {
264 		.count = ARRAY_SIZE(channels),
265 		.list  = channels,
266 		.mask = 0,
267 	};
268 
269 	struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
270 	struct snd_pcm_runtime *runtime = substream->runtime;
271 	int ret;
272 
273 	ret = snd_pcm_hw_constraint_list(runtime, 0,
274 					 SNDRV_PCM_HW_PARAM_RATE,
275 					 &constraints_rates);
276 	if (ret < 0) {
277 		dev_err(rtd->dev, "hw_constraint_list rate failed\n");
278 		return ret;
279 	}
280 
281 	ret = snd_pcm_hw_constraint_list(runtime, 0,
282 					 SNDRV_PCM_HW_PARAM_CHANNELS,
283 					 &constraints_channels);
284 	if (ret < 0) {
285 		dev_err(rtd->dev, "hw_constraint_list channel failed\n");
286 		return ret;
287 	}
288 
289 	return 0;
290 }
291 
292 static const struct snd_soc_ops mt8186_mt6366_da7219_max98357_capture_ops = {
293 	.startup = mt8186_mt6366_da7219_max98357_capture_startup,
294 };
295 
296 /* FE */
297 SND_SOC_DAILINK_DEFS(playback1,
298 		     DAILINK_COMP_ARRAY(COMP_CPU("DL1")),
299 		     DAILINK_COMP_ARRAY(COMP_DUMMY()),
300 		     DAILINK_COMP_ARRAY(COMP_EMPTY()));
301 
302 SND_SOC_DAILINK_DEFS(playback12,
303 		     DAILINK_COMP_ARRAY(COMP_CPU("DL12")),
304 		     DAILINK_COMP_ARRAY(COMP_DUMMY()),
305 		     DAILINK_COMP_ARRAY(COMP_EMPTY()));
306 
307 SND_SOC_DAILINK_DEFS(playback2,
308 		     DAILINK_COMP_ARRAY(COMP_CPU("DL2")),
309 		     DAILINK_COMP_ARRAY(COMP_DUMMY()),
310 		     DAILINK_COMP_ARRAY(COMP_EMPTY()));
311 
312 SND_SOC_DAILINK_DEFS(playback3,
313 		     DAILINK_COMP_ARRAY(COMP_CPU("DL3")),
314 		     DAILINK_COMP_ARRAY(COMP_DUMMY()),
315 		     DAILINK_COMP_ARRAY(COMP_EMPTY()));
316 
317 SND_SOC_DAILINK_DEFS(playback4,
318 		     DAILINK_COMP_ARRAY(COMP_CPU("DL4")),
319 		     DAILINK_COMP_ARRAY(COMP_DUMMY()),
320 		     DAILINK_COMP_ARRAY(COMP_EMPTY()));
321 
322 SND_SOC_DAILINK_DEFS(playback5,
323 		     DAILINK_COMP_ARRAY(COMP_CPU("DL5")),
324 		     DAILINK_COMP_ARRAY(COMP_DUMMY()),
325 		     DAILINK_COMP_ARRAY(COMP_EMPTY()));
326 
327 SND_SOC_DAILINK_DEFS(playback6,
328 		     DAILINK_COMP_ARRAY(COMP_CPU("DL6")),
329 		     DAILINK_COMP_ARRAY(COMP_DUMMY()),
330 		     DAILINK_COMP_ARRAY(COMP_EMPTY()));
331 
332 SND_SOC_DAILINK_DEFS(playback7,
333 		     DAILINK_COMP_ARRAY(COMP_CPU("DL7")),
334 		     DAILINK_COMP_ARRAY(COMP_DUMMY()),
335 		     DAILINK_COMP_ARRAY(COMP_EMPTY()));
336 
337 SND_SOC_DAILINK_DEFS(playback8,
338 		     DAILINK_COMP_ARRAY(COMP_CPU("DL8")),
339 		     DAILINK_COMP_ARRAY(COMP_DUMMY()),
340 		     DAILINK_COMP_ARRAY(COMP_EMPTY()));
341 
342 SND_SOC_DAILINK_DEFS(capture1,
343 		     DAILINK_COMP_ARRAY(COMP_CPU("UL1")),
344 		     DAILINK_COMP_ARRAY(COMP_DUMMY()),
345 		     DAILINK_COMP_ARRAY(COMP_EMPTY()));
346 
347 SND_SOC_DAILINK_DEFS(capture2,
348 		     DAILINK_COMP_ARRAY(COMP_CPU("UL2")),
349 		     DAILINK_COMP_ARRAY(COMP_DUMMY()),
350 		     DAILINK_COMP_ARRAY(COMP_EMPTY()));
351 
352 SND_SOC_DAILINK_DEFS(capture3,
353 		     DAILINK_COMP_ARRAY(COMP_CPU("UL3")),
354 		     DAILINK_COMP_ARRAY(COMP_DUMMY()),
355 		     DAILINK_COMP_ARRAY(COMP_EMPTY()));
356 
357 SND_SOC_DAILINK_DEFS(capture4,
358 		     DAILINK_COMP_ARRAY(COMP_CPU("UL4")),
359 		     DAILINK_COMP_ARRAY(COMP_DUMMY()),
360 		     DAILINK_COMP_ARRAY(COMP_EMPTY()));
361 
362 SND_SOC_DAILINK_DEFS(capture5,
363 		     DAILINK_COMP_ARRAY(COMP_CPU("UL5")),
364 		     DAILINK_COMP_ARRAY(COMP_DUMMY()),
365 		     DAILINK_COMP_ARRAY(COMP_EMPTY()));
366 
367 SND_SOC_DAILINK_DEFS(capture6,
368 		     DAILINK_COMP_ARRAY(COMP_CPU("UL6")),
369 		     DAILINK_COMP_ARRAY(COMP_DUMMY()),
370 		     DAILINK_COMP_ARRAY(COMP_EMPTY()));
371 
372 SND_SOC_DAILINK_DEFS(capture7,
373 		     DAILINK_COMP_ARRAY(COMP_CPU("UL7")),
374 		     DAILINK_COMP_ARRAY(COMP_DUMMY()),
375 		     DAILINK_COMP_ARRAY(COMP_EMPTY()));
376 
377 /* hostless */
378 SND_SOC_DAILINK_DEFS(hostless_lpbk,
379 		     DAILINK_COMP_ARRAY(COMP_CPU("Hostless LPBK DAI")),
380 		     DAILINK_COMP_ARRAY(COMP_DUMMY()),
381 		     DAILINK_COMP_ARRAY(COMP_EMPTY()));
382 SND_SOC_DAILINK_DEFS(hostless_fm,
383 		     DAILINK_COMP_ARRAY(COMP_CPU("Hostless FM DAI")),
384 		     DAILINK_COMP_ARRAY(COMP_DUMMY()),
385 		     DAILINK_COMP_ARRAY(COMP_EMPTY()));
386 SND_SOC_DAILINK_DEFS(hostless_src1,
387 		     DAILINK_COMP_ARRAY(COMP_CPU("Hostless_SRC_1_DAI")),
388 		     DAILINK_COMP_ARRAY(COMP_DUMMY()),
389 		     DAILINK_COMP_ARRAY(COMP_EMPTY()));
390 SND_SOC_DAILINK_DEFS(hostless_src_bargein,
391 		     DAILINK_COMP_ARRAY(COMP_CPU("Hostless_SRC_Bargein_DAI")),
392 		     DAILINK_COMP_ARRAY(COMP_DUMMY()),
393 		     DAILINK_COMP_ARRAY(COMP_EMPTY()));
394 
395 /* BE */
396 SND_SOC_DAILINK_DEFS(adda,
397 		     DAILINK_COMP_ARRAY(COMP_CPU("ADDA")),
398 		     DAILINK_COMP_ARRAY(COMP_CODEC("mt6358-sound",
399 						   "mt6358-snd-codec-aif1"),
400 					COMP_CODEC("dmic-codec",
401 						   "dmic-hifi")),
402 		     DAILINK_COMP_ARRAY(COMP_EMPTY()));
403 SND_SOC_DAILINK_DEFS(i2s0,
404 		     DAILINK_COMP_ARRAY(COMP_CPU("I2S0")),
405 		     DAILINK_COMP_ARRAY(COMP_EMPTY()),
406 		     DAILINK_COMP_ARRAY(COMP_EMPTY()));
407 SND_SOC_DAILINK_DEFS(i2s1,
408 		     DAILINK_COMP_ARRAY(COMP_CPU("I2S1")),
409 		     DAILINK_COMP_ARRAY(COMP_EMPTY()),
410 		     DAILINK_COMP_ARRAY(COMP_EMPTY()));
411 SND_SOC_DAILINK_DEFS(i2s2,
412 		     DAILINK_COMP_ARRAY(COMP_CPU("I2S2")),
413 		     DAILINK_COMP_ARRAY(COMP_DUMMY()),
414 		     DAILINK_COMP_ARRAY(COMP_EMPTY()));
415 SND_SOC_DAILINK_DEFS(i2s3,
416 		     DAILINK_COMP_ARRAY(COMP_CPU("I2S3")),
417 		     DAILINK_COMP_ARRAY(COMP_EMPTY()),
418 		     DAILINK_COMP_ARRAY(COMP_EMPTY()));
419 SND_SOC_DAILINK_DEFS(hw_gain1,
420 		     DAILINK_COMP_ARRAY(COMP_CPU("HW Gain 1")),
421 		     DAILINK_COMP_ARRAY(COMP_DUMMY()),
422 		     DAILINK_COMP_ARRAY(COMP_EMPTY()));
423 SND_SOC_DAILINK_DEFS(hw_gain2,
424 		     DAILINK_COMP_ARRAY(COMP_CPU("HW Gain 2")),
425 		     DAILINK_COMP_ARRAY(COMP_DUMMY()),
426 		     DAILINK_COMP_ARRAY(COMP_EMPTY()));
427 SND_SOC_DAILINK_DEFS(hw_src1,
428 		     DAILINK_COMP_ARRAY(COMP_CPU("HW_SRC_1")),
429 		     DAILINK_COMP_ARRAY(COMP_DUMMY()),
430 		     DAILINK_COMP_ARRAY(COMP_EMPTY()));
431 SND_SOC_DAILINK_DEFS(hw_src2,
432 		     DAILINK_COMP_ARRAY(COMP_CPU("HW_SRC_2")),
433 		     DAILINK_COMP_ARRAY(COMP_DUMMY()),
434 		     DAILINK_COMP_ARRAY(COMP_EMPTY()));
435 SND_SOC_DAILINK_DEFS(connsys_i2s,
436 		     DAILINK_COMP_ARRAY(COMP_CPU("CONNSYS_I2S")),
437 		     DAILINK_COMP_ARRAY(COMP_DUMMY()),
438 		     DAILINK_COMP_ARRAY(COMP_EMPTY()));
439 SND_SOC_DAILINK_DEFS(pcm1,
440 		     DAILINK_COMP_ARRAY(COMP_CPU("PCM 1")),
441 		     DAILINK_COMP_ARRAY(COMP_CODEC("bt-sco", "bt-sco-pcm-wb")),
442 		     DAILINK_COMP_ARRAY(COMP_EMPTY()));
443 SND_SOC_DAILINK_DEFS(tdm_in,
444 		     DAILINK_COMP_ARRAY(COMP_CPU("TDM IN")),
445 		     DAILINK_COMP_ARRAY(COMP_DUMMY()),
446 		     DAILINK_COMP_ARRAY(COMP_EMPTY()));
447 
448 /* hostless */
449 SND_SOC_DAILINK_DEFS(hostless_ul1,
450 		     DAILINK_COMP_ARRAY(COMP_CPU("Hostless_UL1 DAI")),
451 		     DAILINK_COMP_ARRAY(COMP_DUMMY()),
452 		     DAILINK_COMP_ARRAY(COMP_EMPTY()));
453 SND_SOC_DAILINK_DEFS(hostless_ul2,
454 		     DAILINK_COMP_ARRAY(COMP_CPU("Hostless_UL2 DAI")),
455 		     DAILINK_COMP_ARRAY(COMP_DUMMY()),
456 		     DAILINK_COMP_ARRAY(COMP_EMPTY()));
457 SND_SOC_DAILINK_DEFS(hostless_ul3,
458 		     DAILINK_COMP_ARRAY(COMP_CPU("Hostless_UL3 DAI")),
459 		     DAILINK_COMP_ARRAY(COMP_DUMMY()),
460 		     DAILINK_COMP_ARRAY(COMP_EMPTY()));
461 SND_SOC_DAILINK_DEFS(hostless_ul5,
462 		     DAILINK_COMP_ARRAY(COMP_CPU("Hostless_UL5 DAI")),
463 		     DAILINK_COMP_ARRAY(COMP_DUMMY()),
464 		     DAILINK_COMP_ARRAY(COMP_EMPTY()));
465 SND_SOC_DAILINK_DEFS(hostless_ul6,
466 		     DAILINK_COMP_ARRAY(COMP_CPU("Hostless_UL6 DAI")),
467 		     DAILINK_COMP_ARRAY(COMP_DUMMY()),
468 		     DAILINK_COMP_ARRAY(COMP_EMPTY()));
469 SND_SOC_DAILINK_DEFS(hostless_hw_gain_aaudio,
470 		     DAILINK_COMP_ARRAY(COMP_CPU("Hostless HW Gain AAudio DAI")),
471 		     DAILINK_COMP_ARRAY(COMP_DUMMY()),
472 		     DAILINK_COMP_ARRAY(COMP_EMPTY()));
473 SND_SOC_DAILINK_DEFS(hostless_src_aaudio,
474 		     DAILINK_COMP_ARRAY(COMP_CPU("Hostless SRC AAudio DAI")),
475 		     DAILINK_COMP_ARRAY(COMP_DUMMY()),
476 		     DAILINK_COMP_ARRAY(COMP_EMPTY()));
477 static struct snd_soc_dai_link mt8186_mt6366_da7219_max98357_dai_links[] = {
478 	/* Front End DAI links */
479 	{
480 		.name = "Playback_1",
481 		.stream_name = "Playback_1",
482 		.trigger = {SND_SOC_DPCM_TRIGGER_PRE,
483 			    SND_SOC_DPCM_TRIGGER_PRE},
484 		.dynamic = 1,
485 		.dpcm_playback = 1,
486 		.dpcm_merged_format = 1,
487 		.dpcm_merged_chan = 1,
488 		.dpcm_merged_rate = 1,
489 		.ops = &mt8186_mt6366_da7219_max98357_playback_ops,
490 		SND_SOC_DAILINK_REG(playback1),
491 	},
492 	{
493 		.name = "Playback_12",
494 		.stream_name = "Playback_12",
495 		.trigger = {SND_SOC_DPCM_TRIGGER_PRE,
496 			    SND_SOC_DPCM_TRIGGER_PRE},
497 		.dynamic = 1,
498 		.dpcm_playback = 1,
499 		SND_SOC_DAILINK_REG(playback12),
500 	},
501 	{
502 		.name = "Playback_2",
503 		.stream_name = "Playback_2",
504 		.trigger = {SND_SOC_DPCM_TRIGGER_PRE,
505 			    SND_SOC_DPCM_TRIGGER_PRE},
506 		.dynamic = 1,
507 		.dpcm_playback = 1,
508 		.dpcm_merged_format = 1,
509 		.dpcm_merged_chan = 1,
510 		.dpcm_merged_rate = 1,
511 		SND_SOC_DAILINK_REG(playback2),
512 	},
513 	{
514 		.name = "Playback_3",
515 		.stream_name = "Playback_3",
516 		.trigger = {SND_SOC_DPCM_TRIGGER_PRE,
517 			    SND_SOC_DPCM_TRIGGER_PRE},
518 		.dynamic = 1,
519 		.dpcm_playback = 1,
520 		.dpcm_merged_format = 1,
521 		.dpcm_merged_chan = 1,
522 		.dpcm_merged_rate = 1,
523 		.ops = &mt8186_mt6366_da7219_max98357_playback_ops,
524 		SND_SOC_DAILINK_REG(playback3),
525 	},
526 	{
527 		.name = "Playback_4",
528 		.stream_name = "Playback_4",
529 		.trigger = {SND_SOC_DPCM_TRIGGER_PRE,
530 			    SND_SOC_DPCM_TRIGGER_PRE},
531 		.dynamic = 1,
532 		.dpcm_playback = 1,
533 		SND_SOC_DAILINK_REG(playback4),
534 	},
535 	{
536 		.name = "Playback_5",
537 		.stream_name = "Playback_5",
538 		.trigger = {SND_SOC_DPCM_TRIGGER_PRE,
539 			    SND_SOC_DPCM_TRIGGER_PRE},
540 		.dynamic = 1,
541 		.dpcm_playback = 1,
542 		SND_SOC_DAILINK_REG(playback5),
543 	},
544 	{
545 		.name = "Playback_6",
546 		.stream_name = "Playback_6",
547 		.trigger = {SND_SOC_DPCM_TRIGGER_PRE,
548 			    SND_SOC_DPCM_TRIGGER_PRE},
549 		.dynamic = 1,
550 		.dpcm_playback = 1,
551 		SND_SOC_DAILINK_REG(playback6),
552 	},
553 	{
554 		.name = "Playback_7",
555 		.stream_name = "Playback_7",
556 		.trigger = {SND_SOC_DPCM_TRIGGER_PRE,
557 			    SND_SOC_DPCM_TRIGGER_PRE},
558 		.dynamic = 1,
559 		.dpcm_playback = 1,
560 		SND_SOC_DAILINK_REG(playback7),
561 	},
562 	{
563 		.name = "Playback_8",
564 		.stream_name = "Playback_8",
565 		.trigger = {SND_SOC_DPCM_TRIGGER_PRE,
566 			    SND_SOC_DPCM_TRIGGER_PRE},
567 		.dynamic = 1,
568 		.dpcm_playback = 1,
569 		SND_SOC_DAILINK_REG(playback8),
570 	},
571 	{
572 		.name = "Capture_1",
573 		.stream_name = "Capture_1",
574 		.trigger = {SND_SOC_DPCM_TRIGGER_PRE,
575 			    SND_SOC_DPCM_TRIGGER_PRE},
576 		.dynamic = 1,
577 		.dpcm_capture = 1,
578 		SND_SOC_DAILINK_REG(capture1),
579 	},
580 	{
581 		.name = "Capture_2",
582 		.stream_name = "Capture_2",
583 		.trigger = {SND_SOC_DPCM_TRIGGER_PRE,
584 			    SND_SOC_DPCM_TRIGGER_PRE},
585 		.dynamic = 1,
586 		.dpcm_capture = 1,
587 		.dpcm_merged_format = 1,
588 		.dpcm_merged_chan = 1,
589 		.dpcm_merged_rate = 1,
590 		.ops = &mt8186_mt6366_da7219_max98357_capture_ops,
591 		SND_SOC_DAILINK_REG(capture2),
592 	},
593 	{
594 		.name = "Capture_3",
595 		.stream_name = "Capture_3",
596 		.trigger = {SND_SOC_DPCM_TRIGGER_PRE,
597 			    SND_SOC_DPCM_TRIGGER_PRE},
598 		.dynamic = 1,
599 		.dpcm_capture = 1,
600 		SND_SOC_DAILINK_REG(capture3),
601 	},
602 	{
603 		.name = "Capture_4",
604 		.stream_name = "Capture_4",
605 		.trigger = {SND_SOC_DPCM_TRIGGER_PRE,
606 			    SND_SOC_DPCM_TRIGGER_PRE},
607 		.dynamic = 1,
608 		.dpcm_capture = 1,
609 		.dpcm_merged_format = 1,
610 		.dpcm_merged_chan = 1,
611 		.dpcm_merged_rate = 1,
612 		.ops = &mt8186_mt6366_da7219_max98357_capture_ops,
613 		SND_SOC_DAILINK_REG(capture4),
614 	},
615 	{
616 		.name = "Capture_5",
617 		.stream_name = "Capture_5",
618 		.trigger = {SND_SOC_DPCM_TRIGGER_PRE,
619 			    SND_SOC_DPCM_TRIGGER_PRE},
620 		.dynamic = 1,
621 		.dpcm_capture = 1,
622 		SND_SOC_DAILINK_REG(capture5),
623 	},
624 	{
625 		.name = "Capture_6",
626 		.stream_name = "Capture_6",
627 		.trigger = {SND_SOC_DPCM_TRIGGER_PRE,
628 			    SND_SOC_DPCM_TRIGGER_PRE},
629 		.dynamic = 1,
630 		.dpcm_capture = 1,
631 		.dpcm_merged_format = 1,
632 		.dpcm_merged_chan = 1,
633 		.dpcm_merged_rate = 1,
634 		SND_SOC_DAILINK_REG(capture6),
635 	},
636 	{
637 		.name = "Capture_7",
638 		.stream_name = "Capture_7",
639 		.trigger = {SND_SOC_DPCM_TRIGGER_PRE,
640 			    SND_SOC_DPCM_TRIGGER_PRE},
641 		.dynamic = 1,
642 		.dpcm_capture = 1,
643 		SND_SOC_DAILINK_REG(capture7),
644 	},
645 	{
646 		.name = "Hostless_LPBK",
647 		.stream_name = "Hostless_LPBK",
648 		.trigger = {SND_SOC_DPCM_TRIGGER_PRE,
649 			    SND_SOC_DPCM_TRIGGER_PRE},
650 		.dynamic = 1,
651 		.dpcm_playback = 1,
652 		.dpcm_capture = 1,
653 		.ignore_suspend = 1,
654 		SND_SOC_DAILINK_REG(hostless_lpbk),
655 	},
656 	{
657 		.name = "Hostless_FM",
658 		.stream_name = "Hostless_FM",
659 		.trigger = {SND_SOC_DPCM_TRIGGER_PRE,
660 			    SND_SOC_DPCM_TRIGGER_PRE},
661 		.dynamic = 1,
662 		.dpcm_playback = 1,
663 		.dpcm_capture = 1,
664 		.ignore_suspend = 1,
665 		SND_SOC_DAILINK_REG(hostless_fm),
666 	},
667 	{
668 		.name = "Hostless_SRC_1",
669 		.stream_name = "Hostless_SRC_1",
670 		.trigger = {SND_SOC_DPCM_TRIGGER_PRE,
671 			    SND_SOC_DPCM_TRIGGER_PRE},
672 		.dynamic = 1,
673 		.dpcm_playback = 1,
674 		.dpcm_capture = 1,
675 		.ignore_suspend = 1,
676 		SND_SOC_DAILINK_REG(hostless_src1),
677 	},
678 	{
679 		.name = "Hostless_SRC_Bargein",
680 		.stream_name = "Hostless_SRC_Bargein",
681 		.trigger = {SND_SOC_DPCM_TRIGGER_PRE,
682 			    SND_SOC_DPCM_TRIGGER_PRE},
683 		.dynamic = 1,
684 		.dpcm_playback = 1,
685 		.dpcm_capture = 1,
686 		.ignore_suspend = 1,
687 		SND_SOC_DAILINK_REG(hostless_src_bargein),
688 	},
689 	{
690 		.name = "Hostless_HW_Gain_AAudio",
691 		.stream_name = "Hostless_HW_Gain_AAudio",
692 		.trigger = {SND_SOC_DPCM_TRIGGER_PRE,
693 			    SND_SOC_DPCM_TRIGGER_PRE},
694 		.dynamic = 1,
695 		.dpcm_capture = 1,
696 		.ignore_suspend = 1,
697 		SND_SOC_DAILINK_REG(hostless_hw_gain_aaudio),
698 	},
699 	{
700 		.name = "Hostless_SRC_AAudio",
701 		.stream_name = "Hostless_SRC_AAudio",
702 		.trigger = {SND_SOC_DPCM_TRIGGER_PRE,
703 			    SND_SOC_DPCM_TRIGGER_PRE},
704 		.dynamic = 1,
705 		.dpcm_playback = 1,
706 		.dpcm_capture = 1,
707 		.ignore_suspend = 1,
708 		SND_SOC_DAILINK_REG(hostless_src_aaudio),
709 	},
710 	/* Back End DAI links */
711 	{
712 		.name = "Primary Codec",
713 		.no_pcm = 1,
714 		.dpcm_playback = 1,
715 		.dpcm_capture = 1,
716 		.ignore_suspend = 1,
717 		.init = mt8186_mt6366_init,
718 		SND_SOC_DAILINK_REG(adda),
719 	},
720 	{
721 		.name = "I2S3",
722 		.no_pcm = 1,
723 		.dai_fmt = SND_SOC_DAIFMT_I2S |
724 			   SND_SOC_DAIFMT_IB_IF |
725 			   SND_SOC_DAIFMT_CBM_CFM,
726 		.dpcm_playback = 1,
727 		.ignore_suspend = 1,
728 		.init = mt8186_mt6366_da7219_max98357_hdmi_init,
729 		.be_hw_params_fixup = mt8186_anx7625_i2s_hw_params_fixup,
730 		SND_SOC_DAILINK_REG(i2s3),
731 	},
732 	{
733 		.name = "I2S0",
734 		.no_pcm = 1,
735 		.dpcm_capture = 1,
736 		.ignore_suspend = 1,
737 		.be_hw_params_fixup = mt8186_i2s_hw_params_fixup,
738 		.ops = &mt8186_da7219_i2s_ops,
739 		SND_SOC_DAILINK_REG(i2s0),
740 	},
741 	{
742 		.name = "I2S1",
743 		.no_pcm = 1,
744 		.dpcm_playback = 1,
745 		.ignore_suspend = 1,
746 		.be_hw_params_fixup = mt8186_i2s_hw_params_fixup,
747 		.init = mt8186_da7219_init,
748 		.ops = &mt8186_da7219_i2s_ops,
749 		SND_SOC_DAILINK_REG(i2s1),
750 	},
751 	{
752 		.name = "I2S2",
753 		.no_pcm = 1,
754 		.dpcm_capture = 1,
755 		.ignore_suspend = 1,
756 		.be_hw_params_fixup = mt8186_i2s_hw_params_fixup,
757 		SND_SOC_DAILINK_REG(i2s2),
758 	},
759 	{
760 		.name = "HW Gain 1",
761 		.no_pcm = 1,
762 		.dpcm_playback = 1,
763 		.dpcm_capture = 1,
764 		.ignore_suspend = 1,
765 		SND_SOC_DAILINK_REG(hw_gain1),
766 	},
767 	{
768 		.name = "HW Gain 2",
769 		.no_pcm = 1,
770 		.dpcm_playback = 1,
771 		.dpcm_capture = 1,
772 		.ignore_suspend = 1,
773 		SND_SOC_DAILINK_REG(hw_gain2),
774 	},
775 	{
776 		.name = "HW_SRC_1",
777 		.no_pcm = 1,
778 		.dpcm_playback = 1,
779 		.dpcm_capture = 1,
780 		.ignore_suspend = 1,
781 		SND_SOC_DAILINK_REG(hw_src1),
782 	},
783 	{
784 		.name = "HW_SRC_2",
785 		.no_pcm = 1,
786 		.dpcm_playback = 1,
787 		.dpcm_capture = 1,
788 		.ignore_suspend = 1,
789 		SND_SOC_DAILINK_REG(hw_src2),
790 	},
791 	{
792 		.name = "CONNSYS_I2S",
793 		.no_pcm = 1,
794 		.dpcm_capture = 1,
795 		.ignore_suspend = 1,
796 		SND_SOC_DAILINK_REG(connsys_i2s),
797 	},
798 	{
799 		.name = "PCM 1",
800 		.dai_fmt = SND_SOC_DAIFMT_I2S |
801 			   SND_SOC_DAIFMT_NB_IF,
802 		.no_pcm = 1,
803 		.dpcm_playback = 1,
804 		.dpcm_capture = 1,
805 		.ignore_suspend = 1,
806 		SND_SOC_DAILINK_REG(pcm1),
807 	},
808 	{
809 		.name = "TDM IN",
810 		.no_pcm = 1,
811 		.dpcm_capture = 1,
812 		.ignore_suspend = 1,
813 		SND_SOC_DAILINK_REG(tdm_in),
814 	},
815 	/* dummy BE for ul memif to record from dl memif */
816 	{
817 		.name = "Hostless_UL1",
818 		.no_pcm = 1,
819 		.dpcm_capture = 1,
820 		.ignore_suspend = 1,
821 		SND_SOC_DAILINK_REG(hostless_ul1),
822 	},
823 	{
824 		.name = "Hostless_UL2",
825 		.no_pcm = 1,
826 		.dpcm_capture = 1,
827 		.ignore_suspend = 1,
828 		SND_SOC_DAILINK_REG(hostless_ul2),
829 	},
830 	{
831 		.name = "Hostless_UL3",
832 		.no_pcm = 1,
833 		.dpcm_capture = 1,
834 		.ignore_suspend = 1,
835 		SND_SOC_DAILINK_REG(hostless_ul3),
836 	},
837 	{
838 		.name = "Hostless_UL5",
839 		.no_pcm = 1,
840 		.dpcm_capture = 1,
841 		.ignore_suspend = 1,
842 		SND_SOC_DAILINK_REG(hostless_ul5),
843 	},
844 	{
845 		.name = "Hostless_UL6",
846 		.no_pcm = 1,
847 		.dpcm_capture = 1,
848 		.ignore_suspend = 1,
849 		SND_SOC_DAILINK_REG(hostless_ul6),
850 	},
851 };
852 
853 static const struct snd_soc_dapm_widget
854 mt8186_mt6366_da7219_max98357_widgets[] = {
855 	SND_SOC_DAPM_SPK("Speakers", NULL),
856 	SND_SOC_DAPM_OUTPUT("HDMI1"),
857 };
858 
859 static const struct snd_soc_dapm_route
860 mt8186_mt6366_da7219_max98357_routes[] = {
861 	/* SPK */
862 	{ "Speakers", NULL, "Speaker"},
863 	/* HDMI */
864 	{ "HDMI1", NULL, "TX"},
865 };
866 
867 static const struct snd_kcontrol_new
868 mt8186_mt6366_da7219_max98357_controls[] = {
869 	SOC_DAPM_PIN_SWITCH("Speakers"),
870 	SOC_DAPM_PIN_SWITCH("HDMI1"),
871 };
872 
873 static struct snd_soc_card mt8186_mt6366_da7219_max98357_soc_card = {
874 	.name = "mt8186_mt6366_da7219_max98357",
875 	.owner = THIS_MODULE,
876 	.dai_link = mt8186_mt6366_da7219_max98357_dai_links,
877 	.num_links = ARRAY_SIZE(mt8186_mt6366_da7219_max98357_dai_links),
878 	.controls = mt8186_mt6366_da7219_max98357_controls,
879 	.num_controls = ARRAY_SIZE(mt8186_mt6366_da7219_max98357_controls),
880 	.dapm_widgets = mt8186_mt6366_da7219_max98357_widgets,
881 	.num_dapm_widgets = ARRAY_SIZE(mt8186_mt6366_da7219_max98357_widgets),
882 	.dapm_routes = mt8186_mt6366_da7219_max98357_routes,
883 	.num_dapm_routes = ARRAY_SIZE(mt8186_mt6366_da7219_max98357_routes),
884 	.codec_conf = mt8186_mt6366_da7219_max98357_codec_conf,
885 	.num_configs = ARRAY_SIZE(mt8186_mt6366_da7219_max98357_codec_conf),
886 };
887 
888 static int mt8186_mt6366_da7219_max98357_dev_probe(struct platform_device *pdev)
889 {
890 	struct snd_soc_card *card;
891 	struct snd_soc_dai_link *dai_link;
892 	struct mt8186_mt6366_da7219_max98357_priv *priv;
893 	struct device_node *platform_node, *headset_codec, *playback_codec;
894 	int ret, i;
895 
896 	card = (struct snd_soc_card *)device_get_match_data(&pdev->dev);
897 	if (!card)
898 		return -EINVAL;
899 	card->dev = &pdev->dev;
900 
901 	platform_node = of_parse_phandle(pdev->dev.of_node, "mediatek,platform", 0);
902 	if (!platform_node) {
903 		ret = -EINVAL;
904 		dev_err_probe(&pdev->dev, ret, "Property 'platform' missing or invalid\n");
905 		return ret;
906 	}
907 
908 	playback_codec = of_get_child_by_name(pdev->dev.of_node, "playback-codecs");
909 	if (!playback_codec) {
910 		ret = -EINVAL;
911 		dev_err_probe(&pdev->dev, ret, "Property 'speaker-codecs' missing or invalid\n");
912 		goto err_playback_codec;
913 	}
914 
915 	headset_codec = of_get_child_by_name(pdev->dev.of_node, "headset-codec");
916 	if (!headset_codec) {
917 		ret = -EINVAL;
918 		dev_err_probe(&pdev->dev, ret, "Property 'headset-codec' missing or invalid\n");
919 		goto err_headset_codec;
920 	}
921 
922 	for_each_card_prelinks(card, i, dai_link) {
923 		ret = mt8186_mt6366_card_set_be_link(card, dai_link, playback_codec, "I2S3");
924 		if (ret) {
925 			dev_err_probe(&pdev->dev, ret, "%s set speaker_codec fail\n",
926 				      dai_link->name);
927 			goto err_probe;
928 		}
929 
930 		ret = mt8186_mt6366_card_set_be_link(card, dai_link, headset_codec, "I2S0");
931 		if (ret) {
932 			dev_err_probe(&pdev->dev, ret, "%s set headset_codec fail\n",
933 				      dai_link->name);
934 			goto err_probe;
935 		}
936 
937 		ret = mt8186_mt6366_card_set_be_link(card, dai_link, headset_codec, "I2S1");
938 		if (ret) {
939 			dev_err_probe(&pdev->dev, ret, "%s set headset_codec fail\n",
940 				      dai_link->name);
941 			goto err_probe;
942 		}
943 
944 		if (!dai_link->platforms->name)
945 			dai_link->platforms->of_node = platform_node;
946 	}
947 
948 	priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL);
949 	if (!priv) {
950 		ret = -ENOMEM;
951 		goto err_probe;
952 	}
953 
954 	snd_soc_card_set_drvdata(card, priv);
955 
956 	ret = mt8186_afe_gpio_init(&pdev->dev);
957 	if (ret) {
958 		dev_err_probe(&pdev->dev, ret, "%s init gpio error\n", __func__);
959 		goto err_probe;
960 	}
961 
962 	ret = devm_snd_soc_register_card(&pdev->dev, card);
963 	if (ret)
964 		dev_err_probe(&pdev->dev, ret, "%s snd_soc_register_card fail\n", __func__);
965 
966 err_probe:
967 	of_node_put(headset_codec);
968 err_headset_codec:
969 	of_node_put(playback_codec);
970 err_playback_codec:
971 	of_node_put(platform_node);
972 
973 	return ret;
974 }
975 
976 #if IS_ENABLED(CONFIG_OF)
977 static const struct of_device_id mt8186_mt6366_da7219_max98357_dt_match[] = {
978 	{	.compatible = "mediatek,mt8186-mt6366-da7219-max98357-sound",
979 		.data = &mt8186_mt6366_da7219_max98357_soc_card,
980 	},
981 	{}
982 };
983 #endif
984 
985 static struct platform_driver mt8186_mt6366_da7219_max98357_driver = {
986 	.driver = {
987 		.name = "mt8186_mt6366_da7219_max98357",
988 #if IS_ENABLED(CONFIG_OF)
989 		.of_match_table = mt8186_mt6366_da7219_max98357_dt_match,
990 #endif
991 		.pm = &snd_soc_pm_ops,
992 	},
993 	.probe = mt8186_mt6366_da7219_max98357_dev_probe,
994 };
995 
996 module_platform_driver(mt8186_mt6366_da7219_max98357_driver);
997 
998 /* Module information */
999 MODULE_DESCRIPTION("MT8186-MT6366-DA7219-MAX98357 ALSA SoC machine driver");
1000 MODULE_AUTHOR("Jiaxin Yu <jiaxin.yu@mediatek.com>");
1001 MODULE_LICENSE("GPL v2");
1002 MODULE_ALIAS("mt8186_mt6366_da7219_max98357 soc card");
1003