Commit | Line | Data |
---|---|---|
18b13ff2 JY |
1 | // SPDX-License-Identifier: GPL-2.0 |
2 | // | |
3 | // mt8192-mt6359-rt1015-rt5682.c -- | |
4 | // MT8192-MT6359-RT1015-RT6358 ALSA SoC machine driver | |
5 | // | |
6 | // Copyright (c) 2020 MediaTek Inc. | |
7 | // Author: Jiaxin Yu <jiaxin.yu@mediatek.com> | |
8 | // | |
9 | ||
10 | #include <linux/input.h> | |
11 | #include <linux/module.h> | |
2b53d2e1 | 12 | #include <linux/of_device.h> |
18b13ff2 JY |
13 | #include <linux/pm_runtime.h> |
14 | #include <sound/jack.h> | |
15 | #include <sound/pcm_params.h> | |
16 | #include <sound/rt5682.h> | |
17 | #include <sound/soc.h> | |
18 | ||
19 | #include "../../codecs/mt6359.h" | |
20 | #include "../../codecs/rt1015.h" | |
21 | #include "../../codecs/rt5682.h" | |
22 | #include "../common/mtk-afe-platform-driver.h" | |
23 | #include "mt8192-afe-common.h" | |
24 | #include "mt8192-afe-clk.h" | |
25 | #include "mt8192-afe-gpio.h" | |
26 | ||
4674284a NP |
27 | #define DRIVER_NAME "mt8192_mt6359" |
28 | ||
18b13ff2 JY |
29 | #define RT1015_CODEC_DAI "rt1015-aif" |
30 | #define RT1015_DEV0_NAME "rt1015.1-0028" | |
31 | #define RT1015_DEV1_NAME "rt1015.1-0029" | |
32 | ||
6181ab31 JY |
33 | #define RT1015_RT5682_CARD_NAME "mt8192_mt6359_rt1015_rt5682" |
34 | #define RT1015P_RT5682_CARD_NAME "mt8192_mt6359_rt1015p_rt5682" | |
35 | #define RT1015P_RT5682S_CARD_NAME "mt8192_mt6359_rt1015p_rt5682s" | |
36 | ||
37 | #define RT1015_RT5682_OF_NAME "mediatek,mt8192_mt6359_rt1015_rt5682" | |
38 | #define RT1015P_RT5682_OF_NAME "mediatek,mt8192_mt6359_rt1015p_rt5682" | |
39 | #define RT1015P_RT5682S_OF_NAME "mediatek,mt8192_mt6359_rt1015p_rt5682s" | |
40 | ||
4e37528a TBS |
41 | struct mt8192_mt6359_priv { |
42 | struct snd_soc_jack headset_jack; | |
0d80c48c | 43 | struct snd_soc_jack hdmi_jack; |
4e37528a | 44 | }; |
18b13ff2 | 45 | |
194ff8db NP |
46 | /* Headset jack detection DAPM pins */ |
47 | static struct snd_soc_jack_pin mt8192_jack_pins[] = { | |
48 | { | |
49 | .pin = "Headphone Jack", | |
50 | .mask = SND_JACK_HEADPHONE, | |
51 | }, | |
52 | { | |
53 | .pin = "Headset Mic", | |
54 | .mask = SND_JACK_MICROPHONE, | |
55 | }, | |
56 | }; | |
57 | ||
18b13ff2 JY |
58 | static int mt8192_rt1015_i2s_hw_params(struct snd_pcm_substream *substream, |
59 | struct snd_pcm_hw_params *params) | |
60 | { | |
8e59cf94 | 61 | struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); |
18b13ff2 JY |
62 | struct snd_soc_card *card = rtd->card; |
63 | struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0); | |
64 | struct snd_soc_dai *codec_dai; | |
65 | unsigned int rate = params_rate(params); | |
66 | unsigned int mclk_fs_ratio = 128; | |
67 | unsigned int mclk_fs = rate * mclk_fs_ratio; | |
68 | int ret, i; | |
69 | ||
70 | for_each_rtd_codec_dais(rtd, i, codec_dai) { | |
18b13ff2 JY |
71 | ret = snd_soc_dai_set_pll(codec_dai, 0, |
72 | RT1015_PLL_S_BCLK, | |
73 | params_rate(params) * 64, | |
74 | params_rate(params) * 256); | |
75 | if (ret) { | |
76 | dev_err(card->dev, "failed to set pll\n"); | |
77 | return ret; | |
78 | } | |
79 | ||
80 | ret = snd_soc_dai_set_sysclk(codec_dai, | |
81 | RT1015_SCLK_S_PLL, | |
82 | params_rate(params) * 256, | |
83 | SND_SOC_CLOCK_IN); | |
84 | if (ret) { | |
85 | dev_err(card->dev, "failed to set sysclk\n"); | |
86 | return ret; | |
87 | } | |
88 | } | |
89 | ||
90 | return snd_soc_dai_set_sysclk(cpu_dai, 0, mclk_fs, SND_SOC_CLOCK_OUT); | |
91 | } | |
92 | ||
6181ab31 JY |
93 | static int mt8192_rt5682x_i2s_hw_params(struct snd_pcm_substream *substream, |
94 | struct snd_pcm_hw_params *params) | |
18b13ff2 | 95 | { |
8e59cf94 | 96 | struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); |
18b13ff2 JY |
97 | struct snd_soc_card *card = rtd->card; |
98 | struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0); | |
99 | struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0); | |
100 | unsigned int rate = params_rate(params); | |
101 | unsigned int mclk_fs_ratio = 128; | |
102 | unsigned int mclk_fs = rate * mclk_fs_ratio; | |
103 | int bitwidth; | |
104 | int ret; | |
105 | ||
106 | bitwidth = snd_pcm_format_width(params_format(params)); | |
107 | if (bitwidth < 0) { | |
108 | dev_err(card->dev, "invalid bit width: %d\n", bitwidth); | |
109 | return bitwidth; | |
110 | } | |
111 | ||
112 | ret = snd_soc_dai_set_tdm_slot(codec_dai, 0x00, 0x0, 0x2, bitwidth); | |
113 | if (ret) { | |
114 | dev_err(card->dev, "failed to set tdm slot\n"); | |
115 | return ret; | |
116 | } | |
117 | ||
118 | ret = snd_soc_dai_set_pll(codec_dai, RT5682_PLL1, | |
119 | RT5682_PLL1_S_BCLK1, | |
120 | params_rate(params) * 64, | |
121 | params_rate(params) * 512); | |
122 | if (ret) { | |
123 | dev_err(card->dev, "failed to set pll\n"); | |
124 | return ret; | |
125 | } | |
126 | ||
127 | ret = snd_soc_dai_set_sysclk(codec_dai, | |
128 | RT5682_SCLK_S_PLL1, | |
129 | params_rate(params) * 512, | |
130 | SND_SOC_CLOCK_IN); | |
131 | if (ret) { | |
132 | dev_err(card->dev, "failed to set sysclk\n"); | |
133 | return ret; | |
134 | } | |
135 | ||
136 | return snd_soc_dai_set_sysclk(cpu_dai, 0, mclk_fs, SND_SOC_CLOCK_OUT); | |
137 | } | |
138 | ||
139 | static const struct snd_soc_ops mt8192_rt1015_i2s_ops = { | |
140 | .hw_params = mt8192_rt1015_i2s_hw_params, | |
141 | }; | |
142 | ||
6181ab31 JY |
143 | static const struct snd_soc_ops mt8192_rt5682x_i2s_ops = { |
144 | .hw_params = mt8192_rt5682x_i2s_hw_params, | |
18b13ff2 JY |
145 | }; |
146 | ||
147 | static int mt8192_mt6359_mtkaif_calibration(struct snd_soc_pcm_runtime *rtd) | |
148 | { | |
149 | struct snd_soc_component *cmpnt_afe = | |
150 | snd_soc_rtdcom_lookup(rtd, AFE_PCM_NAME); | |
151 | struct snd_soc_component *cmpnt_codec = | |
152 | asoc_rtd_to_codec(rtd, 0)->component; | |
153 | struct mtk_base_afe *afe = snd_soc_component_get_drvdata(cmpnt_afe); | |
154 | struct mt8192_afe_private *afe_priv = afe->platform_priv; | |
155 | int phase; | |
156 | unsigned int monitor; | |
157 | int test_done_1, test_done_2, test_done_3; | |
158 | int cycle_1, cycle_2, cycle_3; | |
159 | int prev_cycle_1, prev_cycle_2, prev_cycle_3; | |
160 | int chosen_phase_1, chosen_phase_2, chosen_phase_3; | |
161 | int counter; | |
162 | int mtkaif_calib_ok; | |
163 | ||
18b13ff2 JY |
164 | pm_runtime_get_sync(afe->dev); |
165 | mt8192_afe_gpio_request(afe->dev, true, MT8192_DAI_ADDA, 1); | |
166 | mt8192_afe_gpio_request(afe->dev, true, MT8192_DAI_ADDA, 0); | |
167 | mt8192_afe_gpio_request(afe->dev, true, MT8192_DAI_ADDA_CH34, 1); | |
168 | mt8192_afe_gpio_request(afe->dev, true, MT8192_DAI_ADDA_CH34, 0); | |
169 | ||
170 | mt6359_mtkaif_calibration_enable(cmpnt_codec); | |
171 | ||
172 | /* set clock protocol 2 */ | |
173 | regmap_update_bits(afe->regmap, AFE_AUD_PAD_TOP, 0xff, 0x38); | |
174 | regmap_update_bits(afe->regmap, AFE_AUD_PAD_TOP, 0xff, 0x39); | |
175 | ||
176 | /* set test type to synchronizer pulse */ | |
177 | regmap_update_bits(afe_priv->topckgen, | |
178 | CKSYS_AUD_TOP_CFG, 0xffff, 0x4); | |
179 | ||
180 | mtkaif_calib_ok = true; | |
181 | afe_priv->mtkaif_calibration_num_phase = 42; /* mt6359: 0 ~ 42 */ | |
182 | afe_priv->mtkaif_chosen_phase[0] = -1; | |
183 | afe_priv->mtkaif_chosen_phase[1] = -1; | |
184 | afe_priv->mtkaif_chosen_phase[2] = -1; | |
185 | ||
186 | for (phase = 0; | |
187 | phase <= afe_priv->mtkaif_calibration_num_phase && | |
188 | mtkaif_calib_ok; | |
189 | phase++) { | |
190 | mt6359_set_mtkaif_calibration_phase(cmpnt_codec, | |
191 | phase, phase, phase); | |
192 | ||
193 | regmap_update_bits(afe_priv->topckgen, | |
194 | CKSYS_AUD_TOP_CFG, 0x1, 0x1); | |
195 | ||
196 | test_done_1 = 0; | |
197 | test_done_2 = 0; | |
198 | test_done_3 = 0; | |
199 | cycle_1 = -1; | |
200 | cycle_2 = -1; | |
201 | cycle_3 = -1; | |
202 | counter = 0; | |
203 | while (test_done_1 == 0 || | |
204 | test_done_2 == 0 || | |
205 | test_done_3 == 0) { | |
206 | regmap_read(afe_priv->topckgen, | |
207 | CKSYS_AUD_TOP_MON, &monitor); | |
208 | ||
209 | test_done_1 = (monitor >> 28) & 0x1; | |
210 | test_done_2 = (monitor >> 29) & 0x1; | |
211 | test_done_3 = (monitor >> 30) & 0x1; | |
212 | if (test_done_1 == 1) | |
213 | cycle_1 = monitor & 0xf; | |
214 | ||
215 | if (test_done_2 == 1) | |
216 | cycle_2 = (monitor >> 4) & 0xf; | |
217 | ||
218 | if (test_done_3 == 1) | |
219 | cycle_3 = (monitor >> 8) & 0xf; | |
220 | ||
221 | /* handle if never test done */ | |
222 | if (++counter > 10000) { | |
223 | dev_err(afe->dev, "%s(), test fail, cycle_1 %d, cycle_2 %d, cycle_3 %d, monitor 0x%x\n", | |
224 | __func__, | |
225 | cycle_1, cycle_2, cycle_3, monitor); | |
226 | mtkaif_calib_ok = false; | |
227 | break; | |
228 | } | |
229 | } | |
230 | ||
231 | if (phase == 0) { | |
232 | prev_cycle_1 = cycle_1; | |
233 | prev_cycle_2 = cycle_2; | |
234 | prev_cycle_3 = cycle_3; | |
235 | } | |
236 | ||
237 | if (cycle_1 != prev_cycle_1 && | |
238 | afe_priv->mtkaif_chosen_phase[0] < 0) { | |
239 | afe_priv->mtkaif_chosen_phase[0] = phase - 1; | |
240 | afe_priv->mtkaif_phase_cycle[0] = prev_cycle_1; | |
241 | } | |
242 | ||
243 | if (cycle_2 != prev_cycle_2 && | |
244 | afe_priv->mtkaif_chosen_phase[1] < 0) { | |
245 | afe_priv->mtkaif_chosen_phase[1] = phase - 1; | |
246 | afe_priv->mtkaif_phase_cycle[1] = prev_cycle_2; | |
247 | } | |
248 | ||
249 | if (cycle_3 != prev_cycle_3 && | |
250 | afe_priv->mtkaif_chosen_phase[2] < 0) { | |
251 | afe_priv->mtkaif_chosen_phase[2] = phase - 1; | |
252 | afe_priv->mtkaif_phase_cycle[2] = prev_cycle_3; | |
253 | } | |
254 | ||
255 | regmap_update_bits(afe_priv->topckgen, | |
256 | CKSYS_AUD_TOP_CFG, 0x1, 0x0); | |
257 | ||
258 | if (afe_priv->mtkaif_chosen_phase[0] >= 0 && | |
259 | afe_priv->mtkaif_chosen_phase[1] >= 0 && | |
260 | afe_priv->mtkaif_chosen_phase[2] >= 0) | |
261 | break; | |
262 | } | |
263 | ||
264 | if (afe_priv->mtkaif_chosen_phase[0] < 0) | |
265 | chosen_phase_1 = 0; | |
266 | else | |
267 | chosen_phase_1 = afe_priv->mtkaif_chosen_phase[0]; | |
268 | ||
269 | if (afe_priv->mtkaif_chosen_phase[1] < 0) | |
270 | chosen_phase_2 = 0; | |
271 | else | |
272 | chosen_phase_2 = afe_priv->mtkaif_chosen_phase[1]; | |
273 | ||
274 | if (afe_priv->mtkaif_chosen_phase[2] < 0) | |
275 | chosen_phase_3 = 0; | |
276 | else | |
277 | chosen_phase_3 = afe_priv->mtkaif_chosen_phase[2]; | |
278 | ||
279 | mt6359_set_mtkaif_calibration_phase(cmpnt_codec, | |
280 | chosen_phase_1, | |
281 | chosen_phase_2, | |
282 | chosen_phase_3); | |
283 | ||
284 | /* disable rx fifo */ | |
285 | regmap_update_bits(afe->regmap, AFE_AUD_PAD_TOP, 0xff, 0x38); | |
286 | ||
287 | mt6359_mtkaif_calibration_disable(cmpnt_codec); | |
288 | ||
289 | mt8192_afe_gpio_request(afe->dev, false, MT8192_DAI_ADDA, 1); | |
290 | mt8192_afe_gpio_request(afe->dev, false, MT8192_DAI_ADDA, 0); | |
291 | mt8192_afe_gpio_request(afe->dev, false, MT8192_DAI_ADDA_CH34, 1); | |
292 | mt8192_afe_gpio_request(afe->dev, false, MT8192_DAI_ADDA_CH34, 0); | |
293 | pm_runtime_put(afe->dev); | |
294 | ||
5f2a53c0 NP |
295 | dev_dbg(afe->dev, "%s(), mtkaif_chosen_phase[0/1/2]:%d/%d/%d\n", |
296 | __func__, | |
297 | afe_priv->mtkaif_chosen_phase[0], | |
298 | afe_priv->mtkaif_chosen_phase[1], | |
299 | afe_priv->mtkaif_chosen_phase[2]); | |
18b13ff2 JY |
300 | |
301 | return 0; | |
302 | } | |
303 | ||
304 | static int mt8192_mt6359_init(struct snd_soc_pcm_runtime *rtd) | |
305 | { | |
306 | struct snd_soc_component *cmpnt_afe = | |
307 | snd_soc_rtdcom_lookup(rtd, AFE_PCM_NAME); | |
308 | struct snd_soc_component *cmpnt_codec = | |
309 | asoc_rtd_to_codec(rtd, 0)->component; | |
310 | struct mtk_base_afe *afe = snd_soc_component_get_drvdata(cmpnt_afe); | |
311 | struct mt8192_afe_private *afe_priv = afe->platform_priv; | |
312 | ||
313 | /* set mtkaif protocol */ | |
314 | mt6359_set_mtkaif_protocol(cmpnt_codec, | |
315 | MT6359_MTKAIF_PROTOCOL_2_CLK_P2); | |
316 | afe_priv->mtkaif_protocol = MTKAIF_PROTOCOL_2_CLK_P2; | |
317 | ||
318 | /* mtkaif calibration */ | |
319 | mt8192_mt6359_mtkaif_calibration(rtd); | |
320 | ||
321 | return 0; | |
322 | } | |
323 | ||
324 | static int mt8192_rt5682_init(struct snd_soc_pcm_runtime *rtd) | |
325 | { | |
3ffb9fa3 NP |
326 | struct snd_soc_component *cmpnt_afe = |
327 | snd_soc_rtdcom_lookup(rtd, AFE_PCM_NAME); | |
328 | struct mtk_base_afe *afe = snd_soc_component_get_drvdata(cmpnt_afe); | |
18b13ff2 JY |
329 | struct snd_soc_component *cmpnt_codec = |
330 | asoc_rtd_to_codec(rtd, 0)->component; | |
4e37528a TBS |
331 | struct mt8192_mt6359_priv *priv = snd_soc_card_get_drvdata(rtd->card); |
332 | struct snd_soc_jack *jack = &priv->headset_jack; | |
18b13ff2 JY |
333 | int ret; |
334 | ||
3ffb9fa3 NP |
335 | ret = mt8192_dai_i2s_set_share(afe, "I2S8", "I2S9"); |
336 | if (ret) { | |
337 | dev_err(rtd->dev, "Failed to set up shared clocks\n"); | |
338 | return ret; | |
339 | } | |
340 | ||
194ff8db | 341 | ret = snd_soc_card_jack_new_pins(rtd->card, "Headset Jack", |
18b13ff2 JY |
342 | SND_JACK_HEADSET | SND_JACK_BTN_0 | |
343 | SND_JACK_BTN_1 | SND_JACK_BTN_2 | | |
344 | SND_JACK_BTN_3, | |
194ff8db NP |
345 | jack, mt8192_jack_pins, |
346 | ARRAY_SIZE(mt8192_jack_pins)); | |
18b13ff2 JY |
347 | if (ret) { |
348 | dev_err(rtd->dev, "Headset Jack creation failed: %d\n", ret); | |
349 | return ret; | |
350 | } | |
351 | ||
352 | snd_jack_set_key(jack->jack, SND_JACK_BTN_0, KEY_PLAYPAUSE); | |
353 | snd_jack_set_key(jack->jack, SND_JACK_BTN_1, KEY_VOICECOMMAND); | |
354 | snd_jack_set_key(jack->jack, SND_JACK_BTN_2, KEY_VOLUMEUP); | |
355 | snd_jack_set_key(jack->jack, SND_JACK_BTN_3, KEY_VOLUMEDOWN); | |
356 | ||
12295ef9 | 357 | return snd_soc_component_set_jack(cmpnt_codec, jack, NULL); |
18b13ff2 JY |
358 | }; |
359 | ||
0d80c48c TBS |
360 | static int mt8192_mt6359_hdmi_init(struct snd_soc_pcm_runtime *rtd) |
361 | { | |
362 | struct snd_soc_component *cmpnt_codec = | |
363 | asoc_rtd_to_codec(rtd, 0)->component; | |
364 | struct mt8192_mt6359_priv *priv = snd_soc_card_get_drvdata(rtd->card); | |
365 | int ret; | |
366 | ||
367 | ret = snd_soc_card_jack_new(rtd->card, "HDMI Jack", SND_JACK_LINEOUT, | |
19aed2d6 | 368 | &priv->hdmi_jack); |
0d80c48c TBS |
369 | if (ret) { |
370 | dev_err(rtd->dev, "HDMI Jack creation failed: %d\n", ret); | |
371 | return ret; | |
372 | } | |
373 | ||
374 | return snd_soc_component_set_jack(cmpnt_codec, &priv->hdmi_jack, NULL); | |
375 | } | |
376 | ||
18b13ff2 JY |
377 | static int mt8192_i2s_hw_params_fixup(struct snd_soc_pcm_runtime *rtd, |
378 | struct snd_pcm_hw_params *params) | |
379 | { | |
03c2192a | 380 | /* fix BE i2s format to S24_LE, clean param mask first */ |
18b13ff2 | 381 | snd_mask_reset_range(hw_param_mask(params, SNDRV_PCM_HW_PARAM_FORMAT), |
03c2192a | 382 | 0, (__force unsigned int)SNDRV_PCM_FORMAT_LAST); |
18b13ff2 JY |
383 | |
384 | params_set_format(params, SNDRV_PCM_FORMAT_S24_LE); | |
385 | ||
386 | return 0; | |
387 | } | |
388 | ||
389 | static int | |
4cceb42f | 390 | mt8192_mt6359_cap1_startup(struct snd_pcm_substream *substream) |
18b13ff2 | 391 | { |
18b13ff2 JY |
392 | static const unsigned int channels[] = { |
393 | 1, 2, 4 | |
394 | }; | |
395 | static const struct snd_pcm_hw_constraint_list constraints_channels = { | |
396 | .count = ARRAY_SIZE(channels), | |
397 | .list = channels, | |
398 | .mask = 0, | |
399 | }; | |
400 | static const unsigned int rates[] = { | |
401 | 8000, 16000, 32000, 48000, 96000, 192000 | |
402 | }; | |
403 | static const struct snd_pcm_hw_constraint_list constraints_rates = { | |
404 | .count = ARRAY_SIZE(rates), | |
405 | .list = rates, | |
406 | .mask = 0, | |
407 | }; | |
408 | ||
4cceb42f | 409 | struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); |
18b13ff2 | 410 | struct snd_pcm_runtime *runtime = substream->runtime; |
4cceb42f | 411 | int ret; |
18b13ff2 JY |
412 | |
413 | ret = snd_pcm_hw_constraint_list(runtime, 0, | |
414 | SNDRV_PCM_HW_PARAM_CHANNELS, | |
415 | &constraints_channels); | |
416 | if (ret < 0) { | |
4cceb42f | 417 | dev_err(rtd->dev, "hw_constraint_list channels failed\n"); |
18b13ff2 JY |
418 | return ret; |
419 | } | |
420 | ||
421 | ret = snd_pcm_hw_constraint_list(runtime, 0, | |
422 | SNDRV_PCM_HW_PARAM_RATE, | |
423 | &constraints_rates); | |
424 | if (ret < 0) { | |
4cceb42f | 425 | dev_err(rtd->dev, "hw_constraint_list rate failed\n"); |
18b13ff2 JY |
426 | return ret; |
427 | } | |
428 | ||
429 | return 0; | |
430 | } | |
431 | ||
4cceb42f TBS |
432 | static const struct snd_soc_ops mt8192_mt6359_capture1_ops = { |
433 | .startup = mt8192_mt6359_cap1_startup, | |
18b13ff2 JY |
434 | }; |
435 | ||
339f6c73 TBS |
436 | static int |
437 | mt8192_mt6359_rt5682_startup(struct snd_pcm_substream *substream) | |
438 | { | |
439 | static const unsigned int channels[] = { | |
440 | 1, 2 | |
441 | }; | |
442 | static const struct snd_pcm_hw_constraint_list constraints_channels = { | |
443 | .count = ARRAY_SIZE(channels), | |
444 | .list = channels, | |
445 | .mask = 0, | |
446 | }; | |
447 | static const unsigned int rates[] = { | |
448 | 48000 | |
449 | }; | |
450 | static const struct snd_pcm_hw_constraint_list constraints_rates = { | |
451 | .count = ARRAY_SIZE(rates), | |
452 | .list = rates, | |
453 | .mask = 0, | |
454 | }; | |
455 | ||
456 | struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); | |
457 | struct snd_pcm_runtime *runtime = substream->runtime; | |
458 | int ret; | |
459 | ||
460 | ret = snd_pcm_hw_constraint_list(runtime, 0, | |
461 | SNDRV_PCM_HW_PARAM_CHANNELS, | |
462 | &constraints_channels); | |
463 | if (ret < 0) { | |
464 | dev_err(rtd->dev, "hw_constraint_list channels failed\n"); | |
465 | return ret; | |
466 | } | |
467 | ||
468 | ret = snd_pcm_hw_constraint_list(runtime, 0, | |
469 | SNDRV_PCM_HW_PARAM_RATE, | |
470 | &constraints_rates); | |
471 | if (ret < 0) { | |
472 | dev_err(rtd->dev, "hw_constraint_list rate failed\n"); | |
473 | return ret; | |
474 | } | |
475 | ||
476 | return 0; | |
477 | } | |
478 | ||
479 | static const struct snd_soc_ops mt8192_mt6359_rt5682_ops = { | |
480 | .startup = mt8192_mt6359_rt5682_startup, | |
481 | }; | |
482 | ||
18b13ff2 JY |
483 | /* FE */ |
484 | SND_SOC_DAILINK_DEFS(playback1, | |
485 | DAILINK_COMP_ARRAY(COMP_CPU("DL1")), | |
486 | DAILINK_COMP_ARRAY(COMP_DUMMY()), | |
487 | DAILINK_COMP_ARRAY(COMP_EMPTY())); | |
488 | ||
489 | SND_SOC_DAILINK_DEFS(playback12, | |
490 | DAILINK_COMP_ARRAY(COMP_CPU("DL12")), | |
491 | DAILINK_COMP_ARRAY(COMP_DUMMY()), | |
492 | DAILINK_COMP_ARRAY(COMP_EMPTY())); | |
493 | ||
494 | SND_SOC_DAILINK_DEFS(playback2, | |
495 | DAILINK_COMP_ARRAY(COMP_CPU("DL2")), | |
496 | DAILINK_COMP_ARRAY(COMP_DUMMY()), | |
497 | DAILINK_COMP_ARRAY(COMP_EMPTY())); | |
498 | ||
499 | SND_SOC_DAILINK_DEFS(playback3, | |
500 | DAILINK_COMP_ARRAY(COMP_CPU("DL3")), | |
501 | DAILINK_COMP_ARRAY(COMP_DUMMY()), | |
502 | DAILINK_COMP_ARRAY(COMP_EMPTY())); | |
503 | ||
504 | SND_SOC_DAILINK_DEFS(playback4, | |
505 | DAILINK_COMP_ARRAY(COMP_CPU("DL4")), | |
506 | DAILINK_COMP_ARRAY(COMP_DUMMY()), | |
507 | DAILINK_COMP_ARRAY(COMP_EMPTY())); | |
508 | ||
509 | SND_SOC_DAILINK_DEFS(playback5, | |
510 | DAILINK_COMP_ARRAY(COMP_CPU("DL5")), | |
511 | DAILINK_COMP_ARRAY(COMP_DUMMY()), | |
512 | DAILINK_COMP_ARRAY(COMP_EMPTY())); | |
513 | ||
514 | SND_SOC_DAILINK_DEFS(playback6, | |
515 | DAILINK_COMP_ARRAY(COMP_CPU("DL6")), | |
516 | DAILINK_COMP_ARRAY(COMP_DUMMY()), | |
517 | DAILINK_COMP_ARRAY(COMP_EMPTY())); | |
518 | ||
519 | SND_SOC_DAILINK_DEFS(playback7, | |
520 | DAILINK_COMP_ARRAY(COMP_CPU("DL7")), | |
521 | DAILINK_COMP_ARRAY(COMP_DUMMY()), | |
522 | DAILINK_COMP_ARRAY(COMP_EMPTY())); | |
523 | ||
524 | SND_SOC_DAILINK_DEFS(playback8, | |
525 | DAILINK_COMP_ARRAY(COMP_CPU("DL8")), | |
526 | DAILINK_COMP_ARRAY(COMP_DUMMY()), | |
527 | DAILINK_COMP_ARRAY(COMP_EMPTY())); | |
528 | ||
529 | SND_SOC_DAILINK_DEFS(playback9, | |
530 | DAILINK_COMP_ARRAY(COMP_CPU("DL9")), | |
531 | DAILINK_COMP_ARRAY(COMP_DUMMY()), | |
532 | DAILINK_COMP_ARRAY(COMP_EMPTY())); | |
533 | ||
534 | SND_SOC_DAILINK_DEFS(capture1, | |
535 | DAILINK_COMP_ARRAY(COMP_CPU("UL1")), | |
536 | DAILINK_COMP_ARRAY(COMP_DUMMY()), | |
537 | DAILINK_COMP_ARRAY(COMP_EMPTY())); | |
538 | ||
539 | SND_SOC_DAILINK_DEFS(capture2, | |
540 | DAILINK_COMP_ARRAY(COMP_CPU("UL2")), | |
541 | DAILINK_COMP_ARRAY(COMP_DUMMY()), | |
542 | DAILINK_COMP_ARRAY(COMP_EMPTY())); | |
543 | ||
544 | SND_SOC_DAILINK_DEFS(capture3, | |
545 | DAILINK_COMP_ARRAY(COMP_CPU("UL3")), | |
546 | DAILINK_COMP_ARRAY(COMP_DUMMY()), | |
547 | DAILINK_COMP_ARRAY(COMP_EMPTY())); | |
548 | ||
549 | SND_SOC_DAILINK_DEFS(capture4, | |
550 | DAILINK_COMP_ARRAY(COMP_CPU("UL4")), | |
551 | DAILINK_COMP_ARRAY(COMP_DUMMY()), | |
552 | DAILINK_COMP_ARRAY(COMP_EMPTY())); | |
553 | ||
554 | SND_SOC_DAILINK_DEFS(capture5, | |
555 | DAILINK_COMP_ARRAY(COMP_CPU("UL5")), | |
556 | DAILINK_COMP_ARRAY(COMP_DUMMY()), | |
557 | DAILINK_COMP_ARRAY(COMP_EMPTY())); | |
558 | ||
559 | SND_SOC_DAILINK_DEFS(capture6, | |
560 | DAILINK_COMP_ARRAY(COMP_CPU("UL6")), | |
561 | DAILINK_COMP_ARRAY(COMP_DUMMY()), | |
562 | DAILINK_COMP_ARRAY(COMP_EMPTY())); | |
563 | ||
564 | SND_SOC_DAILINK_DEFS(capture7, | |
565 | DAILINK_COMP_ARRAY(COMP_CPU("UL7")), | |
566 | DAILINK_COMP_ARRAY(COMP_DUMMY()), | |
567 | DAILINK_COMP_ARRAY(COMP_EMPTY())); | |
568 | ||
569 | SND_SOC_DAILINK_DEFS(capture8, | |
570 | DAILINK_COMP_ARRAY(COMP_CPU("UL8")), | |
571 | DAILINK_COMP_ARRAY(COMP_DUMMY()), | |
572 | DAILINK_COMP_ARRAY(COMP_EMPTY())); | |
573 | ||
574 | SND_SOC_DAILINK_DEFS(capture_mono1, | |
575 | DAILINK_COMP_ARRAY(COMP_CPU("UL_MONO_1")), | |
576 | DAILINK_COMP_ARRAY(COMP_DUMMY()), | |
577 | DAILINK_COMP_ARRAY(COMP_EMPTY())); | |
578 | ||
579 | SND_SOC_DAILINK_DEFS(capture_mono2, | |
580 | DAILINK_COMP_ARRAY(COMP_CPU("UL_MONO_2")), | |
581 | DAILINK_COMP_ARRAY(COMP_DUMMY()), | |
582 | DAILINK_COMP_ARRAY(COMP_EMPTY())); | |
583 | ||
584 | SND_SOC_DAILINK_DEFS(capture_mono3, | |
585 | DAILINK_COMP_ARRAY(COMP_CPU("UL_MONO_3")), | |
586 | DAILINK_COMP_ARRAY(COMP_DUMMY()), | |
587 | DAILINK_COMP_ARRAY(COMP_EMPTY())); | |
588 | ||
589 | SND_SOC_DAILINK_DEFS(playback_hdmi, | |
590 | DAILINK_COMP_ARRAY(COMP_CPU("HDMI")), | |
591 | DAILINK_COMP_ARRAY(COMP_DUMMY()), | |
592 | DAILINK_COMP_ARRAY(COMP_EMPTY())); | |
593 | ||
594 | /* BE */ | |
595 | SND_SOC_DAILINK_DEFS(primary_codec, | |
596 | DAILINK_COMP_ARRAY(COMP_CPU("ADDA")), | |
597 | DAILINK_COMP_ARRAY(COMP_CODEC("mt6359-sound", | |
2aff94e4 JY |
598 | "mt6359-snd-codec-aif1"), |
599 | COMP_CODEC("dmic-codec", | |
600 | "dmic-hifi")), | |
18b13ff2 JY |
601 | DAILINK_COMP_ARRAY(COMP_EMPTY())); |
602 | ||
603 | SND_SOC_DAILINK_DEFS(primary_codec_ch34, | |
604 | DAILINK_COMP_ARRAY(COMP_CPU("ADDA_CH34")), | |
605 | DAILINK_COMP_ARRAY(COMP_CODEC("mt6359-sound", | |
606 | "mt6359-snd-codec-aif2")), | |
607 | DAILINK_COMP_ARRAY(COMP_EMPTY())); | |
608 | ||
609 | SND_SOC_DAILINK_DEFS(ap_dmic, | |
610 | DAILINK_COMP_ARRAY(COMP_CPU("AP_DMIC")), | |
611 | DAILINK_COMP_ARRAY(COMP_DUMMY()), | |
612 | DAILINK_COMP_ARRAY(COMP_EMPTY())); | |
613 | ||
614 | SND_SOC_DAILINK_DEFS(ap_dmic_ch34, | |
615 | DAILINK_COMP_ARRAY(COMP_CPU("AP_DMIC_CH34")), | |
616 | DAILINK_COMP_ARRAY(COMP_DUMMY()), | |
617 | DAILINK_COMP_ARRAY(COMP_EMPTY())); | |
618 | ||
619 | SND_SOC_DAILINK_DEFS(i2s0, | |
620 | DAILINK_COMP_ARRAY(COMP_CPU("I2S0")), | |
621 | DAILINK_COMP_ARRAY(COMP_DUMMY()), | |
622 | DAILINK_COMP_ARRAY(COMP_EMPTY())); | |
623 | ||
624 | SND_SOC_DAILINK_DEFS(i2s1, | |
625 | DAILINK_COMP_ARRAY(COMP_CPU("I2S1")), | |
626 | DAILINK_COMP_ARRAY(COMP_DUMMY()), | |
627 | DAILINK_COMP_ARRAY(COMP_EMPTY())); | |
628 | ||
629 | SND_SOC_DAILINK_DEFS(i2s2, | |
630 | DAILINK_COMP_ARRAY(COMP_CPU("I2S2")), | |
631 | DAILINK_COMP_ARRAY(COMP_DUMMY()), | |
632 | DAILINK_COMP_ARRAY(COMP_EMPTY())); | |
633 | ||
e1e408e6 | 634 | SND_SOC_DAILINK_DEFS(i2s3, |
18b13ff2 | 635 | DAILINK_COMP_ARRAY(COMP_CPU("I2S3")), |
e1e408e6 | 636 | DAILINK_COMP_ARRAY(COMP_EMPTY()), |
cfd8bb25 TBS |
637 | DAILINK_COMP_ARRAY(COMP_EMPTY())); |
638 | ||
18b13ff2 JY |
639 | SND_SOC_DAILINK_DEFS(i2s5, |
640 | DAILINK_COMP_ARRAY(COMP_CPU("I2S5")), | |
641 | DAILINK_COMP_ARRAY(COMP_DUMMY()), | |
642 | DAILINK_COMP_ARRAY(COMP_EMPTY())); | |
643 | ||
644 | SND_SOC_DAILINK_DEFS(i2s6, | |
645 | DAILINK_COMP_ARRAY(COMP_CPU("I2S6")), | |
646 | DAILINK_COMP_ARRAY(COMP_DUMMY()), | |
647 | DAILINK_COMP_ARRAY(COMP_EMPTY())); | |
648 | ||
649 | SND_SOC_DAILINK_DEFS(i2s7, | |
650 | DAILINK_COMP_ARRAY(COMP_CPU("I2S7")), | |
651 | DAILINK_COMP_ARRAY(COMP_DUMMY()), | |
652 | DAILINK_COMP_ARRAY(COMP_EMPTY())); | |
653 | ||
654 | SND_SOC_DAILINK_DEFS(i2s8, | |
655 | DAILINK_COMP_ARRAY(COMP_CPU("I2S8")), | |
f8910fb4 | 656 | DAILINK_COMP_ARRAY(COMP_EMPTY()), |
18b13ff2 JY |
657 | DAILINK_COMP_ARRAY(COMP_EMPTY())); |
658 | ||
659 | SND_SOC_DAILINK_DEFS(i2s9, | |
660 | DAILINK_COMP_ARRAY(COMP_CPU("I2S9")), | |
f8910fb4 | 661 | DAILINK_COMP_ARRAY(COMP_EMPTY()), |
18b13ff2 JY |
662 | DAILINK_COMP_ARRAY(COMP_EMPTY())); |
663 | ||
664 | SND_SOC_DAILINK_DEFS(connsys_i2s, | |
665 | DAILINK_COMP_ARRAY(COMP_CPU("CONNSYS_I2S")), | |
666 | DAILINK_COMP_ARRAY(COMP_DUMMY()), | |
667 | DAILINK_COMP_ARRAY(COMP_EMPTY())); | |
668 | ||
669 | SND_SOC_DAILINK_DEFS(pcm1, | |
670 | DAILINK_COMP_ARRAY(COMP_CPU("PCM 1")), | |
671 | DAILINK_COMP_ARRAY(COMP_DUMMY()), | |
672 | DAILINK_COMP_ARRAY(COMP_EMPTY())); | |
673 | ||
674 | SND_SOC_DAILINK_DEFS(pcm2, | |
675 | DAILINK_COMP_ARRAY(COMP_CPU("PCM 2")), | |
676 | DAILINK_COMP_ARRAY(COMP_DUMMY()), | |
677 | DAILINK_COMP_ARRAY(COMP_EMPTY())); | |
678 | ||
679 | SND_SOC_DAILINK_DEFS(tdm, | |
680 | DAILINK_COMP_ARRAY(COMP_CPU("TDM")), | |
0d80c48c | 681 | DAILINK_COMP_ARRAY(COMP_CODEC(NULL, "i2s-hifi")), |
18b13ff2 JY |
682 | DAILINK_COMP_ARRAY(COMP_EMPTY())); |
683 | ||
a5f80375 | 684 | static struct snd_soc_dai_link mt8192_mt6359_dai_links[] = { |
18b13ff2 JY |
685 | /* Front End DAI links */ |
686 | { | |
687 | .name = "Playback_1", | |
688 | .stream_name = "Playback_1", | |
689 | .trigger = {SND_SOC_DPCM_TRIGGER_PRE, | |
690 | SND_SOC_DPCM_TRIGGER_PRE}, | |
691 | .dynamic = 1, | |
692 | .dpcm_playback = 1, | |
693 | SND_SOC_DAILINK_REG(playback1), | |
694 | }, | |
695 | { | |
696 | .name = "Playback_12", | |
697 | .stream_name = "Playback_12", | |
698 | .trigger = {SND_SOC_DPCM_TRIGGER_PRE, | |
699 | SND_SOC_DPCM_TRIGGER_PRE}, | |
700 | .dynamic = 1, | |
701 | .dpcm_playback = 1, | |
702 | SND_SOC_DAILINK_REG(playback12), | |
703 | }, | |
704 | { | |
705 | .name = "Playback_2", | |
706 | .stream_name = "Playback_2", | |
707 | .trigger = {SND_SOC_DPCM_TRIGGER_PRE, | |
708 | SND_SOC_DPCM_TRIGGER_PRE}, | |
709 | .dynamic = 1, | |
710 | .dpcm_playback = 1, | |
711 | SND_SOC_DAILINK_REG(playback2), | |
712 | }, | |
713 | { | |
714 | .name = "Playback_3", | |
715 | .stream_name = "Playback_3", | |
716 | .trigger = {SND_SOC_DPCM_TRIGGER_PRE, | |
717 | SND_SOC_DPCM_TRIGGER_PRE}, | |
718 | .dynamic = 1, | |
719 | .dpcm_playback = 1, | |
339f6c73 | 720 | .ops = &mt8192_mt6359_rt5682_ops, |
18b13ff2 JY |
721 | SND_SOC_DAILINK_REG(playback3), |
722 | }, | |
723 | { | |
724 | .name = "Playback_4", | |
725 | .stream_name = "Playback_4", | |
726 | .trigger = {SND_SOC_DPCM_TRIGGER_PRE, | |
727 | SND_SOC_DPCM_TRIGGER_PRE}, | |
728 | .dynamic = 1, | |
729 | .dpcm_playback = 1, | |
730 | SND_SOC_DAILINK_REG(playback4), | |
731 | }, | |
732 | { | |
733 | .name = "Playback_5", | |
734 | .stream_name = "Playback_5", | |
735 | .trigger = {SND_SOC_DPCM_TRIGGER_PRE, | |
736 | SND_SOC_DPCM_TRIGGER_PRE}, | |
737 | .dynamic = 1, | |
738 | .dpcm_playback = 1, | |
739 | SND_SOC_DAILINK_REG(playback5), | |
740 | }, | |
741 | { | |
742 | .name = "Playback_6", | |
743 | .stream_name = "Playback_6", | |
744 | .trigger = {SND_SOC_DPCM_TRIGGER_PRE, | |
745 | SND_SOC_DPCM_TRIGGER_PRE}, | |
746 | .dynamic = 1, | |
747 | .dpcm_playback = 1, | |
748 | SND_SOC_DAILINK_REG(playback6), | |
749 | }, | |
750 | { | |
751 | .name = "Playback_7", | |
752 | .stream_name = "Playback_7", | |
753 | .trigger = {SND_SOC_DPCM_TRIGGER_PRE, | |
754 | SND_SOC_DPCM_TRIGGER_PRE}, | |
755 | .dynamic = 1, | |
756 | .dpcm_playback = 1, | |
757 | SND_SOC_DAILINK_REG(playback7), | |
758 | }, | |
759 | { | |
760 | .name = "Playback_8", | |
761 | .stream_name = "Playback_8", | |
762 | .trigger = {SND_SOC_DPCM_TRIGGER_PRE, | |
763 | SND_SOC_DPCM_TRIGGER_PRE}, | |
764 | .dynamic = 1, | |
765 | .dpcm_playback = 1, | |
766 | SND_SOC_DAILINK_REG(playback8), | |
767 | }, | |
768 | { | |
769 | .name = "Playback_9", | |
770 | .stream_name = "Playback_9", | |
771 | .trigger = {SND_SOC_DPCM_TRIGGER_PRE, | |
772 | SND_SOC_DPCM_TRIGGER_PRE}, | |
773 | .dynamic = 1, | |
774 | .dpcm_playback = 1, | |
775 | SND_SOC_DAILINK_REG(playback9), | |
776 | }, | |
777 | { | |
778 | .name = "Capture_1", | |
779 | .stream_name = "Capture_1", | |
780 | .trigger = {SND_SOC_DPCM_TRIGGER_PRE, | |
781 | SND_SOC_DPCM_TRIGGER_PRE}, | |
782 | .dynamic = 1, | |
783 | .dpcm_capture = 1, | |
4cceb42f | 784 | .ops = &mt8192_mt6359_capture1_ops, |
18b13ff2 JY |
785 | SND_SOC_DAILINK_REG(capture1), |
786 | }, | |
787 | { | |
788 | .name = "Capture_2", | |
789 | .stream_name = "Capture_2", | |
790 | .trigger = {SND_SOC_DPCM_TRIGGER_PRE, | |
791 | SND_SOC_DPCM_TRIGGER_PRE}, | |
792 | .dynamic = 1, | |
793 | .dpcm_capture = 1, | |
339f6c73 | 794 | .ops = &mt8192_mt6359_rt5682_ops, |
18b13ff2 JY |
795 | SND_SOC_DAILINK_REG(capture2), |
796 | }, | |
797 | { | |
798 | .name = "Capture_3", | |
799 | .stream_name = "Capture_3", | |
800 | .trigger = {SND_SOC_DPCM_TRIGGER_PRE, | |
801 | SND_SOC_DPCM_TRIGGER_PRE}, | |
802 | .dynamic = 1, | |
803 | .dpcm_capture = 1, | |
804 | SND_SOC_DAILINK_REG(capture3), | |
805 | }, | |
806 | { | |
807 | .name = "Capture_4", | |
808 | .stream_name = "Capture_4", | |
809 | .trigger = {SND_SOC_DPCM_TRIGGER_PRE, | |
810 | SND_SOC_DPCM_TRIGGER_PRE}, | |
811 | .dynamic = 1, | |
812 | .dpcm_capture = 1, | |
813 | SND_SOC_DAILINK_REG(capture4), | |
814 | }, | |
815 | { | |
816 | .name = "Capture_5", | |
817 | .stream_name = "Capture_5", | |
818 | .trigger = {SND_SOC_DPCM_TRIGGER_PRE, | |
819 | SND_SOC_DPCM_TRIGGER_PRE}, | |
820 | .dynamic = 1, | |
821 | .dpcm_capture = 1, | |
822 | SND_SOC_DAILINK_REG(capture5), | |
823 | }, | |
824 | { | |
825 | .name = "Capture_6", | |
826 | .stream_name = "Capture_6", | |
827 | .trigger = {SND_SOC_DPCM_TRIGGER_PRE, | |
828 | SND_SOC_DPCM_TRIGGER_PRE}, | |
829 | .dynamic = 1, | |
830 | .dpcm_capture = 1, | |
831 | SND_SOC_DAILINK_REG(capture6), | |
832 | }, | |
833 | { | |
834 | .name = "Capture_7", | |
835 | .stream_name = "Capture_7", | |
836 | .trigger = {SND_SOC_DPCM_TRIGGER_PRE, | |
837 | SND_SOC_DPCM_TRIGGER_PRE}, | |
838 | .dynamic = 1, | |
839 | .dpcm_capture = 1, | |
840 | SND_SOC_DAILINK_REG(capture7), | |
841 | }, | |
842 | { | |
843 | .name = "Capture_8", | |
844 | .stream_name = "Capture_8", | |
845 | .trigger = {SND_SOC_DPCM_TRIGGER_PRE, | |
846 | SND_SOC_DPCM_TRIGGER_PRE}, | |
847 | .dynamic = 1, | |
848 | .dpcm_capture = 1, | |
849 | SND_SOC_DAILINK_REG(capture8), | |
850 | }, | |
851 | { | |
852 | .name = "Capture_Mono_1", | |
853 | .stream_name = "Capture_Mono_1", | |
854 | .trigger = {SND_SOC_DPCM_TRIGGER_PRE, | |
855 | SND_SOC_DPCM_TRIGGER_PRE}, | |
856 | .dynamic = 1, | |
857 | .dpcm_capture = 1, | |
858 | SND_SOC_DAILINK_REG(capture_mono1), | |
859 | }, | |
860 | { | |
861 | .name = "Capture_Mono_2", | |
862 | .stream_name = "Capture_Mono_2", | |
863 | .trigger = {SND_SOC_DPCM_TRIGGER_PRE, | |
864 | SND_SOC_DPCM_TRIGGER_PRE}, | |
865 | .dynamic = 1, | |
866 | .dpcm_capture = 1, | |
867 | SND_SOC_DAILINK_REG(capture_mono2), | |
868 | }, | |
869 | { | |
870 | .name = "Capture_Mono_3", | |
871 | .stream_name = "Capture_Mono_3", | |
872 | .trigger = {SND_SOC_DPCM_TRIGGER_PRE, | |
873 | SND_SOC_DPCM_TRIGGER_PRE}, | |
874 | .dynamic = 1, | |
875 | .dpcm_capture = 1, | |
876 | SND_SOC_DAILINK_REG(capture_mono3), | |
877 | }, | |
878 | { | |
879 | .name = "playback_hdmi", | |
880 | .stream_name = "Playback_HDMI", | |
881 | .trigger = {SND_SOC_DPCM_TRIGGER_PRE, | |
882 | SND_SOC_DPCM_TRIGGER_PRE}, | |
883 | .dynamic = 1, | |
884 | .dpcm_playback = 1, | |
885 | SND_SOC_DAILINK_REG(playback_hdmi), | |
886 | }, | |
887 | /* Back End DAI links */ | |
888 | { | |
889 | .name = "Primary Codec", | |
890 | .no_pcm = 1, | |
891 | .dpcm_playback = 1, | |
892 | .dpcm_capture = 1, | |
893 | .ignore_suspend = 1, | |
894 | .init = mt8192_mt6359_init, | |
895 | SND_SOC_DAILINK_REG(primary_codec), | |
896 | }, | |
897 | { | |
898 | .name = "Primary Codec CH34", | |
899 | .no_pcm = 1, | |
900 | .dpcm_playback = 1, | |
901 | .dpcm_capture = 1, | |
902 | .ignore_suspend = 1, | |
903 | SND_SOC_DAILINK_REG(primary_codec_ch34), | |
904 | }, | |
905 | { | |
906 | .name = "AP_DMIC", | |
907 | .no_pcm = 1, | |
908 | .dpcm_capture = 1, | |
909 | .ignore_suspend = 1, | |
910 | SND_SOC_DAILINK_REG(ap_dmic), | |
911 | }, | |
912 | { | |
913 | .name = "AP_DMIC_CH34", | |
914 | .no_pcm = 1, | |
915 | .dpcm_capture = 1, | |
916 | .ignore_suspend = 1, | |
917 | SND_SOC_DAILINK_REG(ap_dmic_ch34), | |
918 | }, | |
919 | { | |
920 | .name = "I2S0", | |
921 | .no_pcm = 1, | |
922 | .dpcm_capture = 1, | |
923 | .ignore_suspend = 1, | |
924 | .be_hw_params_fixup = mt8192_i2s_hw_params_fixup, | |
925 | SND_SOC_DAILINK_REG(i2s0), | |
926 | }, | |
927 | { | |
928 | .name = "I2S1", | |
929 | .no_pcm = 1, | |
930 | .dpcm_playback = 1, | |
931 | .ignore_suspend = 1, | |
932 | .be_hw_params_fixup = mt8192_i2s_hw_params_fixup, | |
933 | SND_SOC_DAILINK_REG(i2s1), | |
934 | }, | |
935 | { | |
936 | .name = "I2S2", | |
937 | .no_pcm = 1, | |
938 | .dpcm_capture = 1, | |
939 | .ignore_suspend = 1, | |
940 | .be_hw_params_fixup = mt8192_i2s_hw_params_fixup, | |
941 | SND_SOC_DAILINK_REG(i2s2), | |
942 | }, | |
943 | { | |
944 | .name = "I2S3", | |
945 | .no_pcm = 1, | |
946 | .dpcm_playback = 1, | |
947 | .ignore_suspend = 1, | |
948 | .be_hw_params_fixup = mt8192_i2s_hw_params_fixup, | |
e1e408e6 | 949 | SND_SOC_DAILINK_REG(i2s3), |
18b13ff2 JY |
950 | }, |
951 | { | |
952 | .name = "I2S5", | |
953 | .no_pcm = 1, | |
954 | .dpcm_playback = 1, | |
955 | .ignore_suspend = 1, | |
956 | .be_hw_params_fixup = mt8192_i2s_hw_params_fixup, | |
957 | SND_SOC_DAILINK_REG(i2s5), | |
958 | }, | |
959 | { | |
960 | .name = "I2S6", | |
961 | .no_pcm = 1, | |
962 | .dpcm_capture = 1, | |
963 | .ignore_suspend = 1, | |
964 | .be_hw_params_fixup = mt8192_i2s_hw_params_fixup, | |
965 | SND_SOC_DAILINK_REG(i2s6), | |
966 | }, | |
967 | { | |
968 | .name = "I2S7", | |
969 | .no_pcm = 1, | |
970 | .dpcm_playback = 1, | |
971 | .ignore_suspend = 1, | |
972 | .be_hw_params_fixup = mt8192_i2s_hw_params_fixup, | |
973 | SND_SOC_DAILINK_REG(i2s7), | |
974 | }, | |
975 | { | |
976 | .name = "I2S8", | |
977 | .no_pcm = 1, | |
978 | .dpcm_capture = 1, | |
979 | .ignore_suspend = 1, | |
980 | .init = mt8192_rt5682_init, | |
981 | .be_hw_params_fixup = mt8192_i2s_hw_params_fixup, | |
982 | SND_SOC_DAILINK_REG(i2s8), | |
6181ab31 | 983 | .ops = &mt8192_rt5682x_i2s_ops, |
18b13ff2 JY |
984 | }, |
985 | { | |
986 | .name = "I2S9", | |
987 | .no_pcm = 1, | |
988 | .dpcm_playback = 1, | |
989 | .ignore_suspend = 1, | |
990 | .be_hw_params_fixup = mt8192_i2s_hw_params_fixup, | |
991 | SND_SOC_DAILINK_REG(i2s9), | |
6181ab31 | 992 | .ops = &mt8192_rt5682x_i2s_ops, |
18b13ff2 JY |
993 | }, |
994 | { | |
995 | .name = "CONNSYS_I2S", | |
996 | .no_pcm = 1, | |
997 | .dpcm_capture = 1, | |
998 | .ignore_suspend = 1, | |
999 | SND_SOC_DAILINK_REG(connsys_i2s), | |
1000 | }, | |
1001 | { | |
1002 | .name = "PCM 1", | |
1003 | .no_pcm = 1, | |
1004 | .dpcm_playback = 1, | |
1005 | .dpcm_capture = 1, | |
1006 | .ignore_suspend = 1, | |
1007 | SND_SOC_DAILINK_REG(pcm1), | |
1008 | }, | |
1009 | { | |
1010 | .name = "PCM 2", | |
1011 | .no_pcm = 1, | |
1012 | .dpcm_playback = 1, | |
1013 | .dpcm_capture = 1, | |
1014 | .ignore_suspend = 1, | |
1015 | SND_SOC_DAILINK_REG(pcm2), | |
1016 | }, | |
1017 | { | |
1018 | .name = "TDM", | |
1019 | .no_pcm = 1, | |
0d80c48c TBS |
1020 | .dai_fmt = SND_SOC_DAIFMT_DSP_A | |
1021 | SND_SOC_DAIFMT_IB_NF | | |
1022 | SND_SOC_DAIFMT_CBM_CFM, | |
18b13ff2 JY |
1023 | .dpcm_playback = 1, |
1024 | .ignore_suspend = 1, | |
0d80c48c TBS |
1025 | .be_hw_params_fixup = mt8192_i2s_hw_params_fixup, |
1026 | .ignore = 1, | |
1027 | .init = mt8192_mt6359_hdmi_init, | |
18b13ff2 JY |
1028 | SND_SOC_DAILINK_REG(tdm), |
1029 | }, | |
1030 | }; | |
1031 | ||
ba499c36 TBS |
1032 | static const struct snd_soc_dapm_widget |
1033 | mt8192_mt6359_rt1015_rt5682_widgets[] = { | |
1034 | SND_SOC_DAPM_SPK("Left Spk", NULL), | |
1035 | SND_SOC_DAPM_SPK("Right Spk", NULL), | |
1036 | SND_SOC_DAPM_HP("Headphone Jack", NULL), | |
1037 | SND_SOC_DAPM_MIC("Headset Mic", NULL), | |
0d80c48c | 1038 | SND_SOC_DAPM_OUTPUT("TDM Out"), |
ba499c36 TBS |
1039 | }; |
1040 | ||
1041 | static const struct snd_soc_dapm_route mt8192_mt6359_rt1015_rt5682_routes[] = { | |
1042 | /* speaker */ | |
1043 | { "Left Spk", NULL, "Left SPO" }, | |
1044 | { "Right Spk", NULL, "Right SPO" }, | |
1045 | /* headset */ | |
1046 | { "Headphone Jack", NULL, "HPOL" }, | |
1047 | { "Headphone Jack", NULL, "HPOR" }, | |
1048 | { "IN1P", NULL, "Headset Mic" }, | |
0d80c48c TBS |
1049 | /* TDM */ |
1050 | { "TDM Out", NULL, "TDM" }, | |
ba499c36 TBS |
1051 | }; |
1052 | ||
1053 | static const struct snd_kcontrol_new mt8192_mt6359_rt1015_rt5682_controls[] = { | |
1054 | SOC_DAPM_PIN_SWITCH("Left Spk"), | |
1055 | SOC_DAPM_PIN_SWITCH("Right Spk"), | |
1056 | SOC_DAPM_PIN_SWITCH("Headphone Jack"), | |
1057 | SOC_DAPM_PIN_SWITCH("Headset Mic"), | |
1058 | }; | |
1059 | ||
18b13ff2 JY |
1060 | static struct snd_soc_codec_conf rt1015_amp_conf[] = { |
1061 | { | |
1062 | .dlc = COMP_CODEC_CONF(RT1015_DEV0_NAME), | |
1063 | .name_prefix = "Left", | |
1064 | }, | |
1065 | { | |
1066 | .dlc = COMP_CODEC_CONF(RT1015_DEV1_NAME), | |
1067 | .name_prefix = "Right", | |
1068 | }, | |
1069 | }; | |
1070 | ||
2b53d2e1 | 1071 | static struct snd_soc_card mt8192_mt6359_rt1015_rt5682_card = { |
6181ab31 | 1072 | .name = RT1015_RT5682_CARD_NAME, |
4674284a | 1073 | .driver_name = DRIVER_NAME, |
18b13ff2 | 1074 | .owner = THIS_MODULE, |
a5f80375 TBS |
1075 | .dai_link = mt8192_mt6359_dai_links, |
1076 | .num_links = ARRAY_SIZE(mt8192_mt6359_dai_links), | |
18b13ff2 JY |
1077 | .controls = mt8192_mt6359_rt1015_rt5682_controls, |
1078 | .num_controls = ARRAY_SIZE(mt8192_mt6359_rt1015_rt5682_controls), | |
1079 | .dapm_widgets = mt8192_mt6359_rt1015_rt5682_widgets, | |
1080 | .num_dapm_widgets = ARRAY_SIZE(mt8192_mt6359_rt1015_rt5682_widgets), | |
1081 | .dapm_routes = mt8192_mt6359_rt1015_rt5682_routes, | |
1082 | .num_dapm_routes = ARRAY_SIZE(mt8192_mt6359_rt1015_rt5682_routes), | |
1083 | .codec_conf = rt1015_amp_conf, | |
1084 | .num_configs = ARRAY_SIZE(rt1015_amp_conf), | |
1085 | }; | |
1086 | ||
6181ab31 | 1087 | static const struct snd_soc_dapm_widget mt8192_mt6359_rt1015p_rt5682x_widgets[] = { |
cfd8bb25 TBS |
1088 | SND_SOC_DAPM_SPK("Speakers", NULL), |
1089 | SND_SOC_DAPM_HP("Headphone Jack", NULL), | |
1090 | SND_SOC_DAPM_MIC("Headset Mic", NULL), | |
1091 | }; | |
1092 | ||
6181ab31 | 1093 | static const struct snd_soc_dapm_route mt8192_mt6359_rt1015p_rt5682x_routes[] = { |
cfd8bb25 TBS |
1094 | /* speaker */ |
1095 | { "Speakers", NULL, "Speaker" }, | |
1096 | /* headset */ | |
1097 | { "Headphone Jack", NULL, "HPOL" }, | |
1098 | { "Headphone Jack", NULL, "HPOR" }, | |
1099 | { "IN1P", NULL, "Headset Mic" }, | |
1100 | }; | |
1101 | ||
6181ab31 | 1102 | static const struct snd_kcontrol_new mt8192_mt6359_rt1015p_rt5682x_controls[] = { |
cfd8bb25 TBS |
1103 | SOC_DAPM_PIN_SWITCH("Speakers"), |
1104 | SOC_DAPM_PIN_SWITCH("Headphone Jack"), | |
1105 | SOC_DAPM_PIN_SWITCH("Headset Mic"), | |
1106 | }; | |
1107 | ||
6181ab31 | 1108 | static struct snd_soc_card mt8192_mt6359_rt1015p_rt5682x_card = { |
4674284a | 1109 | .driver_name = DRIVER_NAME, |
cfd8bb25 TBS |
1110 | .owner = THIS_MODULE, |
1111 | .dai_link = mt8192_mt6359_dai_links, | |
1112 | .num_links = ARRAY_SIZE(mt8192_mt6359_dai_links), | |
6181ab31 JY |
1113 | .controls = mt8192_mt6359_rt1015p_rt5682x_controls, |
1114 | .num_controls = ARRAY_SIZE(mt8192_mt6359_rt1015p_rt5682x_controls), | |
1115 | .dapm_widgets = mt8192_mt6359_rt1015p_rt5682x_widgets, | |
1116 | .num_dapm_widgets = ARRAY_SIZE(mt8192_mt6359_rt1015p_rt5682x_widgets), | |
1117 | .dapm_routes = mt8192_mt6359_rt1015p_rt5682x_routes, | |
1118 | .num_dapm_routes = ARRAY_SIZE(mt8192_mt6359_rt1015p_rt5682x_routes), | |
cfd8bb25 TBS |
1119 | }; |
1120 | ||
e1e408e6 JY |
1121 | static int mt8192_mt6359_card_set_be_link(struct snd_soc_card *card, |
1122 | struct snd_soc_dai_link *link, | |
1123 | struct device_node *node, | |
1124 | char *link_name) | |
1125 | { | |
1126 | int ret; | |
1127 | ||
1128 | if (node && strcmp(link->name, link_name) == 0) { | |
1129 | ret = snd_soc_of_get_dai_link_codecs(card->dev, node, link); | |
1130 | if (ret < 0) { | |
1131 | dev_err_probe(card->dev, ret, "get dai link codecs fail\n"); | |
1132 | return ret; | |
1133 | } | |
1134 | } | |
1135 | ||
1136 | return 0; | |
1137 | } | |
1138 | ||
a5f80375 | 1139 | static int mt8192_mt6359_dev_probe(struct platform_device *pdev) |
18b13ff2 | 1140 | { |
2b53d2e1 | 1141 | struct snd_soc_card *card; |
f8910fb4 | 1142 | struct device_node *platform_node, *hdmi_codec, *headset_codec, *speaker_codec; |
18b13ff2 JY |
1143 | int ret, i; |
1144 | struct snd_soc_dai_link *dai_link; | |
4e37528a | 1145 | struct mt8192_mt6359_priv *priv; |
18b13ff2 | 1146 | |
e1e408e6 JY |
1147 | card = (struct snd_soc_card *)of_device_get_match_data(&pdev->dev); |
1148 | if (!card) | |
18b13ff2 | 1149 | return -EINVAL; |
e1e408e6 | 1150 | card->dev = &pdev->dev; |
18b13ff2 | 1151 | |
6181ab31 JY |
1152 | if (of_device_is_compatible(pdev->dev.of_node, RT1015P_RT5682_OF_NAME)) |
1153 | card->name = RT1015P_RT5682_CARD_NAME; | |
1154 | else if (of_device_is_compatible(pdev->dev.of_node, RT1015P_RT5682S_OF_NAME)) | |
1155 | card->name = RT1015P_RT5682S_CARD_NAME; | |
1156 | else | |
1157 | dev_dbg(&pdev->dev, "No need to set card name\n"); | |
1158 | ||
e1e408e6 JY |
1159 | hdmi_codec = of_parse_phandle(pdev->dev.of_node, "mediatek,hdmi-codec", 0); |
1160 | if (!hdmi_codec) | |
1161 | dev_dbg(&pdev->dev, "The machine has no hdmi-codec\n"); | |
1162 | ||
1163 | platform_node = of_parse_phandle(pdev->dev.of_node, "mediatek,platform", 0); | |
1164 | if (!platform_node) { | |
e45ac783 | 1165 | ret = -EINVAL; |
e1e408e6 JY |
1166 | dev_err_probe(&pdev->dev, ret, "Property 'platform' missing or invalid\n"); |
1167 | goto err_platform_node; | |
e45ac783 | 1168 | } |
2b53d2e1 | 1169 | |
e1e408e6 JY |
1170 | speaker_codec = of_get_child_by_name(pdev->dev.of_node, "speaker-codecs"); |
1171 | if (!speaker_codec) { | |
1172 | ret = -EINVAL; | |
1173 | dev_err_probe(&pdev->dev, ret, "Property 'speaker-codecs' missing or invalid\n"); | |
1174 | goto err_speaker_codec; | |
1175 | } | |
0d80c48c | 1176 | |
f8910fb4 JY |
1177 | headset_codec = of_get_child_by_name(pdev->dev.of_node, "headset-codec"); |
1178 | if (!headset_codec) { | |
1179 | ret = -EINVAL; | |
1180 | dev_err_probe(&pdev->dev, ret, "Property 'headset-codec' missing or invalid\n"); | |
1181 | goto err_headset_codec; | |
1182 | } | |
1183 | ||
18b13ff2 | 1184 | for_each_card_prelinks(card, i, dai_link) { |
e1e408e6 JY |
1185 | ret = mt8192_mt6359_card_set_be_link(card, dai_link, speaker_codec, "I2S3"); |
1186 | if (ret) { | |
1187 | dev_err_probe(&pdev->dev, ret, "%s set speaker_codec fail\n", | |
1188 | dai_link->name); | |
1189 | goto err_probe; | |
2b53d2e1 TBS |
1190 | } |
1191 | ||
f8910fb4 JY |
1192 | ret = mt8192_mt6359_card_set_be_link(card, dai_link, headset_codec, "I2S8"); |
1193 | if (ret) { | |
1194 | dev_err_probe(&pdev->dev, ret, "%s set headset_codec fail\n", | |
1195 | dai_link->name); | |
1196 | goto err_probe; | |
1197 | } | |
1198 | ||
1199 | ret = mt8192_mt6359_card_set_be_link(card, dai_link, headset_codec, "I2S9"); | |
1200 | if (ret) { | |
1201 | dev_err_probe(&pdev->dev, ret, "%s set headset_codec fail\n", | |
1202 | dai_link->name); | |
1203 | goto err_probe; | |
1204 | } | |
1205 | ||
0d80c48c TBS |
1206 | if (hdmi_codec && strcmp(dai_link->name, "TDM") == 0) { |
1207 | dai_link->codecs->of_node = hdmi_codec; | |
1208 | dai_link->ignore = 0; | |
1209 | } | |
1210 | ||
e1e408e6 JY |
1211 | if (strcmp(dai_link->codecs[0].dai_name, RT1015_CODEC_DAI) == 0) |
1212 | dai_link->ops = &mt8192_rt1015_i2s_ops; | |
1213 | ||
18b13ff2 JY |
1214 | if (!dai_link->platforms->name) |
1215 | dai_link->platforms->of_node = platform_node; | |
1216 | } | |
1217 | ||
4e37528a | 1218 | priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL); |
e45ac783 ML |
1219 | if (!priv) { |
1220 | ret = -ENOMEM; | |
e1e408e6 | 1221 | goto err_probe; |
e45ac783 | 1222 | } |
4e37528a TBS |
1223 | snd_soc_card_set_drvdata(card, priv); |
1224 | ||
18b13ff2 JY |
1225 | ret = mt8192_afe_gpio_init(&pdev->dev); |
1226 | if (ret) { | |
e1e408e6 JY |
1227 | dev_err_probe(&pdev->dev, ret, "%s init gpio error\n", __func__); |
1228 | goto err_probe; | |
18b13ff2 JY |
1229 | } |
1230 | ||
4e28491a | 1231 | ret = devm_snd_soc_register_card(&pdev->dev, card); |
e1e408e6 JY |
1232 | if (ret) |
1233 | dev_err_probe(&pdev->dev, ret, "%s snd_soc_register_card fail\n", __func__); | |
4e28491a | 1234 | |
e1e408e6 | 1235 | err_probe: |
f8910fb4 JY |
1236 | of_node_put(headset_codec); |
1237 | err_headset_codec: | |
e1e408e6 JY |
1238 | of_node_put(speaker_codec); |
1239 | err_speaker_codec: | |
e45ac783 | 1240 | of_node_put(platform_node); |
e1e408e6 JY |
1241 | err_platform_node: |
1242 | of_node_put(hdmi_codec); | |
4e28491a | 1243 | return ret; |
18b13ff2 JY |
1244 | } |
1245 | ||
1246 | #ifdef CONFIG_OF | |
a5f80375 | 1247 | static const struct of_device_id mt8192_mt6359_dt_match[] = { |
2b53d2e1 | 1248 | { |
6181ab31 | 1249 | .compatible = RT1015_RT5682_OF_NAME, |
2b53d2e1 TBS |
1250 | .data = &mt8192_mt6359_rt1015_rt5682_card, |
1251 | }, | |
cfd8bb25 | 1252 | { |
6181ab31 JY |
1253 | .compatible = RT1015P_RT5682_OF_NAME, |
1254 | .data = &mt8192_mt6359_rt1015p_rt5682x_card, | |
1255 | }, | |
1256 | { | |
1257 | .compatible = RT1015P_RT5682S_OF_NAME, | |
1258 | .data = &mt8192_mt6359_rt1015p_rt5682x_card, | |
cfd8bb25 | 1259 | }, |
18b13ff2 JY |
1260 | {} |
1261 | }; | |
2d32a3e5 | 1262 | MODULE_DEVICE_TABLE(of, mt8192_mt6359_dt_match); |
18b13ff2 JY |
1263 | #endif |
1264 | ||
a5f80375 | 1265 | static const struct dev_pm_ops mt8192_mt6359_pm_ops = { |
18b13ff2 JY |
1266 | .poweroff = snd_soc_poweroff, |
1267 | .restore = snd_soc_resume, | |
1268 | }; | |
1269 | ||
a5f80375 | 1270 | static struct platform_driver mt8192_mt6359_driver = { |
18b13ff2 | 1271 | .driver = { |
4674284a | 1272 | .name = DRIVER_NAME, |
18b13ff2 | 1273 | #ifdef CONFIG_OF |
a5f80375 | 1274 | .of_match_table = mt8192_mt6359_dt_match, |
18b13ff2 | 1275 | #endif |
a5f80375 | 1276 | .pm = &mt8192_mt6359_pm_ops, |
18b13ff2 | 1277 | }, |
a5f80375 | 1278 | .probe = mt8192_mt6359_dev_probe, |
18b13ff2 JY |
1279 | }; |
1280 | ||
a5f80375 | 1281 | module_platform_driver(mt8192_mt6359_driver); |
18b13ff2 JY |
1282 | |
1283 | /* Module information */ | |
a5f80375 | 1284 | MODULE_DESCRIPTION("MT8192-MT6359 ALSA SoC machine driver"); |
18b13ff2 JY |
1285 | MODULE_AUTHOR("Jiaxin Yu <jiaxin.yu@mediatek.com>"); |
1286 | MODULE_LICENSE("GPL v2"); | |
a5f80375 | 1287 | MODULE_ALIAS("mt8192_mt6359 soc card"); |