]> asedeno.scripts.mit.edu Git - linux.git/blob - sound/soc/mediatek/mt8183/mt8183-mt6358-ts3a227-max98357.c
ASoC: mediatek: mt8183: tdm hw support tdm out and 8ch i2s out
[linux.git] / sound / soc / mediatek / mt8183 / mt8183-mt6358-ts3a227-max98357.c
1 // SPDX-License-Identifier: GPL-2.0
2 //
3 // mt8183-mt6358.c  --
4 //      MT8183-MT6358-TS3A227-MAX98357 ALSA SoC machine driver
5 //
6 // Copyright (c) 2018 MediaTek Inc.
7 // Author: Shunli Wang <shunli.wang@mediatek.com>
8
9 #include <linux/module.h>
10 #include <sound/pcm_params.h>
11 #include <sound/soc.h>
12 #include <sound/jack.h>
13 #include <linux/pinctrl/consumer.h>
14
15 #include "mt8183-afe-common.h"
16 #include "../../codecs/ts3a227e.h"
17
18 static struct snd_soc_jack headset_jack;
19
20 static int mt8183_mt6358_i2s_hw_params(struct snd_pcm_substream *substream,
21                                        struct snd_pcm_hw_params *params)
22 {
23         struct snd_soc_pcm_runtime *rtd = substream->private_data;
24         unsigned int rate = params_rate(params);
25         unsigned int mclk_fs_ratio = 128;
26         unsigned int mclk_fs = rate * mclk_fs_ratio;
27
28         return snd_soc_dai_set_sysclk(rtd->cpu_dai,
29                                       0, mclk_fs, SND_SOC_CLOCK_OUT);
30 }
31
32 static const struct snd_soc_ops mt8183_mt6358_i2s_ops = {
33         .hw_params = mt8183_mt6358_i2s_hw_params,
34 };
35
36 static int mt8183_i2s_hw_params_fixup(struct snd_soc_pcm_runtime *rtd,
37                                       struct snd_pcm_hw_params *params)
38 {
39         dev_dbg(rtd->dev, "%s(), fix format to 32bit\n", __func__);
40
41         /* fix BE i2s format to 32bit, clean param mask first */
42         snd_mask_reset_range(hw_param_mask(params, SNDRV_PCM_HW_PARAM_FORMAT),
43                              0, SNDRV_PCM_FORMAT_LAST);
44
45         params_set_format(params, SNDRV_PCM_FORMAT_S32_LE);
46         return 0;
47 }
48
49 enum PINCTRL_PIN_STATE {
50         PIN_STATE_DEFAULT = 0,
51         PIN_TDM_OUT_ON,
52         PIN_TDM_OUT_OFF,
53         PIN_STATE_MAX
54 };
55
56 static const char * const mt8183_pin_str[PIN_STATE_MAX] = {
57         "default", "aud_tdm_out_on", "aud_tdm_out_off",
58 };
59
60 struct mt8183_mt6358_ts3a227_max98357_priv {
61         struct pinctrl *pinctrl;
62         struct pinctrl_state *pin_states[PIN_STATE_MAX];
63 };
64
65 static int
66 mt8183_mt6358_ts3a227_max98357_bt_sco_startup(
67         struct snd_pcm_substream *substream)
68 {
69         static const unsigned int rates[] = {
70                 8000, 16000
71         };
72         static const struct snd_pcm_hw_constraint_list constraints_rates = {
73                 .count = ARRAY_SIZE(rates),
74                 .list  = rates,
75                 .mask = 0,
76         };
77         static const unsigned int channels[] = {
78                 1,
79         };
80         static const struct snd_pcm_hw_constraint_list constraints_channels = {
81                 .count = ARRAY_SIZE(channels),
82                 .list = channels,
83                 .mask = 0,
84         };
85
86         struct snd_pcm_runtime *runtime = substream->runtime;
87
88         snd_pcm_hw_constraint_list(runtime, 0,
89                         SNDRV_PCM_HW_PARAM_RATE, &constraints_rates);
90         runtime->hw.channels_max = 1;
91         snd_pcm_hw_constraint_list(runtime, 0,
92                         SNDRV_PCM_HW_PARAM_CHANNELS,
93                         &constraints_channels);
94
95         runtime->hw.formats = SNDRV_PCM_FMTBIT_S16_LE;
96         snd_pcm_hw_constraint_msbits(runtime, 0, 16, 16);
97
98         return 0;
99 }
100
101 static const struct snd_soc_ops mt8183_mt6358_ts3a227_max98357_bt_sco_ops = {
102         .startup = mt8183_mt6358_ts3a227_max98357_bt_sco_startup,
103 };
104
105 /* FE */
106 SND_SOC_DAILINK_DEFS(playback1,
107         DAILINK_COMP_ARRAY(COMP_CPU("DL1")),
108         DAILINK_COMP_ARRAY(COMP_DUMMY()),
109         DAILINK_COMP_ARRAY(COMP_EMPTY()));
110
111 SND_SOC_DAILINK_DEFS(playback2,
112         DAILINK_COMP_ARRAY(COMP_CPU("DL2")),
113         DAILINK_COMP_ARRAY(COMP_DUMMY()),
114         DAILINK_COMP_ARRAY(COMP_EMPTY()));
115
116 SND_SOC_DAILINK_DEFS(playback3,
117         DAILINK_COMP_ARRAY(COMP_CPU("DL3")),
118         DAILINK_COMP_ARRAY(COMP_DUMMY()),
119         DAILINK_COMP_ARRAY(COMP_EMPTY()));
120
121 SND_SOC_DAILINK_DEFS(capture1,
122         DAILINK_COMP_ARRAY(COMP_CPU("UL1")),
123         DAILINK_COMP_ARRAY(COMP_DUMMY()),
124         DAILINK_COMP_ARRAY(COMP_EMPTY()));
125
126 SND_SOC_DAILINK_DEFS(capture2,
127         DAILINK_COMP_ARRAY(COMP_CPU("UL2")),
128         DAILINK_COMP_ARRAY(COMP_DUMMY()),
129         DAILINK_COMP_ARRAY(COMP_EMPTY()));
130
131 SND_SOC_DAILINK_DEFS(capture3,
132         DAILINK_COMP_ARRAY(COMP_CPU("UL3")),
133         DAILINK_COMP_ARRAY(COMP_DUMMY()),
134         DAILINK_COMP_ARRAY(COMP_EMPTY()));
135
136 SND_SOC_DAILINK_DEFS(capture_mono,
137         DAILINK_COMP_ARRAY(COMP_CPU("UL_MONO_1")),
138         DAILINK_COMP_ARRAY(COMP_DUMMY()),
139         DAILINK_COMP_ARRAY(COMP_EMPTY()));
140
141 SND_SOC_DAILINK_DEFS(playback_hdmi,
142         DAILINK_COMP_ARRAY(COMP_CPU("HDMI")),
143         DAILINK_COMP_ARRAY(COMP_DUMMY()),
144         DAILINK_COMP_ARRAY(COMP_EMPTY()));
145
146 /* BE */
147 SND_SOC_DAILINK_DEFS(primary_codec,
148         DAILINK_COMP_ARRAY(COMP_CPU("ADDA")),
149         DAILINK_COMP_ARRAY(COMP_CODEC("mt6358-sound", "mt6358-snd-codec-aif1")),
150         DAILINK_COMP_ARRAY(COMP_EMPTY()));
151
152 SND_SOC_DAILINK_DEFS(pcm1,
153         DAILINK_COMP_ARRAY(COMP_CPU("PCM 1")),
154         DAILINK_COMP_ARRAY(COMP_DUMMY()),
155         DAILINK_COMP_ARRAY(COMP_EMPTY()));
156
157 SND_SOC_DAILINK_DEFS(pcm2,
158         DAILINK_COMP_ARRAY(COMP_CPU("PCM 2")),
159         DAILINK_COMP_ARRAY(COMP_DUMMY()),
160         DAILINK_COMP_ARRAY(COMP_EMPTY()));
161
162 SND_SOC_DAILINK_DEFS(i2s0,
163         DAILINK_COMP_ARRAY(COMP_CPU("I2S0")),
164         DAILINK_COMP_ARRAY(COMP_CODEC("bt-sco", "bt-sco-pcm")),
165         DAILINK_COMP_ARRAY(COMP_EMPTY()));
166
167 SND_SOC_DAILINK_DEFS(i2s1,
168         DAILINK_COMP_ARRAY(COMP_CPU("I2S1")),
169         DAILINK_COMP_ARRAY(COMP_DUMMY()),
170         DAILINK_COMP_ARRAY(COMP_EMPTY()));
171
172 SND_SOC_DAILINK_DEFS(i2s2,
173         DAILINK_COMP_ARRAY(COMP_CPU("I2S2")),
174         DAILINK_COMP_ARRAY(COMP_DUMMY()),
175         DAILINK_COMP_ARRAY(COMP_EMPTY()));
176
177 SND_SOC_DAILINK_DEFS(i2s3,
178         DAILINK_COMP_ARRAY(COMP_CPU("I2S3")),
179         DAILINK_COMP_ARRAY(COMP_CODEC("max98357a", "HiFi")),
180         DAILINK_COMP_ARRAY(COMP_EMPTY()));
181
182 SND_SOC_DAILINK_DEFS(i2s5,
183         DAILINK_COMP_ARRAY(COMP_CPU("I2S5")),
184         DAILINK_COMP_ARRAY(COMP_CODEC("bt-sco", "bt-sco-pcm")),
185         DAILINK_COMP_ARRAY(COMP_EMPTY()));
186
187 SND_SOC_DAILINK_DEFS(tdm,
188         DAILINK_COMP_ARRAY(COMP_CPU("TDM")),
189         DAILINK_COMP_ARRAY(COMP_DUMMY()),
190         DAILINK_COMP_ARRAY(COMP_EMPTY()));
191
192 static int mt8183_mt6358_tdm_startup(struct snd_pcm_substream *substream)
193 {
194         struct snd_soc_pcm_runtime *rtd = substream->private_data;
195         struct mt8183_mt6358_ts3a227_max98357_priv *priv =
196                 snd_soc_card_get_drvdata(rtd->card);
197         int ret;
198
199         if (IS_ERR(priv->pin_states[PIN_TDM_OUT_ON]))
200                 return PTR_ERR(priv->pin_states[PIN_TDM_OUT_ON]);
201
202         ret = pinctrl_select_state(priv->pinctrl,
203                                    priv->pin_states[PIN_TDM_OUT_ON]);
204         if (ret)
205                 dev_err(rtd->card->dev, "%s failed to select state %d\n",
206                         __func__, ret);
207
208         return ret;
209 }
210
211 static void mt8183_mt6358_tdm_shutdown(struct snd_pcm_substream *substream)
212 {
213         struct snd_soc_pcm_runtime *rtd = substream->private_data;
214         struct mt8183_mt6358_ts3a227_max98357_priv *priv =
215                 snd_soc_card_get_drvdata(rtd->card);
216         int ret;
217
218         if (IS_ERR(priv->pin_states[PIN_TDM_OUT_OFF]))
219                 return;
220
221         ret = pinctrl_select_state(priv->pinctrl,
222                                    priv->pin_states[PIN_TDM_OUT_OFF]);
223         if (ret)
224                 dev_err(rtd->card->dev, "%s failed to select state %d\n",
225                         __func__, ret);
226 }
227
228 static struct snd_soc_ops mt8183_mt6358_tdm_ops = {
229         .startup = mt8183_mt6358_tdm_startup,
230         .shutdown = mt8183_mt6358_tdm_shutdown,
231 };
232
233 static struct snd_soc_dai_link
234 mt8183_mt6358_ts3a227_max98357_dai_links[] = {
235         /* FE */
236         {
237                 .name = "Playback_1",
238                 .stream_name = "Playback_1",
239                 .trigger = {SND_SOC_DPCM_TRIGGER_PRE,
240                             SND_SOC_DPCM_TRIGGER_PRE},
241                 .dynamic = 1,
242                 .dpcm_playback = 1,
243                 SND_SOC_DAILINK_REG(playback1),
244         },
245         {
246                 .name = "Playback_2",
247                 .stream_name = "Playback_2",
248                 .trigger = {SND_SOC_DPCM_TRIGGER_PRE,
249                             SND_SOC_DPCM_TRIGGER_PRE},
250                 .dynamic = 1,
251                 .dpcm_playback = 1,
252                 .ops = &mt8183_mt6358_ts3a227_max98357_bt_sco_ops,
253                 SND_SOC_DAILINK_REG(playback2),
254         },
255         {
256                 .name = "Playback_3",
257                 .stream_name = "Playback_3",
258                 .trigger = {SND_SOC_DPCM_TRIGGER_PRE,
259                             SND_SOC_DPCM_TRIGGER_PRE},
260                 .dynamic = 1,
261                 .dpcm_playback = 1,
262                 SND_SOC_DAILINK_REG(playback3),
263         },
264         {
265                 .name = "Capture_1",
266                 .stream_name = "Capture_1",
267                 .trigger = {SND_SOC_DPCM_TRIGGER_PRE,
268                             SND_SOC_DPCM_TRIGGER_PRE},
269                 .dynamic = 1,
270                 .dpcm_capture = 1,
271                 .ops = &mt8183_mt6358_ts3a227_max98357_bt_sco_ops,
272                 SND_SOC_DAILINK_REG(capture1),
273         },
274         {
275                 .name = "Capture_2",
276                 .stream_name = "Capture_2",
277                 .trigger = {SND_SOC_DPCM_TRIGGER_PRE,
278                             SND_SOC_DPCM_TRIGGER_PRE},
279                 .dynamic = 1,
280                 .dpcm_capture = 1,
281                 SND_SOC_DAILINK_REG(capture2),
282         },
283         {
284                 .name = "Capture_3",
285                 .stream_name = "Capture_3",
286                 .trigger = {SND_SOC_DPCM_TRIGGER_PRE,
287                             SND_SOC_DPCM_TRIGGER_PRE},
288                 .dynamic = 1,
289                 .dpcm_capture = 1,
290                 SND_SOC_DAILINK_REG(capture3),
291         },
292         {
293                 .name = "Capture_Mono_1",
294                 .stream_name = "Capture_Mono_1",
295                 .trigger = {SND_SOC_DPCM_TRIGGER_PRE,
296                             SND_SOC_DPCM_TRIGGER_PRE},
297                 .dynamic = 1,
298                 .dpcm_capture = 1,
299                 SND_SOC_DAILINK_REG(capture_mono),
300         },
301         {
302                 .name = "Playback_HDMI",
303                 .stream_name = "Playback_HDMI",
304                 .trigger = {SND_SOC_DPCM_TRIGGER_PRE,
305                             SND_SOC_DPCM_TRIGGER_PRE},
306                 .dynamic = 1,
307                 .dpcm_playback = 1,
308                 SND_SOC_DAILINK_REG(playback_hdmi),
309         },
310         /* BE */
311         {
312                 .name = "Primary Codec",
313                 .no_pcm = 1,
314                 .dpcm_playback = 1,
315                 .dpcm_capture = 1,
316                 .ignore_suspend = 1,
317                 SND_SOC_DAILINK_REG(primary_codec),
318         },
319         {
320                 .name = "PCM 1",
321                 .no_pcm = 1,
322                 .dpcm_playback = 1,
323                 .dpcm_capture = 1,
324                 .ignore_suspend = 1,
325                 SND_SOC_DAILINK_REG(pcm1),
326         },
327         {
328                 .name = "PCM 2",
329                 .no_pcm = 1,
330                 .dpcm_playback = 1,
331                 .dpcm_capture = 1,
332                 .ignore_suspend = 1,
333                 SND_SOC_DAILINK_REG(pcm2),
334         },
335         {
336                 .name = "I2S0",
337                 .no_pcm = 1,
338                 .dpcm_capture = 1,
339                 .ignore_suspend = 1,
340                 .be_hw_params_fixup = mt8183_i2s_hw_params_fixup,
341                 .ops = &mt8183_mt6358_i2s_ops,
342                 SND_SOC_DAILINK_REG(i2s0),
343         },
344         {
345                 .name = "I2S1",
346                 .no_pcm = 1,
347                 .dpcm_playback = 1,
348                 .ignore_suspend = 1,
349                 .be_hw_params_fixup = mt8183_i2s_hw_params_fixup,
350                 .ops = &mt8183_mt6358_i2s_ops,
351                 SND_SOC_DAILINK_REG(i2s1),
352         },
353         {
354                 .name = "I2S2",
355                 .no_pcm = 1,
356                 .dpcm_capture = 1,
357                 .ignore_suspend = 1,
358                 .be_hw_params_fixup = mt8183_i2s_hw_params_fixup,
359                 .ops = &mt8183_mt6358_i2s_ops,
360                 SND_SOC_DAILINK_REG(i2s2),
361         },
362         {
363                 .name = "I2S3",
364                 .no_pcm = 1,
365                 .dpcm_playback = 1,
366                 .ignore_suspend = 1,
367                 .be_hw_params_fixup = mt8183_i2s_hw_params_fixup,
368                 .ops = &mt8183_mt6358_i2s_ops,
369                 SND_SOC_DAILINK_REG(i2s3),
370         },
371         {
372                 .name = "I2S5",
373                 .no_pcm = 1,
374                 .dpcm_playback = 1,
375                 .ignore_suspend = 1,
376                 .be_hw_params_fixup = mt8183_i2s_hw_params_fixup,
377                 .ops = &mt8183_mt6358_i2s_ops,
378                 SND_SOC_DAILINK_REG(i2s5),
379         },
380         {
381                 .name = "TDM",
382                 .no_pcm = 1,
383                 .dai_fmt = SND_SOC_DAIFMT_I2S |
384                            SND_SOC_DAIFMT_IB_IF |
385                            SND_SOC_DAIFMT_CBM_CFM,
386                 .dpcm_playback = 1,
387                 .ignore_suspend = 1,
388                 .be_hw_params_fixup = mt8183_i2s_hw_params_fixup,
389                 .ops = &mt8183_mt6358_tdm_ops,
390                 SND_SOC_DAILINK_REG(tdm),
391         },
392 };
393
394 static int
395 mt8183_mt6358_ts3a227_max98357_headset_init(struct snd_soc_component *cpnt);
396
397 static struct snd_soc_aux_dev mt8183_mt6358_ts3a227_max98357_headset_dev = {
398         .dlc = COMP_EMPTY(),
399         .init = mt8183_mt6358_ts3a227_max98357_headset_init,
400 };
401
402 static struct snd_soc_card mt8183_mt6358_ts3a227_max98357_card = {
403         .name = "mt8183_mt6358_ts3a227_max98357",
404         .owner = THIS_MODULE,
405         .dai_link = mt8183_mt6358_ts3a227_max98357_dai_links,
406         .num_links = ARRAY_SIZE(mt8183_mt6358_ts3a227_max98357_dai_links),
407 };
408
409 static int
410 mt8183_mt6358_ts3a227_max98357_headset_init(struct snd_soc_component *component)
411 {
412         int ret;
413
414         /* Enable Headset and 4 Buttons Jack detection */
415         ret = snd_soc_card_jack_new(&mt8183_mt6358_ts3a227_max98357_card,
416                                     "Headset Jack",
417                                     SND_JACK_HEADSET |
418                                     SND_JACK_BTN_0 | SND_JACK_BTN_1 |
419                                     SND_JACK_BTN_2 | SND_JACK_BTN_3,
420                                     &headset_jack,
421                                     NULL, 0);
422         if (ret)
423                 return ret;
424
425         ret = ts3a227e_enable_jack_detect(component, &headset_jack);
426
427         return ret;
428 }
429
430 static int
431 mt8183_mt6358_ts3a227_max98357_dev_probe(struct platform_device *pdev)
432 {
433         struct snd_soc_card *card = &mt8183_mt6358_ts3a227_max98357_card;
434         struct device_node *platform_node;
435         struct snd_soc_dai_link *dai_link;
436         struct mt8183_mt6358_ts3a227_max98357_priv *priv;
437         int ret;
438         int i;
439
440         card->dev = &pdev->dev;
441
442         platform_node = of_parse_phandle(pdev->dev.of_node,
443                                          "mediatek,platform", 0);
444         if (!platform_node) {
445                 dev_err(&pdev->dev, "Property 'platform' missing or invalid\n");
446                 return -EINVAL;
447         }
448
449         for_each_card_prelinks(card, i, dai_link) {
450                 if (dai_link->platforms->name)
451                         continue;
452                 dai_link->platforms->of_node = platform_node;
453         }
454
455         mt8183_mt6358_ts3a227_max98357_headset_dev.dlc.of_node =
456                 of_parse_phandle(pdev->dev.of_node,
457                                  "mediatek,headset-codec", 0);
458         if (mt8183_mt6358_ts3a227_max98357_headset_dev.dlc.of_node) {
459                 card->aux_dev = &mt8183_mt6358_ts3a227_max98357_headset_dev;
460                 card->num_aux_devs = 1;
461         }
462
463         priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL);
464         if (!priv)
465                 return -ENOMEM;
466
467         snd_soc_card_set_drvdata(card, priv);
468
469         priv->pinctrl = devm_pinctrl_get(&pdev->dev);
470         if (IS_ERR(priv->pinctrl)) {
471                 dev_err(&pdev->dev, "%s devm_pinctrl_get failed\n",
472                         __func__);
473                 return PTR_ERR(priv->pinctrl);
474         }
475
476         for (i = 0 ; i < PIN_STATE_MAX ; i++) {
477                 priv->pin_states[i] = pinctrl_lookup_state(priv->pinctrl,
478                                                            mt8183_pin_str[i]);
479                 if (IS_ERR(priv->pin_states[i])) {
480                         ret = PTR_ERR(priv->pin_states[i]);
481                         dev_info(&pdev->dev, "%s Can't find pin state %s %d\n",
482                                  __func__, mt8183_pin_str[i], ret);
483                 }
484         }
485
486         if (!IS_ERR(priv->pin_states[PIN_TDM_OUT_OFF])) {
487                 ret = pinctrl_select_state(priv->pinctrl,
488                                            priv->pin_states[PIN_TDM_OUT_OFF]);
489                 if (ret)
490                         dev_info(&pdev->dev,
491                                  "%s failed to select state %d\n",
492                                  __func__, ret);
493         }
494
495         if (!IS_ERR(priv->pin_states[PIN_STATE_DEFAULT])) {
496                 ret = pinctrl_select_state(priv->pinctrl,
497                                            priv->pin_states[PIN_STATE_DEFAULT]);
498                 if (ret)
499                         dev_info(&pdev->dev,
500                                  "%s failed to select state %d\n",
501                                  __func__, ret);
502         }
503
504         return devm_snd_soc_register_card(&pdev->dev, card);
505 }
506
507 #ifdef CONFIG_OF
508 static const struct of_device_id mt8183_mt6358_ts3a227_max98357_dt_match[] = {
509         {.compatible = "mediatek,mt8183_mt6358_ts3a227_max98357",},
510         {}
511 };
512 #endif
513
514 static struct platform_driver mt8183_mt6358_ts3a227_max98357_driver = {
515         .driver = {
516                 .name = "mt8183_mt6358_ts3a227_max98357",
517 #ifdef CONFIG_OF
518                 .of_match_table = mt8183_mt6358_ts3a227_max98357_dt_match,
519 #endif
520         },
521         .probe = mt8183_mt6358_ts3a227_max98357_dev_probe,
522 };
523
524 module_platform_driver(mt8183_mt6358_ts3a227_max98357_driver);
525
526 /* Module information */
527 MODULE_DESCRIPTION("MT8183-MT6358-TS3A227-MAX98357 ALSA SoC machine driver");
528 MODULE_AUTHOR("Shunli Wang <shunli.wang@mediatek.com>");
529 MODULE_LICENSE("GPL v2");
530 MODULE_ALIAS("mt8183_mt6358_ts3a227_max98357 soc card");
531