1// SPDX-License-Identifier: GPL-2.0
2//
3// mt8183-da7219-max98357.c
4// -- MT8183-DA7219-MAX98357 ALSA SoC machine driver
5//
6// Copyright (c) 2018 MediaTek Inc.
7// Author: Shunli Wang <shunli.wang@mediatek.com>
8
9#include <linux/input.h>
10#include <linux/module.h>
11#include <linux/of.h>
12#include <linux/pinctrl/consumer.h>
13#include <sound/jack.h>
14#include <sound/pcm_params.h>
15#include <sound/soc.h>
16
17#include "../../codecs/da7219.h"
18#include "../../codecs/rt1015.h"
19#include "../common/mtk-afe-platform-driver.h"
20#include "mt8183-afe-common.h"
21
22#define DA7219_CODEC_DAI "da7219-hifi"
23#define DA7219_DEV_NAME "da7219.5-001a"
24#define RT1015_CODEC_DAI "rt1015-aif"
25#define RT1015_DEV0_NAME "rt1015.6-0028"
26#define RT1015_DEV1_NAME "rt1015.6-0029"
27
28struct mt8183_da7219_max98357_priv {
29 struct snd_soc_jack headset_jack, hdmi_jack;
30};
31
32static struct snd_soc_jack_pin mt8183_da7219_max98357_jack_pins[] = {
33 {
34 .pin = "Headphones",
35 .mask = SND_JACK_HEADPHONE,
36 },
37 {
38 .pin = "Headset Mic",
39 .mask = SND_JACK_MICROPHONE,
40 },
41 {
42 .pin = "Line Out",
43 .mask = SND_JACK_LINEOUT,
44 },
45};
46
47static int mt8183_mt6358_i2s_hw_params(struct snd_pcm_substream *substream,
48 struct snd_pcm_hw_params *params)
49{
50 struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream);
51 unsigned int rate = params_rate(p: params);
52 unsigned int mclk_fs_ratio = 128;
53 unsigned int mclk_fs = rate * mclk_fs_ratio;
54
55 return snd_soc_dai_set_sysclk(snd_soc_rtd_to_cpu(rtd, 0),
56 clk_id: 0, freq: mclk_fs, SND_SOC_CLOCK_OUT);
57}
58
59static const struct snd_soc_ops mt8183_mt6358_i2s_ops = {
60 .hw_params = mt8183_mt6358_i2s_hw_params,
61};
62
63static int mt8183_da7219_i2s_hw_params(struct snd_pcm_substream *substream,
64 struct snd_pcm_hw_params *params)
65{
66 struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream);
67 struct snd_soc_dai *codec_dai;
68 unsigned int rate = params_rate(p: params);
69 unsigned int mclk_fs_ratio = 256;
70 unsigned int mclk_fs = rate * mclk_fs_ratio;
71 unsigned int freq;
72 int ret = 0, j;
73
74 ret = snd_soc_dai_set_sysclk(snd_soc_rtd_to_cpu(rtd, 0), clk_id: 0,
75 freq: mclk_fs, SND_SOC_CLOCK_OUT);
76 if (ret < 0)
77 dev_err(rtd->dev, "failed to set cpu dai sysclk\n");
78
79 for_each_rtd_codec_dais(rtd, j, codec_dai) {
80 if (!strcmp(codec_dai->component->name, DA7219_DEV_NAME)) {
81 ret = snd_soc_dai_set_sysclk(dai: codec_dai,
82 clk_id: DA7219_CLKSRC_MCLK,
83 freq: mclk_fs,
84 SND_SOC_CLOCK_IN);
85 if (ret < 0)
86 dev_err(rtd->dev, "failed to set sysclk\n");
87
88 if ((rate % 8000) == 0)
89 freq = DA7219_PLL_FREQ_OUT_98304;
90 else
91 freq = DA7219_PLL_FREQ_OUT_90316;
92
93 ret = snd_soc_dai_set_pll(dai: codec_dai, pll_id: 0,
94 source: DA7219_SYSCLK_PLL_SRM,
95 freq_in: 0, freq_out: freq);
96 if (ret)
97 dev_err(rtd->dev, "failed to start PLL: %d\n",
98 ret);
99 }
100 }
101
102 return ret;
103}
104
105static int mt8183_da7219_hw_free(struct snd_pcm_substream *substream)
106{
107 struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream);
108 struct snd_soc_dai *codec_dai;
109 int ret = 0, j;
110
111 for_each_rtd_codec_dais(rtd, j, codec_dai) {
112 if (!strcmp(codec_dai->component->name, DA7219_DEV_NAME)) {
113 ret = snd_soc_dai_set_pll(dai: codec_dai,
114 pll_id: 0, source: DA7219_SYSCLK_MCLK, freq_in: 0, freq_out: 0);
115 if (ret < 0) {
116 dev_err(rtd->dev, "failed to stop PLL: %d\n",
117 ret);
118 break;
119 }
120 }
121 }
122
123 return ret;
124}
125
126static const struct snd_soc_ops mt8183_da7219_i2s_ops = {
127 .hw_params = mt8183_da7219_i2s_hw_params,
128 .hw_free = mt8183_da7219_hw_free,
129};
130
131static int
132mt8183_da7219_rt1015_i2s_hw_params(struct snd_pcm_substream *substream,
133 struct snd_pcm_hw_params *params)
134{
135 struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream);
136 unsigned int rate = params_rate(p: params);
137 struct snd_soc_dai *codec_dai;
138 int ret = 0, i;
139
140 for_each_rtd_codec_dais(rtd, i, codec_dai) {
141 if (!strcmp(codec_dai->component->name, RT1015_DEV0_NAME) ||
142 !strcmp(codec_dai->component->name, RT1015_DEV1_NAME)) {
143 ret = snd_soc_dai_set_pll(dai: codec_dai, pll_id: 0,
144 source: RT1015_PLL_S_BCLK,
145 freq_in: rate * 64, freq_out: rate * 256);
146 if (ret) {
147 dev_err(rtd->dev, "failed to set pll\n");
148 return ret;
149 }
150
151 ret = snd_soc_dai_set_sysclk(dai: codec_dai,
152 clk_id: RT1015_SCLK_S_PLL,
153 freq: rate * 256,
154 SND_SOC_CLOCK_IN);
155 if (ret) {
156 dev_err(rtd->dev, "failed to set sysclk\n");
157 return ret;
158 }
159 }
160 }
161
162 return mt8183_da7219_i2s_hw_params(substream, params);
163}
164
165static const struct snd_soc_ops mt8183_da7219_rt1015_i2s_ops = {
166 .hw_params = mt8183_da7219_rt1015_i2s_hw_params,
167 .hw_free = mt8183_da7219_hw_free,
168};
169
170static int mt8183_i2s_hw_params_fixup(struct snd_soc_pcm_runtime *rtd,
171 struct snd_pcm_hw_params *params)
172{
173 /* fix BE i2s format to S32_LE, clean param mask first */
174 snd_mask_reset_range(mask: hw_param_mask(params, SNDRV_PCM_HW_PARAM_FORMAT),
175 from: 0, to: (__force unsigned int)SNDRV_PCM_FORMAT_LAST);
176
177 params_set_format(p: params, SNDRV_PCM_FORMAT_S32_LE);
178
179 return 0;
180}
181
182static int mt8183_rt1015_i2s_hw_params_fixup(struct snd_soc_pcm_runtime *rtd,
183 struct snd_pcm_hw_params *params)
184{
185 /* fix BE i2s format to S24_LE, clean param mask first */
186 snd_mask_reset_range(mask: hw_param_mask(params, SNDRV_PCM_HW_PARAM_FORMAT),
187 from: 0, to: (__force unsigned int)SNDRV_PCM_FORMAT_LAST);
188
189 params_set_format(p: params, SNDRV_PCM_FORMAT_S24_LE);
190
191 return 0;
192}
193
194static int
195mt8183_da7219_max98357_startup(
196 struct snd_pcm_substream *substream)
197{
198 static const unsigned int rates[] = {
199 48000,
200 };
201 static const struct snd_pcm_hw_constraint_list constraints_rates = {
202 .count = ARRAY_SIZE(rates),
203 .list = rates,
204 .mask = 0,
205 };
206 static const unsigned int channels[] = {
207 2,
208 };
209 static const struct snd_pcm_hw_constraint_list constraints_channels = {
210 .count = ARRAY_SIZE(channels),
211 .list = channels,
212 .mask = 0,
213 };
214
215 struct snd_pcm_runtime *runtime = substream->runtime;
216
217 snd_pcm_hw_constraint_list(runtime, cond: 0,
218 SNDRV_PCM_HW_PARAM_RATE, l: &constraints_rates);
219 runtime->hw.channels_max = 2;
220 snd_pcm_hw_constraint_list(runtime, cond: 0,
221 SNDRV_PCM_HW_PARAM_CHANNELS,
222 l: &constraints_channels);
223
224 runtime->hw.formats = SNDRV_PCM_FMTBIT_S16_LE;
225 snd_pcm_hw_constraint_msbits(runtime, cond: 0, width: 16, msbits: 16);
226
227 return 0;
228}
229
230static const struct snd_soc_ops mt8183_da7219_max98357_ops = {
231 .startup = mt8183_da7219_max98357_startup,
232};
233
234static int
235mt8183_da7219_max98357_bt_sco_startup(
236 struct snd_pcm_substream *substream)
237{
238 static const unsigned int rates[] = {
239 8000, 16000
240 };
241 static const struct snd_pcm_hw_constraint_list constraints_rates = {
242 .count = ARRAY_SIZE(rates),
243 .list = rates,
244 .mask = 0,
245 };
246 static const unsigned int channels[] = {
247 1,
248 };
249 static const struct snd_pcm_hw_constraint_list constraints_channels = {
250 .count = ARRAY_SIZE(channels),
251 .list = channels,
252 .mask = 0,
253 };
254
255 struct snd_pcm_runtime *runtime = substream->runtime;
256
257 snd_pcm_hw_constraint_list(runtime, cond: 0,
258 SNDRV_PCM_HW_PARAM_RATE, l: &constraints_rates);
259 runtime->hw.channels_max = 1;
260 snd_pcm_hw_constraint_list(runtime, cond: 0,
261 SNDRV_PCM_HW_PARAM_CHANNELS,
262 l: &constraints_channels);
263
264 runtime->hw.formats = SNDRV_PCM_FMTBIT_S16_LE;
265 snd_pcm_hw_constraint_msbits(runtime, cond: 0, width: 16, msbits: 16);
266
267 return 0;
268}
269
270static const struct snd_soc_ops mt8183_da7219_max98357_bt_sco_ops = {
271 .startup = mt8183_da7219_max98357_bt_sco_startup,
272};
273
274/* FE */
275SND_SOC_DAILINK_DEFS(playback1,
276 DAILINK_COMP_ARRAY(COMP_CPU("DL1")),
277 DAILINK_COMP_ARRAY(COMP_DUMMY()),
278 DAILINK_COMP_ARRAY(COMP_EMPTY()));
279
280SND_SOC_DAILINK_DEFS(playback2,
281 DAILINK_COMP_ARRAY(COMP_CPU("DL2")),
282 DAILINK_COMP_ARRAY(COMP_DUMMY()),
283 DAILINK_COMP_ARRAY(COMP_EMPTY()));
284
285SND_SOC_DAILINK_DEFS(playback3,
286 DAILINK_COMP_ARRAY(COMP_CPU("DL3")),
287 DAILINK_COMP_ARRAY(COMP_DUMMY()),
288 DAILINK_COMP_ARRAY(COMP_EMPTY()));
289
290SND_SOC_DAILINK_DEFS(capture1,
291 DAILINK_COMP_ARRAY(COMP_CPU("UL1")),
292 DAILINK_COMP_ARRAY(COMP_DUMMY()),
293 DAILINK_COMP_ARRAY(COMP_EMPTY()));
294
295SND_SOC_DAILINK_DEFS(capture2,
296 DAILINK_COMP_ARRAY(COMP_CPU("UL2")),
297 DAILINK_COMP_ARRAY(COMP_DUMMY()),
298 DAILINK_COMP_ARRAY(COMP_EMPTY()));
299
300SND_SOC_DAILINK_DEFS(capture3,
301 DAILINK_COMP_ARRAY(COMP_CPU("UL3")),
302 DAILINK_COMP_ARRAY(COMP_DUMMY()),
303 DAILINK_COMP_ARRAY(COMP_EMPTY()));
304
305SND_SOC_DAILINK_DEFS(capture_mono,
306 DAILINK_COMP_ARRAY(COMP_CPU("UL_MONO_1")),
307 DAILINK_COMP_ARRAY(COMP_DUMMY()),
308 DAILINK_COMP_ARRAY(COMP_EMPTY()));
309
310SND_SOC_DAILINK_DEFS(playback_hdmi,
311 DAILINK_COMP_ARRAY(COMP_CPU("HDMI")),
312 DAILINK_COMP_ARRAY(COMP_DUMMY()),
313 DAILINK_COMP_ARRAY(COMP_EMPTY()));
314
315/* BE */
316SND_SOC_DAILINK_DEFS(primary_codec,
317 DAILINK_COMP_ARRAY(COMP_CPU("ADDA")),
318 DAILINK_COMP_ARRAY(COMP_CODEC("mt6358-sound", "mt6358-snd-codec-aif1")),
319 DAILINK_COMP_ARRAY(COMP_EMPTY()));
320
321SND_SOC_DAILINK_DEFS(pcm1,
322 DAILINK_COMP_ARRAY(COMP_CPU("PCM 1")),
323 DAILINK_COMP_ARRAY(COMP_DUMMY()),
324 DAILINK_COMP_ARRAY(COMP_EMPTY()));
325
326SND_SOC_DAILINK_DEFS(pcm2,
327 DAILINK_COMP_ARRAY(COMP_CPU("PCM 2")),
328 DAILINK_COMP_ARRAY(COMP_DUMMY()),
329 DAILINK_COMP_ARRAY(COMP_EMPTY()));
330
331SND_SOC_DAILINK_DEFS(i2s0,
332 DAILINK_COMP_ARRAY(COMP_CPU("I2S0")),
333 DAILINK_COMP_ARRAY(COMP_CODEC("bt-sco", "bt-sco-pcm")),
334 DAILINK_COMP_ARRAY(COMP_EMPTY()));
335
336SND_SOC_DAILINK_DEFS(i2s1,
337 DAILINK_COMP_ARRAY(COMP_CPU("I2S1")),
338 DAILINK_COMP_ARRAY(COMP_DUMMY()),
339 DAILINK_COMP_ARRAY(COMP_EMPTY()));
340
341SND_SOC_DAILINK_DEFS(i2s2,
342 DAILINK_COMP_ARRAY(COMP_CPU("I2S2")),
343 DAILINK_COMP_ARRAY(COMP_CODEC(DA7219_DEV_NAME, DA7219_CODEC_DAI)),
344 DAILINK_COMP_ARRAY(COMP_EMPTY()));
345
346SND_SOC_DAILINK_DEFS(i2s3_max98357a,
347 DAILINK_COMP_ARRAY(COMP_CPU("I2S3")),
348 DAILINK_COMP_ARRAY(COMP_CODEC("max98357a", "HiFi"),
349 COMP_CODEC(DA7219_DEV_NAME, DA7219_CODEC_DAI)),
350 DAILINK_COMP_ARRAY(COMP_EMPTY()));
351
352SND_SOC_DAILINK_DEFS(i2s3_rt1015,
353 DAILINK_COMP_ARRAY(COMP_CPU("I2S3")),
354 DAILINK_COMP_ARRAY(COMP_CODEC(RT1015_DEV0_NAME, RT1015_CODEC_DAI),
355 COMP_CODEC(RT1015_DEV1_NAME, RT1015_CODEC_DAI),
356 COMP_CODEC(DA7219_DEV_NAME, DA7219_CODEC_DAI)),
357 DAILINK_COMP_ARRAY(COMP_EMPTY()));
358
359SND_SOC_DAILINK_DEFS(i2s3_rt1015p,
360 DAILINK_COMP_ARRAY(COMP_CPU("I2S3")),
361 DAILINK_COMP_ARRAY(COMP_CODEC("rt1015p", "HiFi"),
362 COMP_CODEC(DA7219_DEV_NAME, DA7219_CODEC_DAI)),
363 DAILINK_COMP_ARRAY(COMP_EMPTY()));
364
365SND_SOC_DAILINK_DEFS(i2s5,
366 DAILINK_COMP_ARRAY(COMP_CPU("I2S5")),
367 DAILINK_COMP_ARRAY(COMP_CODEC("bt-sco", "bt-sco-pcm")),
368 DAILINK_COMP_ARRAY(COMP_EMPTY()));
369
370SND_SOC_DAILINK_DEFS(tdm,
371 DAILINK_COMP_ARRAY(COMP_CPU("TDM")),
372 DAILINK_COMP_ARRAY(COMP_CODEC(NULL, "i2s-hifi")),
373 DAILINK_COMP_ARRAY(COMP_EMPTY()));
374
375static int mt8183_da7219_max98357_hdmi_init(struct snd_soc_pcm_runtime *rtd)
376{
377 struct mt8183_da7219_max98357_priv *priv =
378 snd_soc_card_get_drvdata(card: rtd->card);
379 int ret;
380
381 ret = snd_soc_card_jack_new(card: rtd->card, id: "HDMI Jack", type: SND_JACK_AVOUT,
382 jack: &priv->hdmi_jack);
383 if (ret)
384 return ret;
385
386 return snd_soc_component_set_jack(snd_soc_rtd_to_codec(rtd, 0)->component,
387 jack: &priv->hdmi_jack, NULL);
388}
389
390static int mt8183_bt_init(struct snd_soc_pcm_runtime *rtd)
391{
392 struct snd_soc_component *cmpnt_afe =
393 snd_soc_rtdcom_lookup(rtd, AFE_PCM_NAME);
394 struct mtk_base_afe *afe = snd_soc_component_get_drvdata(c: cmpnt_afe);
395 int ret;
396
397 ret = mt8183_dai_i2s_set_share(afe, main_i2s_name: "I2S5", secondary_i2s_name: "I2S0");
398 if (ret) {
399 dev_err(rtd->dev, "Failed to set up shared clocks\n");
400 return ret;
401 }
402 return 0;
403}
404
405static int mt8183_da7219_init(struct snd_soc_pcm_runtime *rtd)
406{
407 struct snd_soc_component *cmpnt_afe =
408 snd_soc_rtdcom_lookup(rtd, AFE_PCM_NAME);
409 struct mtk_base_afe *afe = snd_soc_component_get_drvdata(c: cmpnt_afe);
410 int ret;
411
412 ret = mt8183_dai_i2s_set_share(afe, main_i2s_name: "I2S2", secondary_i2s_name: "I2S3");
413 if (ret) {
414 dev_err(rtd->dev, "Failed to set up shared clocks\n");
415 return ret;
416 }
417 return 0;
418}
419
420static struct snd_soc_dai_link mt8183_da7219_dai_links[] = {
421 /* FE */
422 {
423 .name = "Playback_1",
424 .stream_name = "Playback_1",
425 .trigger = {SND_SOC_DPCM_TRIGGER_PRE,
426 SND_SOC_DPCM_TRIGGER_PRE},
427 .dynamic = 1,
428 .playback_only = 1,
429 .ops = &mt8183_da7219_max98357_ops,
430 SND_SOC_DAILINK_REG(playback1),
431 },
432 {
433 .name = "Playback_2",
434 .stream_name = "Playback_2",
435 .trigger = {SND_SOC_DPCM_TRIGGER_PRE,
436 SND_SOC_DPCM_TRIGGER_PRE},
437 .dynamic = 1,
438 .playback_only = 1,
439 .ops = &mt8183_da7219_max98357_bt_sco_ops,
440 SND_SOC_DAILINK_REG(playback2),
441 },
442 {
443 .name = "Playback_3",
444 .stream_name = "Playback_3",
445 .trigger = {SND_SOC_DPCM_TRIGGER_PRE,
446 SND_SOC_DPCM_TRIGGER_PRE},
447 .dynamic = 1,
448 .playback_only = 1,
449 SND_SOC_DAILINK_REG(playback3),
450 },
451 {
452 .name = "Capture_1",
453 .stream_name = "Capture_1",
454 .trigger = {SND_SOC_DPCM_TRIGGER_PRE,
455 SND_SOC_DPCM_TRIGGER_PRE},
456 .dynamic = 1,
457 .capture_only = 1,
458 .ops = &mt8183_da7219_max98357_bt_sco_ops,
459 SND_SOC_DAILINK_REG(capture1),
460 },
461 {
462 .name = "Capture_2",
463 .stream_name = "Capture_2",
464 .trigger = {SND_SOC_DPCM_TRIGGER_PRE,
465 SND_SOC_DPCM_TRIGGER_PRE},
466 .dynamic = 1,
467 .capture_only = 1,
468 SND_SOC_DAILINK_REG(capture2),
469 },
470 {
471 .name = "Capture_3",
472 .stream_name = "Capture_3",
473 .trigger = {SND_SOC_DPCM_TRIGGER_PRE,
474 SND_SOC_DPCM_TRIGGER_PRE},
475 .dynamic = 1,
476 .capture_only = 1,
477 .ops = &mt8183_da7219_max98357_ops,
478 SND_SOC_DAILINK_REG(capture3),
479 },
480 {
481 .name = "Capture_Mono_1",
482 .stream_name = "Capture_Mono_1",
483 .trigger = {SND_SOC_DPCM_TRIGGER_PRE,
484 SND_SOC_DPCM_TRIGGER_PRE},
485 .dynamic = 1,
486 .capture_only = 1,
487 SND_SOC_DAILINK_REG(capture_mono),
488 },
489 {
490 .name = "Playback_HDMI",
491 .stream_name = "Playback_HDMI",
492 .trigger = {SND_SOC_DPCM_TRIGGER_PRE,
493 SND_SOC_DPCM_TRIGGER_PRE},
494 .dynamic = 1,
495 .playback_only = 1,
496 SND_SOC_DAILINK_REG(playback_hdmi),
497 },
498 /* BE */
499 {
500 .name = "Primary Codec",
501 .no_pcm = 1,
502 .ignore_suspend = 1,
503 SND_SOC_DAILINK_REG(primary_codec),
504 },
505 {
506 .name = "PCM 1",
507 .no_pcm = 1,
508 .ignore_suspend = 1,
509 SND_SOC_DAILINK_REG(pcm1),
510 },
511 {
512 .name = "PCM 2",
513 .no_pcm = 1,
514 .ignore_suspend = 1,
515 SND_SOC_DAILINK_REG(pcm2),
516 },
517 {
518 .name = "I2S0",
519 .no_pcm = 1,
520 .capture_only = 1,
521 .ignore_suspend = 1,
522 .be_hw_params_fixup = mt8183_i2s_hw_params_fixup,
523 .ops = &mt8183_mt6358_i2s_ops,
524 SND_SOC_DAILINK_REG(i2s0),
525 },
526 {
527 .name = "I2S1",
528 .no_pcm = 1,
529 .playback_only = 1,
530 .ignore_suspend = 1,
531 .be_hw_params_fixup = mt8183_i2s_hw_params_fixup,
532 .ops = &mt8183_mt6358_i2s_ops,
533 SND_SOC_DAILINK_REG(i2s1),
534 },
535 {
536 .name = "I2S2",
537 .no_pcm = 1,
538 .capture_only = 1,
539 .ignore_suspend = 1,
540 .be_hw_params_fixup = mt8183_i2s_hw_params_fixup,
541 .ops = &mt8183_da7219_i2s_ops,
542 .init = &mt8183_da7219_init,
543 SND_SOC_DAILINK_REG(i2s2),
544 },
545 {
546 .name = "I2S3",
547 .no_pcm = 1,
548 .playback_only = 1,
549 .ignore_suspend = 1,
550 },
551 {
552 .name = "I2S5",
553 .no_pcm = 1,
554 .playback_only = 1,
555 .ignore_suspend = 1,
556 .be_hw_params_fixup = mt8183_i2s_hw_params_fixup,
557 .ops = &mt8183_mt6358_i2s_ops,
558 .init = &mt8183_bt_init,
559 SND_SOC_DAILINK_REG(i2s5),
560 },
561 {
562 .name = "TDM",
563 .no_pcm = 1,
564 .dai_fmt = SND_SOC_DAIFMT_I2S |
565 SND_SOC_DAIFMT_IB_IF |
566 SND_SOC_DAIFMT_CBP_CFP,
567 .playback_only = 1,
568 .ignore_suspend = 1,
569 .be_hw_params_fixup = mt8183_i2s_hw_params_fixup,
570 .ignore = 1,
571 .init = mt8183_da7219_max98357_hdmi_init,
572 SND_SOC_DAILINK_REG(tdm),
573 },
574};
575
576static int
577mt8183_da7219_max98357_headset_init(struct snd_soc_component *component)
578{
579 int ret;
580 struct mt8183_da7219_max98357_priv *priv =
581 snd_soc_card_get_drvdata(card: component->card);
582
583 /* Enable Headset and 4 Buttons Jack detection */
584 ret = snd_soc_card_jack_new_pins(card: component->card,
585 id: "Headset Jack",
586 type: SND_JACK_HEADSET |
587 SND_JACK_BTN_0 | SND_JACK_BTN_1 |
588 SND_JACK_BTN_2 | SND_JACK_BTN_3 |
589 SND_JACK_LINEOUT,
590 jack: &priv->headset_jack,
591 pins: mt8183_da7219_max98357_jack_pins,
592 ARRAY_SIZE(mt8183_da7219_max98357_jack_pins));
593 if (ret)
594 return ret;
595
596 snd_jack_set_key(
597 jack: priv->headset_jack.jack, type: SND_JACK_BTN_0, KEY_PLAYPAUSE);
598 snd_jack_set_key(
599 jack: priv->headset_jack.jack, type: SND_JACK_BTN_1, KEY_VOLUMEUP);
600 snd_jack_set_key(
601 jack: priv->headset_jack.jack, type: SND_JACK_BTN_2, KEY_VOLUMEDOWN);
602 snd_jack_set_key(
603 jack: priv->headset_jack.jack, type: SND_JACK_BTN_3, KEY_VOICECOMMAND);
604
605 snd_soc_component_set_jack(component, jack: &priv->headset_jack, NULL);
606
607 return 0;
608}
609
610static struct snd_soc_aux_dev mt8183_da7219_max98357_headset_dev = {
611 .dlc = COMP_EMPTY(),
612 .init = mt8183_da7219_max98357_headset_init,
613};
614
615static struct snd_soc_codec_conf mt6358_codec_conf[] = {
616 {
617 .dlc = COMP_CODEC_CONF("mt6358-sound"),
618 .name_prefix = "Mt6358",
619 },
620};
621
622static const struct snd_kcontrol_new mt8183_da7219_max98357_snd_controls[] = {
623 SOC_DAPM_PIN_SWITCH("Headphones"),
624 SOC_DAPM_PIN_SWITCH("Headset Mic"),
625 SOC_DAPM_PIN_SWITCH("Speakers"),
626 SOC_DAPM_PIN_SWITCH("Line Out"),
627};
628
629static const
630struct snd_soc_dapm_widget mt8183_da7219_max98357_dapm_widgets[] = {
631 SND_SOC_DAPM_HP("Headphones", NULL),
632 SND_SOC_DAPM_MIC("Headset Mic", NULL),
633 SND_SOC_DAPM_SPK("Speakers", NULL),
634 SND_SOC_DAPM_SPK("Line Out", NULL),
635 SND_SOC_DAPM_PINCTRL("TDM_OUT_PINCTRL",
636 "aud_tdm_out_on", "aud_tdm_out_off"),
637};
638
639static const struct snd_soc_dapm_route mt8183_da7219_max98357_dapm_routes[] = {
640 {"Speakers", NULL, "Speaker"},
641 {"I2S Playback", NULL, "TDM_OUT_PINCTRL"},
642};
643
644static struct snd_soc_card mt8183_da7219_max98357_card = {
645 .name = "mt8183_da7219_max98357",
646 .owner = THIS_MODULE,
647 .controls = mt8183_da7219_max98357_snd_controls,
648 .num_controls = ARRAY_SIZE(mt8183_da7219_max98357_snd_controls),
649 .dapm_widgets = mt8183_da7219_max98357_dapm_widgets,
650 .num_dapm_widgets = ARRAY_SIZE(mt8183_da7219_max98357_dapm_widgets),
651 .dapm_routes = mt8183_da7219_max98357_dapm_routes,
652 .num_dapm_routes = ARRAY_SIZE(mt8183_da7219_max98357_dapm_routes),
653 .dai_link = mt8183_da7219_dai_links,
654 .num_links = ARRAY_SIZE(mt8183_da7219_dai_links),
655 .aux_dev = &mt8183_da7219_max98357_headset_dev,
656 .num_aux_devs = 1,
657 .codec_conf = mt6358_codec_conf,
658 .num_configs = ARRAY_SIZE(mt6358_codec_conf),
659};
660
661static struct snd_soc_codec_conf mt8183_da7219_rt1015_codec_conf[] = {
662 {
663 .dlc = COMP_CODEC_CONF("mt6358-sound"),
664 .name_prefix = "Mt6358",
665 },
666 {
667 .dlc = COMP_CODEC_CONF(RT1015_DEV0_NAME),
668 .name_prefix = "Left",
669 },
670 {
671 .dlc = COMP_CODEC_CONF(RT1015_DEV1_NAME),
672 .name_prefix = "Right",
673 },
674};
675
676static const struct snd_kcontrol_new mt8183_da7219_rt1015_snd_controls[] = {
677 SOC_DAPM_PIN_SWITCH("Headphones"),
678 SOC_DAPM_PIN_SWITCH("Headset Mic"),
679 SOC_DAPM_PIN_SWITCH("Left Spk"),
680 SOC_DAPM_PIN_SWITCH("Right Spk"),
681 SOC_DAPM_PIN_SWITCH("Line Out"),
682};
683
684static const
685struct snd_soc_dapm_widget mt8183_da7219_rt1015_dapm_widgets[] = {
686 SND_SOC_DAPM_HP("Headphones", NULL),
687 SND_SOC_DAPM_MIC("Headset Mic", NULL),
688 SND_SOC_DAPM_SPK("Left Spk", NULL),
689 SND_SOC_DAPM_SPK("Right Spk", NULL),
690 SND_SOC_DAPM_LINE("Line Out", NULL),
691 SND_SOC_DAPM_PINCTRL("TDM_OUT_PINCTRL",
692 "aud_tdm_out_on", "aud_tdm_out_off"),
693};
694
695static const struct snd_soc_dapm_route mt8183_da7219_rt1015_dapm_routes[] = {
696 {"Left Spk", NULL, "Left SPO"},
697 {"Right Spk", NULL, "Right SPO"},
698 {"I2S Playback", NULL, "TDM_OUT_PINCTRL"},
699};
700
701static struct snd_soc_card mt8183_da7219_rt1015_card = {
702 .name = "mt8183_da7219_rt1015",
703 .owner = THIS_MODULE,
704 .controls = mt8183_da7219_rt1015_snd_controls,
705 .num_controls = ARRAY_SIZE(mt8183_da7219_rt1015_snd_controls),
706 .dapm_widgets = mt8183_da7219_rt1015_dapm_widgets,
707 .num_dapm_widgets = ARRAY_SIZE(mt8183_da7219_rt1015_dapm_widgets),
708 .dapm_routes = mt8183_da7219_rt1015_dapm_routes,
709 .num_dapm_routes = ARRAY_SIZE(mt8183_da7219_rt1015_dapm_routes),
710 .dai_link = mt8183_da7219_dai_links,
711 .num_links = ARRAY_SIZE(mt8183_da7219_dai_links),
712 .aux_dev = &mt8183_da7219_max98357_headset_dev,
713 .num_aux_devs = 1,
714 .codec_conf = mt8183_da7219_rt1015_codec_conf,
715 .num_configs = ARRAY_SIZE(mt8183_da7219_rt1015_codec_conf),
716};
717
718static struct snd_soc_card mt8183_da7219_rt1015p_card = {
719 .name = "mt8183_da7219_rt1015p",
720 .owner = THIS_MODULE,
721 .controls = mt8183_da7219_max98357_snd_controls,
722 .num_controls = ARRAY_SIZE(mt8183_da7219_max98357_snd_controls),
723 .dapm_widgets = mt8183_da7219_max98357_dapm_widgets,
724 .num_dapm_widgets = ARRAY_SIZE(mt8183_da7219_max98357_dapm_widgets),
725 .dapm_routes = mt8183_da7219_max98357_dapm_routes,
726 .num_dapm_routes = ARRAY_SIZE(mt8183_da7219_max98357_dapm_routes),
727 .dai_link = mt8183_da7219_dai_links,
728 .num_links = ARRAY_SIZE(mt8183_da7219_dai_links),
729 .aux_dev = &mt8183_da7219_max98357_headset_dev,
730 .num_aux_devs = 1,
731 .codec_conf = mt6358_codec_conf,
732 .num_configs = ARRAY_SIZE(mt6358_codec_conf),
733};
734
735static int mt8183_da7219_max98357_dev_probe(struct platform_device *pdev)
736{
737 struct snd_soc_card *card;
738 struct device_node *platform_node, *hdmi_codec;
739 struct snd_soc_dai_link *dai_link;
740 struct mt8183_da7219_max98357_priv *priv;
741 struct pinctrl *pinctrl;
742 int ret, i;
743
744 platform_node = of_parse_phandle(np: pdev->dev.of_node,
745 phandle_name: "mediatek,platform", index: 0);
746 if (!platform_node) {
747 dev_err(&pdev->dev, "Property 'platform' missing or invalid\n");
748 return -EINVAL;
749 }
750
751 card = (struct snd_soc_card *)of_device_get_match_data(dev: &pdev->dev);
752 if (!card) {
753 ret = -EINVAL;
754 goto put_platform_node;
755 }
756
757 card->dev = &pdev->dev;
758
759 hdmi_codec = of_parse_phandle(np: pdev->dev.of_node,
760 phandle_name: "mediatek,hdmi-codec", index: 0);
761
762 for_each_card_prelinks(card, i, dai_link) {
763 if (strcmp(dai_link->name, "I2S3") == 0) {
764 if (card == &mt8183_da7219_max98357_card) {
765 dai_link->be_hw_params_fixup =
766 mt8183_i2s_hw_params_fixup;
767 dai_link->ops = &mt8183_da7219_i2s_ops;
768 dai_link->cpus = i2s3_max98357a_cpus;
769 dai_link->num_cpus =
770 ARRAY_SIZE(i2s3_max98357a_cpus);
771 dai_link->codecs = i2s3_max98357a_codecs;
772 dai_link->num_codecs =
773 ARRAY_SIZE(i2s3_max98357a_codecs);
774 dai_link->platforms = i2s3_max98357a_platforms;
775 dai_link->num_platforms =
776 ARRAY_SIZE(i2s3_max98357a_platforms);
777 } else if (card == &mt8183_da7219_rt1015_card) {
778 dai_link->be_hw_params_fixup =
779 mt8183_rt1015_i2s_hw_params_fixup;
780 dai_link->ops = &mt8183_da7219_rt1015_i2s_ops;
781 dai_link->cpus = i2s3_rt1015_cpus;
782 dai_link->num_cpus =
783 ARRAY_SIZE(i2s3_rt1015_cpus);
784 dai_link->codecs = i2s3_rt1015_codecs;
785 dai_link->num_codecs =
786 ARRAY_SIZE(i2s3_rt1015_codecs);
787 dai_link->platforms = i2s3_rt1015_platforms;
788 dai_link->num_platforms =
789 ARRAY_SIZE(i2s3_rt1015_platforms);
790 } else if (card == &mt8183_da7219_rt1015p_card) {
791 dai_link->be_hw_params_fixup =
792 mt8183_rt1015_i2s_hw_params_fixup;
793 dai_link->ops = &mt8183_da7219_i2s_ops;
794 dai_link->cpus = i2s3_rt1015p_cpus;
795 dai_link->num_cpus =
796 ARRAY_SIZE(i2s3_rt1015p_cpus);
797 dai_link->codecs = i2s3_rt1015p_codecs;
798 dai_link->num_codecs =
799 ARRAY_SIZE(i2s3_rt1015p_codecs);
800 dai_link->platforms = i2s3_rt1015p_platforms;
801 dai_link->num_platforms =
802 ARRAY_SIZE(i2s3_rt1015p_platforms);
803 }
804 }
805
806 if (hdmi_codec && strcmp(dai_link->name, "TDM") == 0) {
807 dai_link->codecs->of_node = hdmi_codec;
808 dai_link->ignore = 0;
809 }
810
811 if (!dai_link->platforms->name)
812 dai_link->platforms->of_node = platform_node;
813 }
814
815 mt8183_da7219_max98357_headset_dev.dlc.of_node =
816 of_parse_phandle(np: pdev->dev.of_node,
817 phandle_name: "mediatek,headset-codec", index: 0);
818 if (!mt8183_da7219_max98357_headset_dev.dlc.of_node) {
819 dev_err(&pdev->dev,
820 "Property 'mediatek,headset-codec' missing/invalid\n");
821 ret = -EINVAL;
822 goto put_hdmi_codec;
823 }
824
825 priv = devm_kzalloc(dev: &pdev->dev, size: sizeof(*priv), GFP_KERNEL);
826 if (!priv) {
827 ret = -ENOMEM;
828 goto put_hdmi_codec;
829 }
830
831 snd_soc_card_set_drvdata(card, data: priv);
832
833 pinctrl = devm_pinctrl_get_select(dev: &pdev->dev, PINCTRL_STATE_DEFAULT);
834 if (IS_ERR(ptr: pinctrl)) {
835 ret = PTR_ERR(ptr: pinctrl);
836 dev_err(&pdev->dev, "%s failed to select default state %d\n",
837 __func__, ret);
838 goto put_hdmi_codec;
839 }
840
841 ret = devm_snd_soc_register_card(dev: &pdev->dev, card);
842
843
844put_hdmi_codec:
845 of_node_put(node: hdmi_codec);
846put_platform_node:
847 of_node_put(node: platform_node);
848 return ret;
849}
850
851#ifdef CONFIG_OF
852static const struct of_device_id mt8183_da7219_max98357_dt_match[] = {
853 {
854 .compatible = "mediatek,mt8183_da7219_max98357",
855 .data = &mt8183_da7219_max98357_card,
856 },
857 {
858 .compatible = "mediatek,mt8183_da7219_rt1015",
859 .data = &mt8183_da7219_rt1015_card,
860 },
861 {
862 .compatible = "mediatek,mt8183_da7219_rt1015p",
863 .data = &mt8183_da7219_rt1015p_card,
864 },
865 {}
866};
867MODULE_DEVICE_TABLE(of, mt8183_da7219_max98357_dt_match);
868#endif
869
870static struct platform_driver mt8183_da7219_max98357_driver = {
871 .driver = {
872 .name = "mt8183_da7219",
873#ifdef CONFIG_OF
874 .of_match_table = mt8183_da7219_max98357_dt_match,
875#endif
876 .pm = &snd_soc_pm_ops,
877 },
878 .probe = mt8183_da7219_max98357_dev_probe,
879};
880
881module_platform_driver(mt8183_da7219_max98357_driver);
882
883/* Module information */
884MODULE_DESCRIPTION("MT8183-DA7219-MAX98357 ALSA SoC machine driver");
885MODULE_AUTHOR("Shunli Wang <shunli.wang@mediatek.com>");
886MODULE_LICENSE("GPL v2");
887MODULE_ALIAS("mt8183_da7219_max98357 soc card");
888

source code of linux/sound/soc/mediatek/mt8183/mt8183-da7219-max98357.c