111c02690SShunli Wang // SPDX-License-Identifier: GPL-2.0
211c02690SShunli Wang //
311c02690SShunli Wang // mt8183-mt6358.c --
411c02690SShunli Wang // MT8183-MT6358-TS3A227-MAX98357 ALSA SoC machine driver
511c02690SShunli Wang //
611c02690SShunli Wang // Copyright (c) 2018 MediaTek Inc.
711c02690SShunli Wang // Author: Shunli Wang <shunli.wang@mediatek.com>
811c02690SShunli Wang
911c02690SShunli Wang #include <linux/module.h>
10f4fb4fefSTzung-Bi Shih #include <linux/of_device.h>
114dae01c2STzung-Bi Shih #include <linux/pinctrl/consumer.h>
124dae01c2STzung-Bi Shih #include <sound/jack.h>
1311c02690SShunli Wang #include <sound/pcm_params.h>
1411c02690SShunli Wang #include <sound/soc.h>
1511c02690SShunli Wang
16f4fb4fefSTzung-Bi Shih #include "../../codecs/rt1015.h"
1711c02690SShunli Wang #include "../../codecs/ts3a227e.h"
184583392aSNícolas F. R. A. Prado #include "../common/mtk-afe-platform-driver.h"
194dae01c2STzung-Bi Shih #include "mt8183-afe-common.h"
2011c02690SShunli Wang
21f4fb4fefSTzung-Bi Shih #define RT1015_CODEC_DAI "rt1015-aif"
22f4fb4fefSTzung-Bi Shih #define RT1015_DEV0_NAME "rt1015.6-0028"
23f4fb4fefSTzung-Bi Shih #define RT1015_DEV1_NAME "rt1015.6-0029"
24f4fb4fefSTzung-Bi Shih
2596ed7698STzung-Bi Shih enum PINCTRL_PIN_STATE {
2696ed7698STzung-Bi Shih PIN_STATE_DEFAULT = 0,
2796ed7698STzung-Bi Shih PIN_TDM_OUT_ON,
2896ed7698STzung-Bi Shih PIN_TDM_OUT_OFF,
292cc3cd5fSTzung-Bi Shih PIN_WOV,
3096ed7698STzung-Bi Shih PIN_STATE_MAX
3196ed7698STzung-Bi Shih };
3296ed7698STzung-Bi Shih
3396ed7698STzung-Bi Shih static const char * const mt8183_pin_str[PIN_STATE_MAX] = {
342cc3cd5fSTzung-Bi Shih "default", "aud_tdm_out_on", "aud_tdm_out_off", "wov",
3596ed7698STzung-Bi Shih };
3696ed7698STzung-Bi Shih
3796ed7698STzung-Bi Shih struct mt8183_mt6358_ts3a227_max98357_priv {
3896ed7698STzung-Bi Shih struct pinctrl *pinctrl;
3996ed7698STzung-Bi Shih struct pinctrl_state *pin_states[PIN_STATE_MAX];
4088abbf62STzung-Bi Shih struct snd_soc_jack headset_jack, hdmi_jack;
4196ed7698STzung-Bi Shih };
4296ed7698STzung-Bi Shih
mt8183_mt6358_i2s_hw_params(struct snd_pcm_substream * substream,struct snd_pcm_hw_params * params)4311c02690SShunli Wang static int mt8183_mt6358_i2s_hw_params(struct snd_pcm_substream *substream,
4411c02690SShunli Wang struct snd_pcm_hw_params *params)
4511c02690SShunli Wang {
460cd08b10SKuninori Morimoto struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
4711c02690SShunli Wang unsigned int rate = params_rate(params);
4811c02690SShunli Wang unsigned int mclk_fs_ratio = 128;
4911c02690SShunli Wang unsigned int mclk_fs = rate * mclk_fs_ratio;
5011c02690SShunli Wang
51c8ac8212SKuninori Morimoto return snd_soc_dai_set_sysclk(asoc_rtd_to_cpu(rtd, 0),
5211c02690SShunli Wang 0, mclk_fs, SND_SOC_CLOCK_OUT);
5311c02690SShunli Wang }
5411c02690SShunli Wang
5511c02690SShunli Wang static const struct snd_soc_ops mt8183_mt6358_i2s_ops = {
5611c02690SShunli Wang .hw_params = mt8183_mt6358_i2s_hw_params,
5711c02690SShunli Wang };
5811c02690SShunli Wang
59f4fb4fefSTzung-Bi Shih static int
mt8183_mt6358_rt1015_i2s_hw_params(struct snd_pcm_substream * substream,struct snd_pcm_hw_params * params)60f4fb4fefSTzung-Bi Shih mt8183_mt6358_rt1015_i2s_hw_params(struct snd_pcm_substream *substream,
61f4fb4fefSTzung-Bi Shih struct snd_pcm_hw_params *params)
62f4fb4fefSTzung-Bi Shih {
630cd08b10SKuninori Morimoto struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
64f4fb4fefSTzung-Bi Shih unsigned int rate = params_rate(params);
65f4fb4fefSTzung-Bi Shih unsigned int mclk_fs_ratio = 128;
66f4fb4fefSTzung-Bi Shih unsigned int mclk_fs = rate * mclk_fs_ratio;
67f4fb4fefSTzung-Bi Shih struct snd_soc_card *card = rtd->card;
68f4fb4fefSTzung-Bi Shih struct snd_soc_dai *codec_dai;
69f4fb4fefSTzung-Bi Shih int ret, i;
70f4fb4fefSTzung-Bi Shih
71f4fb4fefSTzung-Bi Shih for_each_rtd_codec_dais(rtd, i, codec_dai) {
72f4fb4fefSTzung-Bi Shih ret = snd_soc_dai_set_pll(codec_dai, 0, RT1015_PLL_S_BCLK,
73f4fb4fefSTzung-Bi Shih rate * 64, rate * 256);
74f4fb4fefSTzung-Bi Shih if (ret < 0) {
75f4fb4fefSTzung-Bi Shih dev_err(card->dev, "failed to set pll\n");
76f4fb4fefSTzung-Bi Shih return ret;
77f4fb4fefSTzung-Bi Shih }
78f4fb4fefSTzung-Bi Shih
79f4fb4fefSTzung-Bi Shih ret = snd_soc_dai_set_sysclk(codec_dai, RT1015_SCLK_S_PLL,
80f4fb4fefSTzung-Bi Shih rate * 256, SND_SOC_CLOCK_IN);
81f4fb4fefSTzung-Bi Shih if (ret < 0) {
82f4fb4fefSTzung-Bi Shih dev_err(card->dev, "failed to set sysclk\n");
83f4fb4fefSTzung-Bi Shih return ret;
84f4fb4fefSTzung-Bi Shih }
85f4fb4fefSTzung-Bi Shih }
86f4fb4fefSTzung-Bi Shih
87f4fb4fefSTzung-Bi Shih return snd_soc_dai_set_sysclk(asoc_rtd_to_cpu(rtd, 0),
88f4fb4fefSTzung-Bi Shih 0, mclk_fs, SND_SOC_CLOCK_OUT);
89f4fb4fefSTzung-Bi Shih }
90f4fb4fefSTzung-Bi Shih
91f4fb4fefSTzung-Bi Shih static const struct snd_soc_ops mt8183_mt6358_rt1015_i2s_ops = {
92f4fb4fefSTzung-Bi Shih .hw_params = mt8183_mt6358_rt1015_i2s_hw_params,
93f4fb4fefSTzung-Bi Shih };
94f4fb4fefSTzung-Bi Shih
mt8183_i2s_hw_params_fixup(struct snd_soc_pcm_runtime * rtd,struct snd_pcm_hw_params * params)9511c02690SShunli Wang static int mt8183_i2s_hw_params_fixup(struct snd_soc_pcm_runtime *rtd,
9611c02690SShunli Wang struct snd_pcm_hw_params *params)
9711c02690SShunli Wang {
9803c2192aSJiaxin Yu dev_dbg(rtd->dev, "%s(), fix format to S32_LE\n", __func__);
9911c02690SShunli Wang
10003c2192aSJiaxin Yu /* fix BE i2s format to S32_LE, clean param mask first */
10111c02690SShunli Wang snd_mask_reset_range(hw_param_mask(params, SNDRV_PCM_HW_PARAM_FORMAT),
10203c2192aSJiaxin Yu 0, (__force unsigned int)SNDRV_PCM_FORMAT_LAST);
10311c02690SShunli Wang
10411c02690SShunli Wang params_set_format(params, SNDRV_PCM_FORMAT_S32_LE);
10511c02690SShunli Wang return 0;
10611c02690SShunli Wang }
10711c02690SShunli Wang
mt8183_rt1015_i2s_hw_params_fixup(struct snd_soc_pcm_runtime * rtd,struct snd_pcm_hw_params * params)108f4fb4fefSTzung-Bi Shih static int mt8183_rt1015_i2s_hw_params_fixup(struct snd_soc_pcm_runtime *rtd,
109f4fb4fefSTzung-Bi Shih struct snd_pcm_hw_params *params)
110f4fb4fefSTzung-Bi Shih {
11103c2192aSJiaxin Yu dev_dbg(rtd->dev, "%s(), fix format to S24_LE\n", __func__);
112f4fb4fefSTzung-Bi Shih
11303c2192aSJiaxin Yu /* fix BE i2s format to S24_LE, clean param mask first */
114f4fb4fefSTzung-Bi Shih snd_mask_reset_range(hw_param_mask(params, SNDRV_PCM_HW_PARAM_FORMAT),
11503c2192aSJiaxin Yu 0, (__force unsigned int)SNDRV_PCM_FORMAT_LAST);
116f4fb4fefSTzung-Bi Shih
117f4fb4fefSTzung-Bi Shih params_set_format(params, SNDRV_PCM_FORMAT_S24_LE);
118f4fb4fefSTzung-Bi Shih return 0;
119f4fb4fefSTzung-Bi Shih }
120f4fb4fefSTzung-Bi Shih
1211df1e545STzung-Bi Shih static int
mt8183_mt6358_startup(struct snd_pcm_substream * substream)12219657a60SJiaxin Yu mt8183_mt6358_startup(struct snd_pcm_substream *substream)
12319657a60SJiaxin Yu {
12419657a60SJiaxin Yu static const unsigned int rates[] = {
12519657a60SJiaxin Yu 48000,
12619657a60SJiaxin Yu };
12719657a60SJiaxin Yu static const struct snd_pcm_hw_constraint_list constraints_rates = {
12819657a60SJiaxin Yu .count = ARRAY_SIZE(rates),
12919657a60SJiaxin Yu .list = rates,
13019657a60SJiaxin Yu .mask = 0,
13119657a60SJiaxin Yu };
13219657a60SJiaxin Yu static const unsigned int channels[] = {
13319657a60SJiaxin Yu 2,
13419657a60SJiaxin Yu };
13519657a60SJiaxin Yu static const struct snd_pcm_hw_constraint_list constraints_channels = {
13619657a60SJiaxin Yu .count = ARRAY_SIZE(channels),
13719657a60SJiaxin Yu .list = channels,
13819657a60SJiaxin Yu .mask = 0,
13919657a60SJiaxin Yu };
14019657a60SJiaxin Yu
14119657a60SJiaxin Yu struct snd_pcm_runtime *runtime = substream->runtime;
14219657a60SJiaxin Yu
14319657a60SJiaxin Yu snd_pcm_hw_constraint_list(runtime, 0,
14419657a60SJiaxin Yu SNDRV_PCM_HW_PARAM_RATE, &constraints_rates);
14519657a60SJiaxin Yu runtime->hw.channels_max = 2;
14619657a60SJiaxin Yu snd_pcm_hw_constraint_list(runtime, 0,
14719657a60SJiaxin Yu SNDRV_PCM_HW_PARAM_CHANNELS,
14819657a60SJiaxin Yu &constraints_channels);
14919657a60SJiaxin Yu
15019657a60SJiaxin Yu runtime->hw.formats = SNDRV_PCM_FMTBIT_S16_LE;
15119657a60SJiaxin Yu snd_pcm_hw_constraint_msbits(runtime, 0, 16, 16);
15219657a60SJiaxin Yu
15319657a60SJiaxin Yu return 0;
15419657a60SJiaxin Yu }
15519657a60SJiaxin Yu
15619657a60SJiaxin Yu static const struct snd_soc_ops mt8183_mt6358_ops = {
15719657a60SJiaxin Yu .startup = mt8183_mt6358_startup,
15819657a60SJiaxin Yu };
15919657a60SJiaxin Yu
16019657a60SJiaxin Yu static int
mt8183_mt6358_ts3a227_max98357_bt_sco_startup(struct snd_pcm_substream * substream)1611df1e545STzung-Bi Shih mt8183_mt6358_ts3a227_max98357_bt_sco_startup(
1621df1e545STzung-Bi Shih struct snd_pcm_substream *substream)
1631df1e545STzung-Bi Shih {
1641df1e545STzung-Bi Shih static const unsigned int rates[] = {
1651df1e545STzung-Bi Shih 8000, 16000
1661df1e545STzung-Bi Shih };
1671df1e545STzung-Bi Shih static const struct snd_pcm_hw_constraint_list constraints_rates = {
1681df1e545STzung-Bi Shih .count = ARRAY_SIZE(rates),
1691df1e545STzung-Bi Shih .list = rates,
1701df1e545STzung-Bi Shih .mask = 0,
1711df1e545STzung-Bi Shih };
1721df1e545STzung-Bi Shih static const unsigned int channels[] = {
1731df1e545STzung-Bi Shih 1,
1741df1e545STzung-Bi Shih };
1751df1e545STzung-Bi Shih static const struct snd_pcm_hw_constraint_list constraints_channels = {
1761df1e545STzung-Bi Shih .count = ARRAY_SIZE(channels),
1771df1e545STzung-Bi Shih .list = channels,
1781df1e545STzung-Bi Shih .mask = 0,
1791df1e545STzung-Bi Shih };
1801df1e545STzung-Bi Shih
1811df1e545STzung-Bi Shih struct snd_pcm_runtime *runtime = substream->runtime;
1821df1e545STzung-Bi Shih
1831df1e545STzung-Bi Shih snd_pcm_hw_constraint_list(runtime, 0,
1841df1e545STzung-Bi Shih SNDRV_PCM_HW_PARAM_RATE, &constraints_rates);
1851df1e545STzung-Bi Shih runtime->hw.channels_max = 1;
1861df1e545STzung-Bi Shih snd_pcm_hw_constraint_list(runtime, 0,
1871df1e545STzung-Bi Shih SNDRV_PCM_HW_PARAM_CHANNELS,
1881df1e545STzung-Bi Shih &constraints_channels);
1891df1e545STzung-Bi Shih
1901df1e545STzung-Bi Shih runtime->hw.formats = SNDRV_PCM_FMTBIT_S16_LE;
1911df1e545STzung-Bi Shih snd_pcm_hw_constraint_msbits(runtime, 0, 16, 16);
1921df1e545STzung-Bi Shih
1931df1e545STzung-Bi Shih return 0;
1941df1e545STzung-Bi Shih }
1951df1e545STzung-Bi Shih
1961df1e545STzung-Bi Shih static const struct snd_soc_ops mt8183_mt6358_ts3a227_max98357_bt_sco_ops = {
1971df1e545STzung-Bi Shih .startup = mt8183_mt6358_ts3a227_max98357_bt_sco_startup,
1981df1e545STzung-Bi Shih };
1991df1e545STzung-Bi Shih
200fa284fd0SKuninori Morimoto /* FE */
201fa284fd0SKuninori Morimoto SND_SOC_DAILINK_DEFS(playback1,
202fa284fd0SKuninori Morimoto DAILINK_COMP_ARRAY(COMP_CPU("DL1")),
203fa284fd0SKuninori Morimoto DAILINK_COMP_ARRAY(COMP_DUMMY()),
204fa284fd0SKuninori Morimoto DAILINK_COMP_ARRAY(COMP_EMPTY()));
205fa284fd0SKuninori Morimoto
206fa284fd0SKuninori Morimoto SND_SOC_DAILINK_DEFS(playback2,
207fa284fd0SKuninori Morimoto DAILINK_COMP_ARRAY(COMP_CPU("DL2")),
208fa284fd0SKuninori Morimoto DAILINK_COMP_ARRAY(COMP_DUMMY()),
209fa284fd0SKuninori Morimoto DAILINK_COMP_ARRAY(COMP_EMPTY()));
210fa284fd0SKuninori Morimoto
211fa284fd0SKuninori Morimoto SND_SOC_DAILINK_DEFS(playback3,
212fa284fd0SKuninori Morimoto DAILINK_COMP_ARRAY(COMP_CPU("DL3")),
213fa284fd0SKuninori Morimoto DAILINK_COMP_ARRAY(COMP_DUMMY()),
214fa284fd0SKuninori Morimoto DAILINK_COMP_ARRAY(COMP_EMPTY()));
215fa284fd0SKuninori Morimoto
216fa284fd0SKuninori Morimoto SND_SOC_DAILINK_DEFS(capture1,
217fa284fd0SKuninori Morimoto DAILINK_COMP_ARRAY(COMP_CPU("UL1")),
218fa284fd0SKuninori Morimoto DAILINK_COMP_ARRAY(COMP_DUMMY()),
219fa284fd0SKuninori Morimoto DAILINK_COMP_ARRAY(COMP_EMPTY()));
220fa284fd0SKuninori Morimoto
221fa284fd0SKuninori Morimoto SND_SOC_DAILINK_DEFS(capture2,
222fa284fd0SKuninori Morimoto DAILINK_COMP_ARRAY(COMP_CPU("UL2")),
223fa284fd0SKuninori Morimoto DAILINK_COMP_ARRAY(COMP_DUMMY()),
224fa284fd0SKuninori Morimoto DAILINK_COMP_ARRAY(COMP_EMPTY()));
225fa284fd0SKuninori Morimoto
226fa284fd0SKuninori Morimoto SND_SOC_DAILINK_DEFS(capture3,
227fa284fd0SKuninori Morimoto DAILINK_COMP_ARRAY(COMP_CPU("UL3")),
228fa284fd0SKuninori Morimoto DAILINK_COMP_ARRAY(COMP_DUMMY()),
229fa284fd0SKuninori Morimoto DAILINK_COMP_ARRAY(COMP_EMPTY()));
230fa284fd0SKuninori Morimoto
231fa284fd0SKuninori Morimoto SND_SOC_DAILINK_DEFS(capture_mono,
232fa284fd0SKuninori Morimoto DAILINK_COMP_ARRAY(COMP_CPU("UL_MONO_1")),
233fa284fd0SKuninori Morimoto DAILINK_COMP_ARRAY(COMP_DUMMY()),
234fa284fd0SKuninori Morimoto DAILINK_COMP_ARRAY(COMP_EMPTY()));
235fa284fd0SKuninori Morimoto
236fa284fd0SKuninori Morimoto SND_SOC_DAILINK_DEFS(playback_hdmi,
237fa284fd0SKuninori Morimoto DAILINK_COMP_ARRAY(COMP_CPU("HDMI")),
238fa284fd0SKuninori Morimoto DAILINK_COMP_ARRAY(COMP_DUMMY()),
239fa284fd0SKuninori Morimoto DAILINK_COMP_ARRAY(COMP_EMPTY()));
240fa284fd0SKuninori Morimoto
2412cc3cd5fSTzung-Bi Shih SND_SOC_DAILINK_DEFS(wake_on_voice,
2422cc3cd5fSTzung-Bi Shih DAILINK_COMP_ARRAY(COMP_DUMMY()),
2432cc3cd5fSTzung-Bi Shih DAILINK_COMP_ARRAY(COMP_DUMMY()),
2442cc3cd5fSTzung-Bi Shih DAILINK_COMP_ARRAY(COMP_EMPTY()));
2452cc3cd5fSTzung-Bi Shih
246fa284fd0SKuninori Morimoto /* BE */
247fa284fd0SKuninori Morimoto SND_SOC_DAILINK_DEFS(primary_codec,
248fa284fd0SKuninori Morimoto DAILINK_COMP_ARRAY(COMP_CPU("ADDA")),
249fa284fd0SKuninori Morimoto DAILINK_COMP_ARRAY(COMP_CODEC("mt6358-sound", "mt6358-snd-codec-aif1")),
250fa284fd0SKuninori Morimoto DAILINK_COMP_ARRAY(COMP_EMPTY()));
251fa284fd0SKuninori Morimoto
252fa284fd0SKuninori Morimoto SND_SOC_DAILINK_DEFS(pcm1,
253fa284fd0SKuninori Morimoto DAILINK_COMP_ARRAY(COMP_CPU("PCM 1")),
254fa284fd0SKuninori Morimoto DAILINK_COMP_ARRAY(COMP_DUMMY()),
255fa284fd0SKuninori Morimoto DAILINK_COMP_ARRAY(COMP_EMPTY()));
256fa284fd0SKuninori Morimoto
257fa284fd0SKuninori Morimoto SND_SOC_DAILINK_DEFS(pcm2,
258fa284fd0SKuninori Morimoto DAILINK_COMP_ARRAY(COMP_CPU("PCM 2")),
259fa284fd0SKuninori Morimoto DAILINK_COMP_ARRAY(COMP_DUMMY()),
260fa284fd0SKuninori Morimoto DAILINK_COMP_ARRAY(COMP_EMPTY()));
261fa284fd0SKuninori Morimoto
262fa284fd0SKuninori Morimoto SND_SOC_DAILINK_DEFS(i2s0,
263fa284fd0SKuninori Morimoto DAILINK_COMP_ARRAY(COMP_CPU("I2S0")),
2645ea14bf6SJiaxin Yu DAILINK_COMP_ARRAY(COMP_CODEC("bt-sco", "bt-sco-pcm-wb")),
265fa284fd0SKuninori Morimoto DAILINK_COMP_ARRAY(COMP_EMPTY()));
266fa284fd0SKuninori Morimoto
267fa284fd0SKuninori Morimoto SND_SOC_DAILINK_DEFS(i2s1,
268fa284fd0SKuninori Morimoto DAILINK_COMP_ARRAY(COMP_CPU("I2S1")),
269fa284fd0SKuninori Morimoto DAILINK_COMP_ARRAY(COMP_DUMMY()),
270fa284fd0SKuninori Morimoto DAILINK_COMP_ARRAY(COMP_EMPTY()));
271fa284fd0SKuninori Morimoto
272fa284fd0SKuninori Morimoto SND_SOC_DAILINK_DEFS(i2s2,
273fa284fd0SKuninori Morimoto DAILINK_COMP_ARRAY(COMP_CPU("I2S2")),
274fa284fd0SKuninori Morimoto DAILINK_COMP_ARRAY(COMP_DUMMY()),
275fa284fd0SKuninori Morimoto DAILINK_COMP_ARRAY(COMP_EMPTY()));
276fa284fd0SKuninori Morimoto
277f4fb4fefSTzung-Bi Shih SND_SOC_DAILINK_DEFS(i2s3_max98357a,
278fa284fd0SKuninori Morimoto DAILINK_COMP_ARRAY(COMP_CPU("I2S3")),
279fa284fd0SKuninori Morimoto DAILINK_COMP_ARRAY(COMP_CODEC("max98357a", "HiFi")),
280fa284fd0SKuninori Morimoto DAILINK_COMP_ARRAY(COMP_EMPTY()));
281fa284fd0SKuninori Morimoto
282f4fb4fefSTzung-Bi Shih SND_SOC_DAILINK_DEFS(i2s3_rt1015,
283f4fb4fefSTzung-Bi Shih DAILINK_COMP_ARRAY(COMP_CPU("I2S3")),
284f4fb4fefSTzung-Bi Shih DAILINK_COMP_ARRAY(COMP_CODEC(RT1015_DEV0_NAME, RT1015_CODEC_DAI),
285f4fb4fefSTzung-Bi Shih COMP_CODEC(RT1015_DEV1_NAME, RT1015_CODEC_DAI)),
286f4fb4fefSTzung-Bi Shih DAILINK_COMP_ARRAY(COMP_EMPTY()));
287f4fb4fefSTzung-Bi Shih
2889dc21a06STzung-Bi Shih SND_SOC_DAILINK_DEFS(i2s3_rt1015p,
2899dc21a06STzung-Bi Shih DAILINK_COMP_ARRAY(COMP_CPU("I2S3")),
2909dc21a06STzung-Bi Shih DAILINK_COMP_ARRAY(COMP_CODEC("rt1015p", "HiFi")),
2919dc21a06STzung-Bi Shih DAILINK_COMP_ARRAY(COMP_EMPTY()));
2929dc21a06STzung-Bi Shih
293fa284fd0SKuninori Morimoto SND_SOC_DAILINK_DEFS(i2s5,
294fa284fd0SKuninori Morimoto DAILINK_COMP_ARRAY(COMP_CPU("I2S5")),
2955ea14bf6SJiaxin Yu DAILINK_COMP_ARRAY(COMP_CODEC("bt-sco", "bt-sco-pcm-wb")),
296fa284fd0SKuninori Morimoto DAILINK_COMP_ARRAY(COMP_EMPTY()));
297fa284fd0SKuninori Morimoto
298fa284fd0SKuninori Morimoto SND_SOC_DAILINK_DEFS(tdm,
299fa284fd0SKuninori Morimoto DAILINK_COMP_ARRAY(COMP_CPU("TDM")),
300f2024dc5STzung-Bi Shih DAILINK_COMP_ARRAY(COMP_CODEC(NULL, "i2s-hifi")),
301fa284fd0SKuninori Morimoto DAILINK_COMP_ARRAY(COMP_EMPTY()));
302fa284fd0SKuninori Morimoto
mt8183_mt6358_tdm_startup(struct snd_pcm_substream * substream)3036191cbdeSJiaxin Yu static int mt8183_mt6358_tdm_startup(struct snd_pcm_substream *substream)
3046191cbdeSJiaxin Yu {
3050cd08b10SKuninori Morimoto struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
3066191cbdeSJiaxin Yu struct mt8183_mt6358_ts3a227_max98357_priv *priv =
3076191cbdeSJiaxin Yu snd_soc_card_get_drvdata(rtd->card);
3086191cbdeSJiaxin Yu int ret;
3096191cbdeSJiaxin Yu
3106191cbdeSJiaxin Yu if (IS_ERR(priv->pin_states[PIN_TDM_OUT_ON]))
3116191cbdeSJiaxin Yu return PTR_ERR(priv->pin_states[PIN_TDM_OUT_ON]);
3126191cbdeSJiaxin Yu
3136191cbdeSJiaxin Yu ret = pinctrl_select_state(priv->pinctrl,
3146191cbdeSJiaxin Yu priv->pin_states[PIN_TDM_OUT_ON]);
3156191cbdeSJiaxin Yu if (ret)
3166191cbdeSJiaxin Yu dev_err(rtd->card->dev, "%s failed to select state %d\n",
3176191cbdeSJiaxin Yu __func__, ret);
3186191cbdeSJiaxin Yu
3196191cbdeSJiaxin Yu return ret;
3206191cbdeSJiaxin Yu }
3216191cbdeSJiaxin Yu
mt8183_mt6358_tdm_shutdown(struct snd_pcm_substream * substream)3226191cbdeSJiaxin Yu static void mt8183_mt6358_tdm_shutdown(struct snd_pcm_substream *substream)
3236191cbdeSJiaxin Yu {
3240cd08b10SKuninori Morimoto struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
3256191cbdeSJiaxin Yu struct mt8183_mt6358_ts3a227_max98357_priv *priv =
3266191cbdeSJiaxin Yu snd_soc_card_get_drvdata(rtd->card);
3276191cbdeSJiaxin Yu int ret;
3286191cbdeSJiaxin Yu
3296191cbdeSJiaxin Yu if (IS_ERR(priv->pin_states[PIN_TDM_OUT_OFF]))
3306191cbdeSJiaxin Yu return;
3316191cbdeSJiaxin Yu
3326191cbdeSJiaxin Yu ret = pinctrl_select_state(priv->pinctrl,
3336191cbdeSJiaxin Yu priv->pin_states[PIN_TDM_OUT_OFF]);
3346191cbdeSJiaxin Yu if (ret)
3356191cbdeSJiaxin Yu dev_err(rtd->card->dev, "%s failed to select state %d\n",
3366191cbdeSJiaxin Yu __func__, ret);
3376191cbdeSJiaxin Yu }
3386191cbdeSJiaxin Yu
339abed054fSRikard Falkeborn static const struct snd_soc_ops mt8183_mt6358_tdm_ops = {
3406191cbdeSJiaxin Yu .startup = mt8183_mt6358_tdm_startup,
3416191cbdeSJiaxin Yu .shutdown = mt8183_mt6358_tdm_shutdown,
3426191cbdeSJiaxin Yu };
3436191cbdeSJiaxin Yu
3442cc3cd5fSTzung-Bi Shih static int
mt8183_mt6358_ts3a227_max98357_wov_startup(struct snd_pcm_substream * substream)3452cc3cd5fSTzung-Bi Shih mt8183_mt6358_ts3a227_max98357_wov_startup(
3462cc3cd5fSTzung-Bi Shih struct snd_pcm_substream *substream)
3472cc3cd5fSTzung-Bi Shih {
3480cd08b10SKuninori Morimoto struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
3492cc3cd5fSTzung-Bi Shih struct snd_soc_card *card = rtd->card;
3502cc3cd5fSTzung-Bi Shih struct mt8183_mt6358_ts3a227_max98357_priv *priv =
3512cc3cd5fSTzung-Bi Shih snd_soc_card_get_drvdata(card);
3522cc3cd5fSTzung-Bi Shih
3532cc3cd5fSTzung-Bi Shih return pinctrl_select_state(priv->pinctrl,
3542cc3cd5fSTzung-Bi Shih priv->pin_states[PIN_WOV]);
3552cc3cd5fSTzung-Bi Shih }
3562cc3cd5fSTzung-Bi Shih
3572cc3cd5fSTzung-Bi Shih static void
mt8183_mt6358_ts3a227_max98357_wov_shutdown(struct snd_pcm_substream * substream)3582cc3cd5fSTzung-Bi Shih mt8183_mt6358_ts3a227_max98357_wov_shutdown(
3592cc3cd5fSTzung-Bi Shih struct snd_pcm_substream *substream)
3602cc3cd5fSTzung-Bi Shih {
3610cd08b10SKuninori Morimoto struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
3622cc3cd5fSTzung-Bi Shih struct snd_soc_card *card = rtd->card;
3632cc3cd5fSTzung-Bi Shih struct mt8183_mt6358_ts3a227_max98357_priv *priv =
3642cc3cd5fSTzung-Bi Shih snd_soc_card_get_drvdata(card);
3652cc3cd5fSTzung-Bi Shih int ret;
3662cc3cd5fSTzung-Bi Shih
3672cc3cd5fSTzung-Bi Shih ret = pinctrl_select_state(priv->pinctrl,
3682cc3cd5fSTzung-Bi Shih priv->pin_states[PIN_STATE_DEFAULT]);
3692cc3cd5fSTzung-Bi Shih if (ret)
3702cc3cd5fSTzung-Bi Shih dev_err(card->dev, "%s failed to select state %d\n",
3712cc3cd5fSTzung-Bi Shih __func__, ret);
3722cc3cd5fSTzung-Bi Shih }
3732cc3cd5fSTzung-Bi Shih
3742cc3cd5fSTzung-Bi Shih static const struct snd_soc_ops mt8183_mt6358_ts3a227_max98357_wov_ops = {
3752cc3cd5fSTzung-Bi Shih .startup = mt8183_mt6358_ts3a227_max98357_wov_startup,
3762cc3cd5fSTzung-Bi Shih .shutdown = mt8183_mt6358_ts3a227_max98357_wov_shutdown,
3772cc3cd5fSTzung-Bi Shih };
3782cc3cd5fSTzung-Bi Shih
37988abbf62STzung-Bi Shih static int
mt8183_mt6358_ts3a227_max98357_hdmi_init(struct snd_soc_pcm_runtime * rtd)38088abbf62STzung-Bi Shih mt8183_mt6358_ts3a227_max98357_hdmi_init(struct snd_soc_pcm_runtime *rtd)
38188abbf62STzung-Bi Shih {
38288abbf62STzung-Bi Shih struct mt8183_mt6358_ts3a227_max98357_priv *priv =
38388abbf62STzung-Bi Shih snd_soc_card_get_drvdata(rtd->card);
38488abbf62STzung-Bi Shih int ret;
38588abbf62STzung-Bi Shih
38688abbf62STzung-Bi Shih ret = snd_soc_card_jack_new(rtd->card, "HDMI Jack", SND_JACK_LINEOUT,
38719aed2d6SAkihiko Odaki &priv->hdmi_jack);
38888abbf62STzung-Bi Shih if (ret)
38988abbf62STzung-Bi Shih return ret;
39088abbf62STzung-Bi Shih
39155c5cc63SCheng-Yi Chiang return snd_soc_component_set_jack(asoc_rtd_to_codec(rtd, 0)->component,
39255c5cc63SCheng-Yi Chiang &priv->hdmi_jack, NULL);
39388abbf62STzung-Bi Shih }
39488abbf62STzung-Bi Shih
mt8183_bt_init(struct snd_soc_pcm_runtime * rtd)3954583392aSNícolas F. R. A. Prado static int mt8183_bt_init(struct snd_soc_pcm_runtime *rtd)
3964583392aSNícolas F. R. A. Prado {
3974583392aSNícolas F. R. A. Prado struct snd_soc_component *cmpnt_afe =
3984583392aSNícolas F. R. A. Prado snd_soc_rtdcom_lookup(rtd, AFE_PCM_NAME);
3994583392aSNícolas F. R. A. Prado struct mtk_base_afe *afe = snd_soc_component_get_drvdata(cmpnt_afe);
4004583392aSNícolas F. R. A. Prado int ret;
4014583392aSNícolas F. R. A. Prado
4024583392aSNícolas F. R. A. Prado ret = mt8183_dai_i2s_set_share(afe, "I2S5", "I2S0");
4034583392aSNícolas F. R. A. Prado if (ret) {
4044583392aSNícolas F. R. A. Prado dev_err(rtd->dev, "Failed to set up shared clocks\n");
4054583392aSNícolas F. R. A. Prado return ret;
4064583392aSNícolas F. R. A. Prado }
4074583392aSNícolas F. R. A. Prado return 0;
4084583392aSNícolas F. R. A. Prado }
4094583392aSNícolas F. R. A. Prado
mt8183_i2s2_init(struct snd_soc_pcm_runtime * rtd)4104583392aSNícolas F. R. A. Prado static int mt8183_i2s2_init(struct snd_soc_pcm_runtime *rtd)
4114583392aSNícolas F. R. A. Prado {
4124583392aSNícolas F. R. A. Prado struct snd_soc_component *cmpnt_afe =
4134583392aSNícolas F. R. A. Prado snd_soc_rtdcom_lookup(rtd, AFE_PCM_NAME);
4144583392aSNícolas F. R. A. Prado struct mtk_base_afe *afe = snd_soc_component_get_drvdata(cmpnt_afe);
4154583392aSNícolas F. R. A. Prado int ret;
4164583392aSNícolas F. R. A. Prado
4174583392aSNícolas F. R. A. Prado ret = mt8183_dai_i2s_set_share(afe, "I2S2", "I2S3");
4184583392aSNícolas F. R. A. Prado if (ret) {
4194583392aSNícolas F. R. A. Prado dev_err(rtd->dev, "Failed to set up shared clocks\n");
4204583392aSNícolas F. R. A. Prado return ret;
4214583392aSNícolas F. R. A. Prado }
4224583392aSNícolas F. R. A. Prado return 0;
4234583392aSNícolas F. R. A. Prado }
4244583392aSNícolas F. R. A. Prado
425f4fb4fefSTzung-Bi Shih static struct snd_soc_dai_link mt8183_mt6358_ts3a227_dai_links[] = {
42611c02690SShunli Wang /* FE */
42711c02690SShunli Wang {
42811c02690SShunli Wang .name = "Playback_1",
42911c02690SShunli Wang .stream_name = "Playback_1",
43011c02690SShunli Wang .trigger = {SND_SOC_DPCM_TRIGGER_PRE,
43111c02690SShunli Wang SND_SOC_DPCM_TRIGGER_PRE},
43211c02690SShunli Wang .dynamic = 1,
43311c02690SShunli Wang .dpcm_playback = 1,
43419657a60SJiaxin Yu .ops = &mt8183_mt6358_ops,
435fa284fd0SKuninori Morimoto SND_SOC_DAILINK_REG(playback1),
43611c02690SShunli Wang },
43711c02690SShunli Wang {
43811c02690SShunli Wang .name = "Playback_2",
43911c02690SShunli Wang .stream_name = "Playback_2",
44011c02690SShunli Wang .trigger = {SND_SOC_DPCM_TRIGGER_PRE,
44111c02690SShunli Wang SND_SOC_DPCM_TRIGGER_PRE},
44211c02690SShunli Wang .dynamic = 1,
44311c02690SShunli Wang .dpcm_playback = 1,
4441df1e545STzung-Bi Shih .ops = &mt8183_mt6358_ts3a227_max98357_bt_sco_ops,
445fa284fd0SKuninori Morimoto SND_SOC_DAILINK_REG(playback2),
44611c02690SShunli Wang },
44711c02690SShunli Wang {
44811c02690SShunli Wang .name = "Playback_3",
44911c02690SShunli Wang .stream_name = "Playback_3",
45011c02690SShunli Wang .trigger = {SND_SOC_DPCM_TRIGGER_PRE,
45111c02690SShunli Wang SND_SOC_DPCM_TRIGGER_PRE},
45211c02690SShunli Wang .dynamic = 1,
45311c02690SShunli Wang .dpcm_playback = 1,
454fa284fd0SKuninori Morimoto SND_SOC_DAILINK_REG(playback3),
45511c02690SShunli Wang },
45611c02690SShunli Wang {
45711c02690SShunli Wang .name = "Capture_1",
45811c02690SShunli Wang .stream_name = "Capture_1",
45911c02690SShunli Wang .trigger = {SND_SOC_DPCM_TRIGGER_PRE,
46011c02690SShunli Wang SND_SOC_DPCM_TRIGGER_PRE},
46111c02690SShunli Wang .dynamic = 1,
46211c02690SShunli Wang .dpcm_capture = 1,
4631df1e545STzung-Bi Shih .ops = &mt8183_mt6358_ts3a227_max98357_bt_sco_ops,
464fa284fd0SKuninori Morimoto SND_SOC_DAILINK_REG(capture1),
46511c02690SShunli Wang },
46611c02690SShunli Wang {
46711c02690SShunli Wang .name = "Capture_2",
46811c02690SShunli Wang .stream_name = "Capture_2",
46911c02690SShunli Wang .trigger = {SND_SOC_DPCM_TRIGGER_PRE,
47011c02690SShunli Wang SND_SOC_DPCM_TRIGGER_PRE},
47111c02690SShunli Wang .dynamic = 1,
47211c02690SShunli Wang .dpcm_capture = 1,
473fa284fd0SKuninori Morimoto SND_SOC_DAILINK_REG(capture2),
47411c02690SShunli Wang },
47511c02690SShunli Wang {
47611c02690SShunli Wang .name = "Capture_3",
47711c02690SShunli Wang .stream_name = "Capture_3",
47811c02690SShunli Wang .trigger = {SND_SOC_DPCM_TRIGGER_PRE,
47911c02690SShunli Wang SND_SOC_DPCM_TRIGGER_PRE},
48011c02690SShunli Wang .dynamic = 1,
48111c02690SShunli Wang .dpcm_capture = 1,
48219657a60SJiaxin Yu .ops = &mt8183_mt6358_ops,
483fa284fd0SKuninori Morimoto SND_SOC_DAILINK_REG(capture3),
48411c02690SShunli Wang },
48511c02690SShunli Wang {
48611c02690SShunli Wang .name = "Capture_Mono_1",
48711c02690SShunli Wang .stream_name = "Capture_Mono_1",
48811c02690SShunli Wang .trigger = {SND_SOC_DPCM_TRIGGER_PRE,
48911c02690SShunli Wang SND_SOC_DPCM_TRIGGER_PRE},
49011c02690SShunli Wang .dynamic = 1,
49111c02690SShunli Wang .dpcm_capture = 1,
492fa284fd0SKuninori Morimoto SND_SOC_DAILINK_REG(capture_mono),
49311c02690SShunli Wang },
49411c02690SShunli Wang {
49511c02690SShunli Wang .name = "Playback_HDMI",
49611c02690SShunli Wang .stream_name = "Playback_HDMI",
49711c02690SShunli Wang .trigger = {SND_SOC_DPCM_TRIGGER_PRE,
49811c02690SShunli Wang SND_SOC_DPCM_TRIGGER_PRE},
49911c02690SShunli Wang .dynamic = 1,
50011c02690SShunli Wang .dpcm_playback = 1,
501fa284fd0SKuninori Morimoto SND_SOC_DAILINK_REG(playback_hdmi),
50211c02690SShunli Wang },
5032cc3cd5fSTzung-Bi Shih {
5042cc3cd5fSTzung-Bi Shih .name = "Wake on Voice",
5052cc3cd5fSTzung-Bi Shih .stream_name = "Wake on Voice",
5062cc3cd5fSTzung-Bi Shih .ignore_suspend = 1,
5072cc3cd5fSTzung-Bi Shih .ignore = 1,
5082cc3cd5fSTzung-Bi Shih SND_SOC_DAILINK_REG(wake_on_voice),
5092cc3cd5fSTzung-Bi Shih .ops = &mt8183_mt6358_ts3a227_max98357_wov_ops,
5102cc3cd5fSTzung-Bi Shih },
5112cc3cd5fSTzung-Bi Shih
51211c02690SShunli Wang /* BE */
51311c02690SShunli Wang {
51411c02690SShunli Wang .name = "Primary Codec",
51511c02690SShunli Wang .no_pcm = 1,
51611c02690SShunli Wang .dpcm_playback = 1,
51711c02690SShunli Wang .dpcm_capture = 1,
51811c02690SShunli Wang .ignore_suspend = 1,
519fa284fd0SKuninori Morimoto SND_SOC_DAILINK_REG(primary_codec),
52011c02690SShunli Wang },
52111c02690SShunli Wang {
52211c02690SShunli Wang .name = "PCM 1",
52311c02690SShunli Wang .no_pcm = 1,
52411c02690SShunli Wang .dpcm_playback = 1,
52511c02690SShunli Wang .dpcm_capture = 1,
52611c02690SShunli Wang .ignore_suspend = 1,
527fa284fd0SKuninori Morimoto SND_SOC_DAILINK_REG(pcm1),
52811c02690SShunli Wang },
52911c02690SShunli Wang {
53011c02690SShunli Wang .name = "PCM 2",
53111c02690SShunli Wang .no_pcm = 1,
53211c02690SShunli Wang .dpcm_playback = 1,
53311c02690SShunli Wang .dpcm_capture = 1,
53411c02690SShunli Wang .ignore_suspend = 1,
535fa284fd0SKuninori Morimoto SND_SOC_DAILINK_REG(pcm2),
53611c02690SShunli Wang },
53711c02690SShunli Wang {
53811c02690SShunli Wang .name = "I2S0",
53911c02690SShunli Wang .no_pcm = 1,
54011c02690SShunli Wang .dpcm_capture = 1,
54111c02690SShunli Wang .ignore_suspend = 1,
54211c02690SShunli Wang .ops = &mt8183_mt6358_i2s_ops,
543fa284fd0SKuninori Morimoto SND_SOC_DAILINK_REG(i2s0),
54411c02690SShunli Wang },
54511c02690SShunli Wang {
54611c02690SShunli Wang .name = "I2S1",
54711c02690SShunli Wang .no_pcm = 1,
54811c02690SShunli Wang .dpcm_playback = 1,
54911c02690SShunli Wang .ignore_suspend = 1,
55011c02690SShunli Wang .be_hw_params_fixup = mt8183_i2s_hw_params_fixup,
55111c02690SShunli Wang .ops = &mt8183_mt6358_i2s_ops,
552fa284fd0SKuninori Morimoto SND_SOC_DAILINK_REG(i2s1),
55311c02690SShunli Wang },
55411c02690SShunli Wang {
55511c02690SShunli Wang .name = "I2S2",
55611c02690SShunli Wang .no_pcm = 1,
55711c02690SShunli Wang .dpcm_capture = 1,
55811c02690SShunli Wang .ignore_suspend = 1,
55911c02690SShunli Wang .be_hw_params_fixup = mt8183_i2s_hw_params_fixup,
56011c02690SShunli Wang .ops = &mt8183_mt6358_i2s_ops,
5614583392aSNícolas F. R. A. Prado .init = &mt8183_i2s2_init,
562fa284fd0SKuninori Morimoto SND_SOC_DAILINK_REG(i2s2),
56311c02690SShunli Wang },
56411c02690SShunli Wang {
56511c02690SShunli Wang .name = "I2S3",
56611c02690SShunli Wang .no_pcm = 1,
56711c02690SShunli Wang .dpcm_playback = 1,
56811c02690SShunli Wang .ignore_suspend = 1,
56911c02690SShunli Wang },
57011c02690SShunli Wang {
57111c02690SShunli Wang .name = "I2S5",
57211c02690SShunli Wang .no_pcm = 1,
57311c02690SShunli Wang .dpcm_playback = 1,
57411c02690SShunli Wang .ignore_suspend = 1,
57511c02690SShunli Wang .ops = &mt8183_mt6358_i2s_ops,
5764583392aSNícolas F. R. A. Prado .init = &mt8183_bt_init,
577fa284fd0SKuninori Morimoto SND_SOC_DAILINK_REG(i2s5),
57811c02690SShunli Wang },
57911c02690SShunli Wang {
58011c02690SShunli Wang .name = "TDM",
58111c02690SShunli Wang .no_pcm = 1,
5828e58c521SJiaxin Yu .dai_fmt = SND_SOC_DAIFMT_I2S |
5838e58c521SJiaxin Yu SND_SOC_DAIFMT_IB_IF |
5848e58c521SJiaxin Yu SND_SOC_DAIFMT_CBM_CFM,
58511c02690SShunli Wang .dpcm_playback = 1,
58611c02690SShunli Wang .ignore_suspend = 1,
5876191cbdeSJiaxin Yu .be_hw_params_fixup = mt8183_i2s_hw_params_fixup,
5886191cbdeSJiaxin Yu .ops = &mt8183_mt6358_tdm_ops,
5895ac15444STzung-Bi Shih .ignore = 1,
59088abbf62STzung-Bi Shih .init = mt8183_mt6358_ts3a227_max98357_hdmi_init,
591fa284fd0SKuninori Morimoto SND_SOC_DAILINK_REG(tdm),
59211c02690SShunli Wang },
59311c02690SShunli Wang };
59411c02690SShunli Wang
595*09a22368SAlper Nebi Yasak static const
596*09a22368SAlper Nebi Yasak struct snd_kcontrol_new mt8183_mt6358_ts3a227_max98357_snd_controls[] = {
597*09a22368SAlper Nebi Yasak SOC_DAPM_PIN_SWITCH("Headphone"),
598*09a22368SAlper Nebi Yasak SOC_DAPM_PIN_SWITCH("Headset Mic"),
599*09a22368SAlper Nebi Yasak };
600*09a22368SAlper Nebi Yasak
601*09a22368SAlper Nebi Yasak static const
602*09a22368SAlper Nebi Yasak struct snd_soc_dapm_widget mt8183_mt6358_ts3a227_max98357_dapm_widgets[] = {
603*09a22368SAlper Nebi Yasak SND_SOC_DAPM_HP("Headphone", NULL),
604*09a22368SAlper Nebi Yasak SND_SOC_DAPM_MIC("Headset Mic", NULL),
605*09a22368SAlper Nebi Yasak };
606*09a22368SAlper Nebi Yasak
607*09a22368SAlper Nebi Yasak static struct snd_soc_jack_pin mt8183_mt6358_ts3a227_max98357_jack_pins[] = {
608*09a22368SAlper Nebi Yasak {
609*09a22368SAlper Nebi Yasak .pin = "Headphone",
610*09a22368SAlper Nebi Yasak .mask = SND_JACK_HEADPHONE,
611*09a22368SAlper Nebi Yasak },
612*09a22368SAlper Nebi Yasak {
613*09a22368SAlper Nebi Yasak .pin = "Headset Mic",
614*09a22368SAlper Nebi Yasak .mask = SND_JACK_MICROPHONE,
615*09a22368SAlper Nebi Yasak },
616*09a22368SAlper Nebi Yasak };
617*09a22368SAlper Nebi Yasak
61811c02690SShunli Wang static struct snd_soc_card mt8183_mt6358_ts3a227_max98357_card = {
61911c02690SShunli Wang .name = "mt8183_mt6358_ts3a227_max98357",
62011c02690SShunli Wang .owner = THIS_MODULE,
621f4fb4fefSTzung-Bi Shih .dai_link = mt8183_mt6358_ts3a227_dai_links,
622f4fb4fefSTzung-Bi Shih .num_links = ARRAY_SIZE(mt8183_mt6358_ts3a227_dai_links),
623*09a22368SAlper Nebi Yasak .controls = mt8183_mt6358_ts3a227_max98357_snd_controls,
624*09a22368SAlper Nebi Yasak .num_controls = ARRAY_SIZE(mt8183_mt6358_ts3a227_max98357_snd_controls),
625*09a22368SAlper Nebi Yasak .dapm_widgets = mt8183_mt6358_ts3a227_max98357_dapm_widgets,
626*09a22368SAlper Nebi Yasak .num_dapm_widgets = ARRAY_SIZE(mt8183_mt6358_ts3a227_max98357_dapm_widgets),
627f4fb4fefSTzung-Bi Shih };
628f4fb4fefSTzung-Bi Shih
62908145535STzung-Bi Shih static struct snd_soc_card mt8183_mt6358_ts3a227_max98357b_card = {
63008145535STzung-Bi Shih .name = "mt8183_mt6358_ts3a227_max98357b",
63108145535STzung-Bi Shih .owner = THIS_MODULE,
63208145535STzung-Bi Shih .dai_link = mt8183_mt6358_ts3a227_dai_links,
63308145535STzung-Bi Shih .num_links = ARRAY_SIZE(mt8183_mt6358_ts3a227_dai_links),
634*09a22368SAlper Nebi Yasak .controls = mt8183_mt6358_ts3a227_max98357_snd_controls,
635*09a22368SAlper Nebi Yasak .num_controls = ARRAY_SIZE(mt8183_mt6358_ts3a227_max98357_snd_controls),
636*09a22368SAlper Nebi Yasak .dapm_widgets = mt8183_mt6358_ts3a227_max98357_dapm_widgets,
637*09a22368SAlper Nebi Yasak .num_dapm_widgets = ARRAY_SIZE(mt8183_mt6358_ts3a227_max98357_dapm_widgets),
63808145535STzung-Bi Shih };
63908145535STzung-Bi Shih
640f4fb4fefSTzung-Bi Shih static struct snd_soc_codec_conf mt8183_mt6358_ts3a227_rt1015_amp_conf[] = {
641f4fb4fefSTzung-Bi Shih {
642f4fb4fefSTzung-Bi Shih .dlc = COMP_CODEC_CONF(RT1015_DEV0_NAME),
643f4fb4fefSTzung-Bi Shih .name_prefix = "Left",
644f4fb4fefSTzung-Bi Shih },
645f4fb4fefSTzung-Bi Shih {
646f4fb4fefSTzung-Bi Shih .dlc = COMP_CODEC_CONF(RT1015_DEV1_NAME),
647f4fb4fefSTzung-Bi Shih .name_prefix = "Right",
648f4fb4fefSTzung-Bi Shih },
649f4fb4fefSTzung-Bi Shih };
650f4fb4fefSTzung-Bi Shih
651f4fb4fefSTzung-Bi Shih static struct snd_soc_card mt8183_mt6358_ts3a227_rt1015_card = {
652f4fb4fefSTzung-Bi Shih .name = "mt8183_mt6358_ts3a227_rt1015",
653f4fb4fefSTzung-Bi Shih .owner = THIS_MODULE,
654f4fb4fefSTzung-Bi Shih .dai_link = mt8183_mt6358_ts3a227_dai_links,
655f4fb4fefSTzung-Bi Shih .num_links = ARRAY_SIZE(mt8183_mt6358_ts3a227_dai_links),
656f4fb4fefSTzung-Bi Shih .codec_conf = mt8183_mt6358_ts3a227_rt1015_amp_conf,
657f4fb4fefSTzung-Bi Shih .num_configs = ARRAY_SIZE(mt8183_mt6358_ts3a227_rt1015_amp_conf),
658*09a22368SAlper Nebi Yasak .controls = mt8183_mt6358_ts3a227_max98357_snd_controls,
659*09a22368SAlper Nebi Yasak .num_controls = ARRAY_SIZE(mt8183_mt6358_ts3a227_max98357_snd_controls),
660*09a22368SAlper Nebi Yasak .dapm_widgets = mt8183_mt6358_ts3a227_max98357_dapm_widgets,
661*09a22368SAlper Nebi Yasak .num_dapm_widgets = ARRAY_SIZE(mt8183_mt6358_ts3a227_max98357_dapm_widgets),
66211c02690SShunli Wang };
66311c02690SShunli Wang
6649dc21a06STzung-Bi Shih static struct snd_soc_card mt8183_mt6358_ts3a227_rt1015p_card = {
6659dc21a06STzung-Bi Shih .name = "mt8183_mt6358_ts3a227_rt1015p",
6669dc21a06STzung-Bi Shih .owner = THIS_MODULE,
6679dc21a06STzung-Bi Shih .dai_link = mt8183_mt6358_ts3a227_dai_links,
6689dc21a06STzung-Bi Shih .num_links = ARRAY_SIZE(mt8183_mt6358_ts3a227_dai_links),
669*09a22368SAlper Nebi Yasak .controls = mt8183_mt6358_ts3a227_max98357_snd_controls,
670*09a22368SAlper Nebi Yasak .num_controls = ARRAY_SIZE(mt8183_mt6358_ts3a227_max98357_snd_controls),
671*09a22368SAlper Nebi Yasak .dapm_widgets = mt8183_mt6358_ts3a227_max98357_dapm_widgets,
672*09a22368SAlper Nebi Yasak .num_dapm_widgets = ARRAY_SIZE(mt8183_mt6358_ts3a227_max98357_dapm_widgets),
6739dc21a06STzung-Bi Shih };
6749dc21a06STzung-Bi Shih
67511c02690SShunli Wang static int
mt8183_mt6358_ts3a227_max98357_headset_init(struct snd_soc_component * component)67611c02690SShunli Wang mt8183_mt6358_ts3a227_max98357_headset_init(struct snd_soc_component *component)
67711c02690SShunli Wang {
67811c02690SShunli Wang int ret;
67995d779b4STzung-Bi Shih struct mt8183_mt6358_ts3a227_max98357_priv *priv =
68095d779b4STzung-Bi Shih snd_soc_card_get_drvdata(component->card);
68111c02690SShunli Wang
68211c02690SShunli Wang /* Enable Headset and 4 Buttons Jack detection */
683*09a22368SAlper Nebi Yasak ret = snd_soc_card_jack_new_pins(component->card,
68411c02690SShunli Wang "Headset Jack",
68511c02690SShunli Wang SND_JACK_HEADSET |
68611c02690SShunli Wang SND_JACK_BTN_0 | SND_JACK_BTN_1 |
68711c02690SShunli Wang SND_JACK_BTN_2 | SND_JACK_BTN_3,
688*09a22368SAlper Nebi Yasak &priv->headset_jack,
689*09a22368SAlper Nebi Yasak mt8183_mt6358_ts3a227_max98357_jack_pins,
690*09a22368SAlper Nebi Yasak ARRAY_SIZE(mt8183_mt6358_ts3a227_max98357_jack_pins));
69111c02690SShunli Wang if (ret)
69211c02690SShunli Wang return ret;
69311c02690SShunli Wang
69495d779b4STzung-Bi Shih ret = ts3a227e_enable_jack_detect(component, &priv->headset_jack);
69511c02690SShunli Wang
69611c02690SShunli Wang return ret;
69711c02690SShunli Wang }
69811c02690SShunli Wang
699fc347483STzung-Bi Shih static struct snd_soc_aux_dev mt8183_mt6358_ts3a227_max98357_headset_dev = {
700fc347483STzung-Bi Shih .dlc = COMP_EMPTY(),
701fc347483STzung-Bi Shih .init = mt8183_mt6358_ts3a227_max98357_headset_init,
702fc347483STzung-Bi Shih };
703fc347483STzung-Bi Shih
70411c02690SShunli Wang static int
mt8183_mt6358_ts3a227_max98357_dev_probe(struct platform_device * pdev)70511c02690SShunli Wang mt8183_mt6358_ts3a227_max98357_dev_probe(struct platform_device *pdev)
70611c02690SShunli Wang {
707f4fb4fefSTzung-Bi Shih struct snd_soc_card *card;
708f2024dc5STzung-Bi Shih struct device_node *platform_node, *ec_codec, *hdmi_codec;
70911c02690SShunli Wang struct snd_soc_dai_link *dai_link;
7106191cbdeSJiaxin Yu struct mt8183_mt6358_ts3a227_max98357_priv *priv;
711f4fb4fefSTzung-Bi Shih int ret, i;
71211c02690SShunli Wang
71311c02690SShunli Wang platform_node = of_parse_phandle(pdev->dev.of_node,
71411c02690SShunli Wang "mediatek,platform", 0);
71511c02690SShunli Wang if (!platform_node) {
71611c02690SShunli Wang dev_err(&pdev->dev, "Property 'platform' missing or invalid\n");
71711c02690SShunli Wang return -EINVAL;
71811c02690SShunli Wang }
71911c02690SShunli Wang
7203667a037STzung-Bi Shih card = (struct snd_soc_card *)of_device_get_match_data(&pdev->dev);
72138eef3beSWang Yufen if (!card) {
72238eef3beSWang Yufen of_node_put(platform_node);
723f4fb4fefSTzung-Bi Shih return -EINVAL;
72438eef3beSWang Yufen }
725f4fb4fefSTzung-Bi Shih card->dev = &pdev->dev;
726f4fb4fefSTzung-Bi Shih
7272cc3cd5fSTzung-Bi Shih ec_codec = of_parse_phandle(pdev->dev.of_node, "mediatek,ec-codec", 0);
728f2024dc5STzung-Bi Shih hdmi_codec = of_parse_phandle(pdev->dev.of_node,
729f2024dc5STzung-Bi Shih "mediatek,hdmi-codec", 0);
7302cc3cd5fSTzung-Bi Shih
73111c02690SShunli Wang for_each_card_prelinks(card, i, dai_link) {
7322cc3cd5fSTzung-Bi Shih if (ec_codec && strcmp(dai_link->name, "Wake on Voice") == 0) {
7332cc3cd5fSTzung-Bi Shih dai_link->cpus[0].name = NULL;
7342cc3cd5fSTzung-Bi Shih dai_link->cpus[0].of_node = ec_codec;
7352cc3cd5fSTzung-Bi Shih dai_link->cpus[0].dai_name = NULL;
7362cc3cd5fSTzung-Bi Shih dai_link->codecs[0].name = NULL;
7372cc3cd5fSTzung-Bi Shih dai_link->codecs[0].of_node = ec_codec;
7382cc3cd5fSTzung-Bi Shih dai_link->codecs[0].dai_name = "Wake on Voice";
7392cc3cd5fSTzung-Bi Shih dai_link->platforms[0].of_node = ec_codec;
7402cc3cd5fSTzung-Bi Shih dai_link->ignore = 0;
74111c02690SShunli Wang }
742f4fb4fefSTzung-Bi Shih
743f4fb4fefSTzung-Bi Shih if (strcmp(dai_link->name, "I2S3") == 0) {
74408145535STzung-Bi Shih if (card == &mt8183_mt6358_ts3a227_max98357_card ||
74508145535STzung-Bi Shih card == &mt8183_mt6358_ts3a227_max98357b_card) {
746f4fb4fefSTzung-Bi Shih dai_link->be_hw_params_fixup =
747f4fb4fefSTzung-Bi Shih mt8183_i2s_hw_params_fixup;
748f4fb4fefSTzung-Bi Shih dai_link->ops = &mt8183_mt6358_i2s_ops;
749f4fb4fefSTzung-Bi Shih dai_link->cpus = i2s3_max98357a_cpus;
750f4fb4fefSTzung-Bi Shih dai_link->num_cpus =
751f4fb4fefSTzung-Bi Shih ARRAY_SIZE(i2s3_max98357a_cpus);
752f4fb4fefSTzung-Bi Shih dai_link->codecs = i2s3_max98357a_codecs;
753f4fb4fefSTzung-Bi Shih dai_link->num_codecs =
754f4fb4fefSTzung-Bi Shih ARRAY_SIZE(i2s3_max98357a_codecs);
755f4fb4fefSTzung-Bi Shih dai_link->platforms = i2s3_max98357a_platforms;
756f4fb4fefSTzung-Bi Shih dai_link->num_platforms =
757f4fb4fefSTzung-Bi Shih ARRAY_SIZE(i2s3_max98357a_platforms);
758f4fb4fefSTzung-Bi Shih } else if (card == &mt8183_mt6358_ts3a227_rt1015_card) {
759f4fb4fefSTzung-Bi Shih dai_link->be_hw_params_fixup =
760f4fb4fefSTzung-Bi Shih mt8183_rt1015_i2s_hw_params_fixup;
761f4fb4fefSTzung-Bi Shih dai_link->ops = &mt8183_mt6358_rt1015_i2s_ops;
762f4fb4fefSTzung-Bi Shih dai_link->cpus = i2s3_rt1015_cpus;
763f4fb4fefSTzung-Bi Shih dai_link->num_cpus =
764f4fb4fefSTzung-Bi Shih ARRAY_SIZE(i2s3_rt1015_cpus);
765f4fb4fefSTzung-Bi Shih dai_link->codecs = i2s3_rt1015_codecs;
766f4fb4fefSTzung-Bi Shih dai_link->num_codecs =
767f4fb4fefSTzung-Bi Shih ARRAY_SIZE(i2s3_rt1015_codecs);
768f4fb4fefSTzung-Bi Shih dai_link->platforms = i2s3_rt1015_platforms;
769f4fb4fefSTzung-Bi Shih dai_link->num_platforms =
770f4fb4fefSTzung-Bi Shih ARRAY_SIZE(i2s3_rt1015_platforms);
7719dc21a06STzung-Bi Shih } else if (card == &mt8183_mt6358_ts3a227_rt1015p_card) {
7729dc21a06STzung-Bi Shih dai_link->be_hw_params_fixup =
7739dc21a06STzung-Bi Shih mt8183_rt1015_i2s_hw_params_fixup;
7749dc21a06STzung-Bi Shih dai_link->ops = &mt8183_mt6358_i2s_ops;
7759dc21a06STzung-Bi Shih dai_link->cpus = i2s3_rt1015p_cpus;
7769dc21a06STzung-Bi Shih dai_link->num_cpus =
7779dc21a06STzung-Bi Shih ARRAY_SIZE(i2s3_rt1015p_cpus);
7789dc21a06STzung-Bi Shih dai_link->codecs = i2s3_rt1015p_codecs;
7799dc21a06STzung-Bi Shih dai_link->num_codecs =
7809dc21a06STzung-Bi Shih ARRAY_SIZE(i2s3_rt1015p_codecs);
7819dc21a06STzung-Bi Shih dai_link->platforms = i2s3_rt1015p_platforms;
7829dc21a06STzung-Bi Shih dai_link->num_platforms =
7839dc21a06STzung-Bi Shih ARRAY_SIZE(i2s3_rt1015p_platforms);
784f4fb4fefSTzung-Bi Shih }
785f4fb4fefSTzung-Bi Shih }
786f4fb4fefSTzung-Bi Shih
78708145535STzung-Bi Shih if (card == &mt8183_mt6358_ts3a227_max98357b_card) {
78808145535STzung-Bi Shih if (strcmp(dai_link->name, "I2S2") == 0 ||
78908145535STzung-Bi Shih strcmp(dai_link->name, "I2S3") == 0)
79008145535STzung-Bi Shih dai_link->dai_fmt = SND_SOC_DAIFMT_LEFT_J |
79108145535STzung-Bi Shih SND_SOC_DAIFMT_NB_NF |
79208145535STzung-Bi Shih SND_SOC_DAIFMT_CBM_CFM;
79308145535STzung-Bi Shih }
79408145535STzung-Bi Shih
7955ac15444STzung-Bi Shih if (hdmi_codec && strcmp(dai_link->name, "TDM") == 0) {
796f2024dc5STzung-Bi Shih dai_link->codecs->of_node = hdmi_codec;
7975ac15444STzung-Bi Shih dai_link->ignore = 0;
7985ac15444STzung-Bi Shih }
799f2024dc5STzung-Bi Shih
800f4fb4fefSTzung-Bi Shih if (!dai_link->platforms->name)
801f4fb4fefSTzung-Bi Shih dai_link->platforms->of_node = platform_node;
8022cc3cd5fSTzung-Bi Shih }
80311c02690SShunli Wang
804b812cd58SKuninori Morimoto mt8183_mt6358_ts3a227_max98357_headset_dev.dlc.of_node =
80511c02690SShunli Wang of_parse_phandle(pdev->dev.of_node,
80611c02690SShunli Wang "mediatek,headset-codec", 0);
807b812cd58SKuninori Morimoto if (mt8183_mt6358_ts3a227_max98357_headset_dev.dlc.of_node) {
808a962a809STzung-Bi Shih card->aux_dev = &mt8183_mt6358_ts3a227_max98357_headset_dev;
809a962a809STzung-Bi Shih card->num_aux_devs = 1;
81011c02690SShunli Wang }
81111c02690SShunli Wang
8126191cbdeSJiaxin Yu priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL);
81338eef3beSWang Yufen if (!priv) {
81438eef3beSWang Yufen ret = -ENOMEM;
81538eef3beSWang Yufen goto out;
81638eef3beSWang Yufen }
8176191cbdeSJiaxin Yu
8186191cbdeSJiaxin Yu snd_soc_card_set_drvdata(card, priv);
8196191cbdeSJiaxin Yu
8206191cbdeSJiaxin Yu priv->pinctrl = devm_pinctrl_get(&pdev->dev);
8216191cbdeSJiaxin Yu if (IS_ERR(priv->pinctrl)) {
8226191cbdeSJiaxin Yu dev_err(&pdev->dev, "%s devm_pinctrl_get failed\n",
82311c02690SShunli Wang __func__);
82438eef3beSWang Yufen ret = PTR_ERR(priv->pinctrl);
82538eef3beSWang Yufen goto out;
8266191cbdeSJiaxin Yu }
8276191cbdeSJiaxin Yu
8286191cbdeSJiaxin Yu for (i = 0; i < PIN_STATE_MAX; i++) {
8296191cbdeSJiaxin Yu priv->pin_states[i] = pinctrl_lookup_state(priv->pinctrl,
8306191cbdeSJiaxin Yu mt8183_pin_str[i]);
8316191cbdeSJiaxin Yu if (IS_ERR(priv->pin_states[i])) {
8326191cbdeSJiaxin Yu ret = PTR_ERR(priv->pin_states[i]);
8336191cbdeSJiaxin Yu dev_info(&pdev->dev, "%s Can't find pin state %s %d\n",
8346191cbdeSJiaxin Yu __func__, mt8183_pin_str[i], ret);
8356191cbdeSJiaxin Yu }
8366191cbdeSJiaxin Yu }
8376191cbdeSJiaxin Yu
8386191cbdeSJiaxin Yu if (!IS_ERR(priv->pin_states[PIN_TDM_OUT_OFF])) {
8396191cbdeSJiaxin Yu ret = pinctrl_select_state(priv->pinctrl,
8406191cbdeSJiaxin Yu priv->pin_states[PIN_TDM_OUT_OFF]);
8416191cbdeSJiaxin Yu if (ret)
8426191cbdeSJiaxin Yu dev_info(&pdev->dev,
8436191cbdeSJiaxin Yu "%s failed to select state %d\n",
8446191cbdeSJiaxin Yu __func__, ret);
8456191cbdeSJiaxin Yu }
8466191cbdeSJiaxin Yu
8476191cbdeSJiaxin Yu if (!IS_ERR(priv->pin_states[PIN_STATE_DEFAULT])) {
8486191cbdeSJiaxin Yu ret = pinctrl_select_state(priv->pinctrl,
8496191cbdeSJiaxin Yu priv->pin_states[PIN_STATE_DEFAULT]);
8506191cbdeSJiaxin Yu if (ret)
8516191cbdeSJiaxin Yu dev_info(&pdev->dev,
8526191cbdeSJiaxin Yu "%s failed to select state %d\n",
8536191cbdeSJiaxin Yu __func__, ret);
85411c02690SShunli Wang }
85511c02690SShunli Wang
856cb006006STzung-Bi Shih ret = devm_snd_soc_register_card(&pdev->dev, card);
857cb006006STzung-Bi Shih
85838eef3beSWang Yufen out:
859cb006006STzung-Bi Shih of_node_put(platform_node);
860cb006006STzung-Bi Shih of_node_put(ec_codec);
861cb006006STzung-Bi Shih of_node_put(hdmi_codec);
862cb006006STzung-Bi Shih return ret;
86311c02690SShunli Wang }
86411c02690SShunli Wang
86511c02690SShunli Wang #ifdef CONFIG_OF
86611c02690SShunli Wang static const struct of_device_id mt8183_mt6358_ts3a227_max98357_dt_match[] = {
867f4fb4fefSTzung-Bi Shih {
868f4fb4fefSTzung-Bi Shih .compatible = "mediatek,mt8183_mt6358_ts3a227_max98357",
869f4fb4fefSTzung-Bi Shih .data = &mt8183_mt6358_ts3a227_max98357_card,
870f4fb4fefSTzung-Bi Shih },
871f4fb4fefSTzung-Bi Shih {
87208145535STzung-Bi Shih .compatible = "mediatek,mt8183_mt6358_ts3a227_max98357b",
87308145535STzung-Bi Shih .data = &mt8183_mt6358_ts3a227_max98357b_card,
87408145535STzung-Bi Shih },
87508145535STzung-Bi Shih {
876f4fb4fefSTzung-Bi Shih .compatible = "mediatek,mt8183_mt6358_ts3a227_rt1015",
877f4fb4fefSTzung-Bi Shih .data = &mt8183_mt6358_ts3a227_rt1015_card,
878f4fb4fefSTzung-Bi Shih },
8799dc21a06STzung-Bi Shih {
8809dc21a06STzung-Bi Shih .compatible = "mediatek,mt8183_mt6358_ts3a227_rt1015p",
8819dc21a06STzung-Bi Shih .data = &mt8183_mt6358_ts3a227_rt1015p_card,
8829dc21a06STzung-Bi Shih },
88311c02690SShunli Wang {}
88411c02690SShunli Wang };
885bc63a806SNícolas F. R. A. Prado MODULE_DEVICE_TABLE(of, mt8183_mt6358_ts3a227_max98357_dt_match);
88611c02690SShunli Wang #endif
88711c02690SShunli Wang
88811c02690SShunli Wang static struct platform_driver mt8183_mt6358_ts3a227_max98357_driver = {
88911c02690SShunli Wang .driver = {
890f4fb4fefSTzung-Bi Shih .name = "mt8183_mt6358_ts3a227",
89111c02690SShunli Wang #ifdef CONFIG_OF
89211c02690SShunli Wang .of_match_table = mt8183_mt6358_ts3a227_max98357_dt_match,
89311c02690SShunli Wang #endif
894de96bd7bSTzung-Bi Shih .pm = &snd_soc_pm_ops,
89511c02690SShunli Wang },
89611c02690SShunli Wang .probe = mt8183_mt6358_ts3a227_max98357_dev_probe,
89711c02690SShunli Wang };
89811c02690SShunli Wang
89911c02690SShunli Wang module_platform_driver(mt8183_mt6358_ts3a227_max98357_driver);
90011c02690SShunli Wang
90111c02690SShunli Wang /* Module information */
90211c02690SShunli Wang MODULE_DESCRIPTION("MT8183-MT6358-TS3A227-MAX98357 ALSA SoC machine driver");
90311c02690SShunli Wang MODULE_AUTHOR("Shunli Wang <shunli.wang@mediatek.com>");
90411c02690SShunli Wang MODULE_LICENSE("GPL v2");
90511c02690SShunli Wang MODULE_ALIAS("mt8183_mt6358_ts3a227_max98357 soc card");
906