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" 184dae01c2STzung-Bi Shih #include "mt8183-afe-common.h" 1911c02690SShunli Wang 20f4fb4fefSTzung-Bi Shih #define RT1015_CODEC_DAI "rt1015-aif" 21f4fb4fefSTzung-Bi Shih #define RT1015_DEV0_NAME "rt1015.6-0028" 22f4fb4fefSTzung-Bi Shih #define RT1015_DEV1_NAME "rt1015.6-0029" 23f4fb4fefSTzung-Bi Shih 2496ed7698STzung-Bi Shih enum PINCTRL_PIN_STATE { 2596ed7698STzung-Bi Shih PIN_STATE_DEFAULT = 0, 2696ed7698STzung-Bi Shih PIN_TDM_OUT_ON, 2796ed7698STzung-Bi Shih PIN_TDM_OUT_OFF, 282cc3cd5fSTzung-Bi Shih PIN_WOV, 2996ed7698STzung-Bi Shih PIN_STATE_MAX 3096ed7698STzung-Bi Shih }; 3196ed7698STzung-Bi Shih 3296ed7698STzung-Bi Shih static const char * const mt8183_pin_str[PIN_STATE_MAX] = { 332cc3cd5fSTzung-Bi Shih "default", "aud_tdm_out_on", "aud_tdm_out_off", "wov", 3496ed7698STzung-Bi Shih }; 3596ed7698STzung-Bi Shih 3696ed7698STzung-Bi Shih struct mt8183_mt6358_ts3a227_max98357_priv { 3796ed7698STzung-Bi Shih struct pinctrl *pinctrl; 3896ed7698STzung-Bi Shih struct pinctrl_state *pin_states[PIN_STATE_MAX]; 3988abbf62STzung-Bi Shih struct snd_soc_jack headset_jack, hdmi_jack; 4096ed7698STzung-Bi Shih }; 4196ed7698STzung-Bi Shih 4211c02690SShunli Wang static int mt8183_mt6358_i2s_hw_params(struct snd_pcm_substream *substream, 4311c02690SShunli Wang struct snd_pcm_hw_params *params) 4411c02690SShunli Wang { 450cd08b10SKuninori Morimoto struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); 4611c02690SShunli Wang unsigned int rate = params_rate(params); 4711c02690SShunli Wang unsigned int mclk_fs_ratio = 128; 4811c02690SShunli Wang unsigned int mclk_fs = rate * mclk_fs_ratio; 4911c02690SShunli Wang 50c8ac8212SKuninori Morimoto return snd_soc_dai_set_sysclk(asoc_rtd_to_cpu(rtd, 0), 5111c02690SShunli Wang 0, mclk_fs, SND_SOC_CLOCK_OUT); 5211c02690SShunli Wang } 5311c02690SShunli Wang 5411c02690SShunli Wang static const struct snd_soc_ops mt8183_mt6358_i2s_ops = { 5511c02690SShunli Wang .hw_params = mt8183_mt6358_i2s_hw_params, 5611c02690SShunli Wang }; 5711c02690SShunli Wang 58f4fb4fefSTzung-Bi Shih static int 59f4fb4fefSTzung-Bi Shih mt8183_mt6358_rt1015_i2s_hw_params(struct snd_pcm_substream *substream, 60f4fb4fefSTzung-Bi Shih struct snd_pcm_hw_params *params) 61f4fb4fefSTzung-Bi Shih { 620cd08b10SKuninori Morimoto struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); 63f4fb4fefSTzung-Bi Shih unsigned int rate = params_rate(params); 64f4fb4fefSTzung-Bi Shih unsigned int mclk_fs_ratio = 128; 65f4fb4fefSTzung-Bi Shih unsigned int mclk_fs = rate * mclk_fs_ratio; 66f4fb4fefSTzung-Bi Shih struct snd_soc_card *card = rtd->card; 67f4fb4fefSTzung-Bi Shih struct snd_soc_dai *codec_dai; 68f4fb4fefSTzung-Bi Shih int ret, i; 69f4fb4fefSTzung-Bi Shih 70f4fb4fefSTzung-Bi Shih for_each_rtd_codec_dais(rtd, i, codec_dai) { 71f4fb4fefSTzung-Bi Shih ret = snd_soc_dai_set_pll(codec_dai, 0, RT1015_PLL_S_BCLK, 72f4fb4fefSTzung-Bi Shih rate * 64, rate * 256); 73f4fb4fefSTzung-Bi Shih if (ret < 0) { 74f4fb4fefSTzung-Bi Shih dev_err(card->dev, "failed to set pll\n"); 75f4fb4fefSTzung-Bi Shih return ret; 76f4fb4fefSTzung-Bi Shih } 77f4fb4fefSTzung-Bi Shih 78f4fb4fefSTzung-Bi Shih ret = snd_soc_dai_set_sysclk(codec_dai, RT1015_SCLK_S_PLL, 79f4fb4fefSTzung-Bi Shih rate * 256, SND_SOC_CLOCK_IN); 80f4fb4fefSTzung-Bi Shih if (ret < 0) { 81f4fb4fefSTzung-Bi Shih dev_err(card->dev, "failed to set sysclk\n"); 82f4fb4fefSTzung-Bi Shih return ret; 83f4fb4fefSTzung-Bi Shih } 84f4fb4fefSTzung-Bi Shih } 85f4fb4fefSTzung-Bi Shih 86f4fb4fefSTzung-Bi Shih return snd_soc_dai_set_sysclk(asoc_rtd_to_cpu(rtd, 0), 87f4fb4fefSTzung-Bi Shih 0, mclk_fs, SND_SOC_CLOCK_OUT); 88f4fb4fefSTzung-Bi Shih } 89f4fb4fefSTzung-Bi Shih 90f4fb4fefSTzung-Bi Shih static const struct snd_soc_ops mt8183_mt6358_rt1015_i2s_ops = { 91f4fb4fefSTzung-Bi Shih .hw_params = mt8183_mt6358_rt1015_i2s_hw_params, 92f4fb4fefSTzung-Bi Shih }; 93f4fb4fefSTzung-Bi Shih 9411c02690SShunli Wang static int mt8183_i2s_hw_params_fixup(struct snd_soc_pcm_runtime *rtd, 9511c02690SShunli Wang struct snd_pcm_hw_params *params) 9611c02690SShunli Wang { 9711c02690SShunli Wang dev_dbg(rtd->dev, "%s(), fix format to 32bit\n", __func__); 9811c02690SShunli Wang 9911c02690SShunli Wang /* fix BE i2s format to 32bit, clean param mask first */ 10011c02690SShunli Wang snd_mask_reset_range(hw_param_mask(params, SNDRV_PCM_HW_PARAM_FORMAT), 10111c02690SShunli Wang 0, SNDRV_PCM_FORMAT_LAST); 10211c02690SShunli Wang 10311c02690SShunli Wang params_set_format(params, SNDRV_PCM_FORMAT_S32_LE); 10411c02690SShunli Wang return 0; 10511c02690SShunli Wang } 10611c02690SShunli Wang 107f4fb4fefSTzung-Bi Shih static int mt8183_rt1015_i2s_hw_params_fixup(struct snd_soc_pcm_runtime *rtd, 108f4fb4fefSTzung-Bi Shih struct snd_pcm_hw_params *params) 109f4fb4fefSTzung-Bi Shih { 110f4fb4fefSTzung-Bi Shih dev_dbg(rtd->dev, "%s(), fix format to 32bit\n", __func__); 111f4fb4fefSTzung-Bi Shih 112f4fb4fefSTzung-Bi Shih /* fix BE i2s format to 32bit, clean param mask first */ 113f4fb4fefSTzung-Bi Shih snd_mask_reset_range(hw_param_mask(params, SNDRV_PCM_HW_PARAM_FORMAT), 114f4fb4fefSTzung-Bi Shih 0, SNDRV_PCM_FORMAT_LAST); 115f4fb4fefSTzung-Bi Shih 116f4fb4fefSTzung-Bi Shih params_set_format(params, SNDRV_PCM_FORMAT_S24_LE); 117f4fb4fefSTzung-Bi Shih return 0; 118f4fb4fefSTzung-Bi Shih } 119f4fb4fefSTzung-Bi Shih 1201df1e545STzung-Bi Shih static int 12119657a60SJiaxin Yu mt8183_mt6358_startup(struct snd_pcm_substream *substream) 12219657a60SJiaxin Yu { 12319657a60SJiaxin Yu static const unsigned int rates[] = { 12419657a60SJiaxin Yu 48000, 12519657a60SJiaxin Yu }; 12619657a60SJiaxin Yu static const struct snd_pcm_hw_constraint_list constraints_rates = { 12719657a60SJiaxin Yu .count = ARRAY_SIZE(rates), 12819657a60SJiaxin Yu .list = rates, 12919657a60SJiaxin Yu .mask = 0, 13019657a60SJiaxin Yu }; 13119657a60SJiaxin Yu static const unsigned int channels[] = { 13219657a60SJiaxin Yu 2, 13319657a60SJiaxin Yu }; 13419657a60SJiaxin Yu static const struct snd_pcm_hw_constraint_list constraints_channels = { 13519657a60SJiaxin Yu .count = ARRAY_SIZE(channels), 13619657a60SJiaxin Yu .list = channels, 13719657a60SJiaxin Yu .mask = 0, 13819657a60SJiaxin Yu }; 13919657a60SJiaxin Yu 14019657a60SJiaxin Yu struct snd_pcm_runtime *runtime = substream->runtime; 14119657a60SJiaxin Yu 14219657a60SJiaxin Yu snd_pcm_hw_constraint_list(runtime, 0, 14319657a60SJiaxin Yu SNDRV_PCM_HW_PARAM_RATE, &constraints_rates); 14419657a60SJiaxin Yu runtime->hw.channels_max = 2; 14519657a60SJiaxin Yu snd_pcm_hw_constraint_list(runtime, 0, 14619657a60SJiaxin Yu SNDRV_PCM_HW_PARAM_CHANNELS, 14719657a60SJiaxin Yu &constraints_channels); 14819657a60SJiaxin Yu 14919657a60SJiaxin Yu runtime->hw.formats = SNDRV_PCM_FMTBIT_S16_LE; 15019657a60SJiaxin Yu snd_pcm_hw_constraint_msbits(runtime, 0, 16, 16); 15119657a60SJiaxin Yu 15219657a60SJiaxin Yu return 0; 15319657a60SJiaxin Yu } 15419657a60SJiaxin Yu 15519657a60SJiaxin Yu static const struct snd_soc_ops mt8183_mt6358_ops = { 15619657a60SJiaxin Yu .startup = mt8183_mt6358_startup, 15719657a60SJiaxin Yu }; 15819657a60SJiaxin Yu 15919657a60SJiaxin Yu static int 1601df1e545STzung-Bi Shih mt8183_mt6358_ts3a227_max98357_bt_sco_startup( 1611df1e545STzung-Bi Shih struct snd_pcm_substream *substream) 1621df1e545STzung-Bi Shih { 1631df1e545STzung-Bi Shih static const unsigned int rates[] = { 1641df1e545STzung-Bi Shih 8000, 16000 1651df1e545STzung-Bi Shih }; 1661df1e545STzung-Bi Shih static const struct snd_pcm_hw_constraint_list constraints_rates = { 1671df1e545STzung-Bi Shih .count = ARRAY_SIZE(rates), 1681df1e545STzung-Bi Shih .list = rates, 1691df1e545STzung-Bi Shih .mask = 0, 1701df1e545STzung-Bi Shih }; 1711df1e545STzung-Bi Shih static const unsigned int channels[] = { 1721df1e545STzung-Bi Shih 1, 1731df1e545STzung-Bi Shih }; 1741df1e545STzung-Bi Shih static const struct snd_pcm_hw_constraint_list constraints_channels = { 1751df1e545STzung-Bi Shih .count = ARRAY_SIZE(channels), 1761df1e545STzung-Bi Shih .list = channels, 1771df1e545STzung-Bi Shih .mask = 0, 1781df1e545STzung-Bi Shih }; 1791df1e545STzung-Bi Shih 1801df1e545STzung-Bi Shih struct snd_pcm_runtime *runtime = substream->runtime; 1811df1e545STzung-Bi Shih 1821df1e545STzung-Bi Shih snd_pcm_hw_constraint_list(runtime, 0, 1831df1e545STzung-Bi Shih SNDRV_PCM_HW_PARAM_RATE, &constraints_rates); 1841df1e545STzung-Bi Shih runtime->hw.channels_max = 1; 1851df1e545STzung-Bi Shih snd_pcm_hw_constraint_list(runtime, 0, 1861df1e545STzung-Bi Shih SNDRV_PCM_HW_PARAM_CHANNELS, 1871df1e545STzung-Bi Shih &constraints_channels); 1881df1e545STzung-Bi Shih 1891df1e545STzung-Bi Shih runtime->hw.formats = SNDRV_PCM_FMTBIT_S16_LE; 1901df1e545STzung-Bi Shih snd_pcm_hw_constraint_msbits(runtime, 0, 16, 16); 1911df1e545STzung-Bi Shih 1921df1e545STzung-Bi Shih return 0; 1931df1e545STzung-Bi Shih } 1941df1e545STzung-Bi Shih 1951df1e545STzung-Bi Shih static const struct snd_soc_ops mt8183_mt6358_ts3a227_max98357_bt_sco_ops = { 1961df1e545STzung-Bi Shih .startup = mt8183_mt6358_ts3a227_max98357_bt_sco_startup, 1971df1e545STzung-Bi Shih }; 1981df1e545STzung-Bi Shih 199fa284fd0SKuninori Morimoto /* FE */ 200fa284fd0SKuninori Morimoto SND_SOC_DAILINK_DEFS(playback1, 201fa284fd0SKuninori Morimoto DAILINK_COMP_ARRAY(COMP_CPU("DL1")), 202fa284fd0SKuninori Morimoto DAILINK_COMP_ARRAY(COMP_DUMMY()), 203fa284fd0SKuninori Morimoto DAILINK_COMP_ARRAY(COMP_EMPTY())); 204fa284fd0SKuninori Morimoto 205fa284fd0SKuninori Morimoto SND_SOC_DAILINK_DEFS(playback2, 206fa284fd0SKuninori Morimoto DAILINK_COMP_ARRAY(COMP_CPU("DL2")), 207fa284fd0SKuninori Morimoto DAILINK_COMP_ARRAY(COMP_DUMMY()), 208fa284fd0SKuninori Morimoto DAILINK_COMP_ARRAY(COMP_EMPTY())); 209fa284fd0SKuninori Morimoto 210fa284fd0SKuninori Morimoto SND_SOC_DAILINK_DEFS(playback3, 211fa284fd0SKuninori Morimoto DAILINK_COMP_ARRAY(COMP_CPU("DL3")), 212fa284fd0SKuninori Morimoto DAILINK_COMP_ARRAY(COMP_DUMMY()), 213fa284fd0SKuninori Morimoto DAILINK_COMP_ARRAY(COMP_EMPTY())); 214fa284fd0SKuninori Morimoto 215fa284fd0SKuninori Morimoto SND_SOC_DAILINK_DEFS(capture1, 216fa284fd0SKuninori Morimoto DAILINK_COMP_ARRAY(COMP_CPU("UL1")), 217fa284fd0SKuninori Morimoto DAILINK_COMP_ARRAY(COMP_DUMMY()), 218fa284fd0SKuninori Morimoto DAILINK_COMP_ARRAY(COMP_EMPTY())); 219fa284fd0SKuninori Morimoto 220fa284fd0SKuninori Morimoto SND_SOC_DAILINK_DEFS(capture2, 221fa284fd0SKuninori Morimoto DAILINK_COMP_ARRAY(COMP_CPU("UL2")), 222fa284fd0SKuninori Morimoto DAILINK_COMP_ARRAY(COMP_DUMMY()), 223fa284fd0SKuninori Morimoto DAILINK_COMP_ARRAY(COMP_EMPTY())); 224fa284fd0SKuninori Morimoto 225fa284fd0SKuninori Morimoto SND_SOC_DAILINK_DEFS(capture3, 226fa284fd0SKuninori Morimoto DAILINK_COMP_ARRAY(COMP_CPU("UL3")), 227fa284fd0SKuninori Morimoto DAILINK_COMP_ARRAY(COMP_DUMMY()), 228fa284fd0SKuninori Morimoto DAILINK_COMP_ARRAY(COMP_EMPTY())); 229fa284fd0SKuninori Morimoto 230fa284fd0SKuninori Morimoto SND_SOC_DAILINK_DEFS(capture_mono, 231fa284fd0SKuninori Morimoto DAILINK_COMP_ARRAY(COMP_CPU("UL_MONO_1")), 232fa284fd0SKuninori Morimoto DAILINK_COMP_ARRAY(COMP_DUMMY()), 233fa284fd0SKuninori Morimoto DAILINK_COMP_ARRAY(COMP_EMPTY())); 234fa284fd0SKuninori Morimoto 235fa284fd0SKuninori Morimoto SND_SOC_DAILINK_DEFS(playback_hdmi, 236fa284fd0SKuninori Morimoto DAILINK_COMP_ARRAY(COMP_CPU("HDMI")), 237fa284fd0SKuninori Morimoto DAILINK_COMP_ARRAY(COMP_DUMMY()), 238fa284fd0SKuninori Morimoto DAILINK_COMP_ARRAY(COMP_EMPTY())); 239fa284fd0SKuninori Morimoto 2402cc3cd5fSTzung-Bi Shih SND_SOC_DAILINK_DEFS(wake_on_voice, 2412cc3cd5fSTzung-Bi Shih DAILINK_COMP_ARRAY(COMP_DUMMY()), 2422cc3cd5fSTzung-Bi Shih DAILINK_COMP_ARRAY(COMP_DUMMY()), 2432cc3cd5fSTzung-Bi Shih DAILINK_COMP_ARRAY(COMP_EMPTY())); 2442cc3cd5fSTzung-Bi Shih 245fa284fd0SKuninori Morimoto /* BE */ 246fa284fd0SKuninori Morimoto SND_SOC_DAILINK_DEFS(primary_codec, 247fa284fd0SKuninori Morimoto DAILINK_COMP_ARRAY(COMP_CPU("ADDA")), 248fa284fd0SKuninori Morimoto DAILINK_COMP_ARRAY(COMP_CODEC("mt6358-sound", "mt6358-snd-codec-aif1")), 249fa284fd0SKuninori Morimoto DAILINK_COMP_ARRAY(COMP_EMPTY())); 250fa284fd0SKuninori Morimoto 251fa284fd0SKuninori Morimoto SND_SOC_DAILINK_DEFS(pcm1, 252fa284fd0SKuninori Morimoto DAILINK_COMP_ARRAY(COMP_CPU("PCM 1")), 253fa284fd0SKuninori Morimoto DAILINK_COMP_ARRAY(COMP_DUMMY()), 254fa284fd0SKuninori Morimoto DAILINK_COMP_ARRAY(COMP_EMPTY())); 255fa284fd0SKuninori Morimoto 256fa284fd0SKuninori Morimoto SND_SOC_DAILINK_DEFS(pcm2, 257fa284fd0SKuninori Morimoto DAILINK_COMP_ARRAY(COMP_CPU("PCM 2")), 258fa284fd0SKuninori Morimoto DAILINK_COMP_ARRAY(COMP_DUMMY()), 259fa284fd0SKuninori Morimoto DAILINK_COMP_ARRAY(COMP_EMPTY())); 260fa284fd0SKuninori Morimoto 261fa284fd0SKuninori Morimoto SND_SOC_DAILINK_DEFS(i2s0, 262fa284fd0SKuninori Morimoto DAILINK_COMP_ARRAY(COMP_CPU("I2S0")), 263fa284fd0SKuninori Morimoto DAILINK_COMP_ARRAY(COMP_CODEC("bt-sco", "bt-sco-pcm")), 264fa284fd0SKuninori Morimoto DAILINK_COMP_ARRAY(COMP_EMPTY())); 265fa284fd0SKuninori Morimoto 266fa284fd0SKuninori Morimoto SND_SOC_DAILINK_DEFS(i2s1, 267fa284fd0SKuninori Morimoto DAILINK_COMP_ARRAY(COMP_CPU("I2S1")), 268fa284fd0SKuninori Morimoto DAILINK_COMP_ARRAY(COMP_DUMMY()), 269fa284fd0SKuninori Morimoto DAILINK_COMP_ARRAY(COMP_EMPTY())); 270fa284fd0SKuninori Morimoto 271fa284fd0SKuninori Morimoto SND_SOC_DAILINK_DEFS(i2s2, 272fa284fd0SKuninori Morimoto DAILINK_COMP_ARRAY(COMP_CPU("I2S2")), 273fa284fd0SKuninori Morimoto DAILINK_COMP_ARRAY(COMP_DUMMY()), 274fa284fd0SKuninori Morimoto DAILINK_COMP_ARRAY(COMP_EMPTY())); 275fa284fd0SKuninori Morimoto 276f4fb4fefSTzung-Bi Shih SND_SOC_DAILINK_DEFS(i2s3_max98357a, 277fa284fd0SKuninori Morimoto DAILINK_COMP_ARRAY(COMP_CPU("I2S3")), 278fa284fd0SKuninori Morimoto DAILINK_COMP_ARRAY(COMP_CODEC("max98357a", "HiFi")), 279fa284fd0SKuninori Morimoto DAILINK_COMP_ARRAY(COMP_EMPTY())); 280fa284fd0SKuninori Morimoto 281f4fb4fefSTzung-Bi Shih SND_SOC_DAILINK_DEFS(i2s3_rt1015, 282f4fb4fefSTzung-Bi Shih DAILINK_COMP_ARRAY(COMP_CPU("I2S3")), 283f4fb4fefSTzung-Bi Shih DAILINK_COMP_ARRAY(COMP_CODEC(RT1015_DEV0_NAME, RT1015_CODEC_DAI), 284f4fb4fefSTzung-Bi Shih COMP_CODEC(RT1015_DEV1_NAME, RT1015_CODEC_DAI)), 285f4fb4fefSTzung-Bi Shih DAILINK_COMP_ARRAY(COMP_EMPTY())); 286f4fb4fefSTzung-Bi Shih 287*9dc21a06STzung-Bi Shih SND_SOC_DAILINK_DEFS(i2s3_rt1015p, 288*9dc21a06STzung-Bi Shih DAILINK_COMP_ARRAY(COMP_CPU("I2S3")), 289*9dc21a06STzung-Bi Shih DAILINK_COMP_ARRAY(COMP_CODEC("rt1015p", "HiFi")), 290*9dc21a06STzung-Bi Shih DAILINK_COMP_ARRAY(COMP_EMPTY())); 291*9dc21a06STzung-Bi Shih 292fa284fd0SKuninori Morimoto SND_SOC_DAILINK_DEFS(i2s5, 293fa284fd0SKuninori Morimoto DAILINK_COMP_ARRAY(COMP_CPU("I2S5")), 294fa284fd0SKuninori Morimoto DAILINK_COMP_ARRAY(COMP_CODEC("bt-sco", "bt-sco-pcm")), 295fa284fd0SKuninori Morimoto DAILINK_COMP_ARRAY(COMP_EMPTY())); 296fa284fd0SKuninori Morimoto 297fa284fd0SKuninori Morimoto SND_SOC_DAILINK_DEFS(tdm, 298fa284fd0SKuninori Morimoto DAILINK_COMP_ARRAY(COMP_CPU("TDM")), 299f2024dc5STzung-Bi Shih DAILINK_COMP_ARRAY(COMP_CODEC(NULL, "i2s-hifi")), 300fa284fd0SKuninori Morimoto DAILINK_COMP_ARRAY(COMP_EMPTY())); 301fa284fd0SKuninori Morimoto 3026191cbdeSJiaxin Yu static int mt8183_mt6358_tdm_startup(struct snd_pcm_substream *substream) 3036191cbdeSJiaxin Yu { 3040cd08b10SKuninori Morimoto struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); 3056191cbdeSJiaxin Yu struct mt8183_mt6358_ts3a227_max98357_priv *priv = 3066191cbdeSJiaxin Yu snd_soc_card_get_drvdata(rtd->card); 3076191cbdeSJiaxin Yu int ret; 3086191cbdeSJiaxin Yu 3096191cbdeSJiaxin Yu if (IS_ERR(priv->pin_states[PIN_TDM_OUT_ON])) 3106191cbdeSJiaxin Yu return PTR_ERR(priv->pin_states[PIN_TDM_OUT_ON]); 3116191cbdeSJiaxin Yu 3126191cbdeSJiaxin Yu ret = pinctrl_select_state(priv->pinctrl, 3136191cbdeSJiaxin Yu priv->pin_states[PIN_TDM_OUT_ON]); 3146191cbdeSJiaxin Yu if (ret) 3156191cbdeSJiaxin Yu dev_err(rtd->card->dev, "%s failed to select state %d\n", 3166191cbdeSJiaxin Yu __func__, ret); 3176191cbdeSJiaxin Yu 3186191cbdeSJiaxin Yu return ret; 3196191cbdeSJiaxin Yu } 3206191cbdeSJiaxin Yu 3216191cbdeSJiaxin Yu static void mt8183_mt6358_tdm_shutdown(struct snd_pcm_substream *substream) 3226191cbdeSJiaxin Yu { 3230cd08b10SKuninori Morimoto struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); 3246191cbdeSJiaxin Yu struct mt8183_mt6358_ts3a227_max98357_priv *priv = 3256191cbdeSJiaxin Yu snd_soc_card_get_drvdata(rtd->card); 3266191cbdeSJiaxin Yu int ret; 3276191cbdeSJiaxin Yu 3286191cbdeSJiaxin Yu if (IS_ERR(priv->pin_states[PIN_TDM_OUT_OFF])) 3296191cbdeSJiaxin Yu return; 3306191cbdeSJiaxin Yu 3316191cbdeSJiaxin Yu ret = pinctrl_select_state(priv->pinctrl, 3326191cbdeSJiaxin Yu priv->pin_states[PIN_TDM_OUT_OFF]); 3336191cbdeSJiaxin Yu if (ret) 3346191cbdeSJiaxin Yu dev_err(rtd->card->dev, "%s failed to select state %d\n", 3356191cbdeSJiaxin Yu __func__, ret); 3366191cbdeSJiaxin Yu } 3376191cbdeSJiaxin Yu 3386191cbdeSJiaxin Yu static struct snd_soc_ops mt8183_mt6358_tdm_ops = { 3396191cbdeSJiaxin Yu .startup = mt8183_mt6358_tdm_startup, 3406191cbdeSJiaxin Yu .shutdown = mt8183_mt6358_tdm_shutdown, 3416191cbdeSJiaxin Yu }; 3426191cbdeSJiaxin Yu 3432cc3cd5fSTzung-Bi Shih static int 3442cc3cd5fSTzung-Bi Shih mt8183_mt6358_ts3a227_max98357_wov_startup( 3452cc3cd5fSTzung-Bi Shih struct snd_pcm_substream *substream) 3462cc3cd5fSTzung-Bi Shih { 3470cd08b10SKuninori Morimoto struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); 3482cc3cd5fSTzung-Bi Shih struct snd_soc_card *card = rtd->card; 3492cc3cd5fSTzung-Bi Shih struct mt8183_mt6358_ts3a227_max98357_priv *priv = 3502cc3cd5fSTzung-Bi Shih snd_soc_card_get_drvdata(card); 3512cc3cd5fSTzung-Bi Shih 3522cc3cd5fSTzung-Bi Shih return pinctrl_select_state(priv->pinctrl, 3532cc3cd5fSTzung-Bi Shih priv->pin_states[PIN_WOV]); 3542cc3cd5fSTzung-Bi Shih } 3552cc3cd5fSTzung-Bi Shih 3562cc3cd5fSTzung-Bi Shih static void 3572cc3cd5fSTzung-Bi Shih mt8183_mt6358_ts3a227_max98357_wov_shutdown( 3582cc3cd5fSTzung-Bi Shih struct snd_pcm_substream *substream) 3592cc3cd5fSTzung-Bi Shih { 3600cd08b10SKuninori Morimoto struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); 3612cc3cd5fSTzung-Bi Shih struct snd_soc_card *card = rtd->card; 3622cc3cd5fSTzung-Bi Shih struct mt8183_mt6358_ts3a227_max98357_priv *priv = 3632cc3cd5fSTzung-Bi Shih snd_soc_card_get_drvdata(card); 3642cc3cd5fSTzung-Bi Shih int ret; 3652cc3cd5fSTzung-Bi Shih 3662cc3cd5fSTzung-Bi Shih ret = pinctrl_select_state(priv->pinctrl, 3672cc3cd5fSTzung-Bi Shih priv->pin_states[PIN_STATE_DEFAULT]); 3682cc3cd5fSTzung-Bi Shih if (ret) 3692cc3cd5fSTzung-Bi Shih dev_err(card->dev, "%s failed to select state %d\n", 3702cc3cd5fSTzung-Bi Shih __func__, ret); 3712cc3cd5fSTzung-Bi Shih } 3722cc3cd5fSTzung-Bi Shih 3732cc3cd5fSTzung-Bi Shih static const struct snd_soc_ops mt8183_mt6358_ts3a227_max98357_wov_ops = { 3742cc3cd5fSTzung-Bi Shih .startup = mt8183_mt6358_ts3a227_max98357_wov_startup, 3752cc3cd5fSTzung-Bi Shih .shutdown = mt8183_mt6358_ts3a227_max98357_wov_shutdown, 3762cc3cd5fSTzung-Bi Shih }; 3772cc3cd5fSTzung-Bi Shih 37888abbf62STzung-Bi Shih static int 37988abbf62STzung-Bi Shih mt8183_mt6358_ts3a227_max98357_hdmi_init(struct snd_soc_pcm_runtime *rtd) 38088abbf62STzung-Bi Shih { 38188abbf62STzung-Bi Shih struct mt8183_mt6358_ts3a227_max98357_priv *priv = 38288abbf62STzung-Bi Shih snd_soc_card_get_drvdata(rtd->card); 38388abbf62STzung-Bi Shih int ret; 38488abbf62STzung-Bi Shih 38588abbf62STzung-Bi Shih ret = snd_soc_card_jack_new(rtd->card, "HDMI Jack", SND_JACK_LINEOUT, 38688abbf62STzung-Bi Shih &priv->hdmi_jack, NULL, 0); 38788abbf62STzung-Bi Shih if (ret) 38888abbf62STzung-Bi Shih return ret; 38988abbf62STzung-Bi Shih 39055c5cc63SCheng-Yi Chiang return snd_soc_component_set_jack(asoc_rtd_to_codec(rtd, 0)->component, 39155c5cc63SCheng-Yi Chiang &priv->hdmi_jack, NULL); 39288abbf62STzung-Bi Shih } 39388abbf62STzung-Bi Shih 394f4fb4fefSTzung-Bi Shih static struct snd_soc_dai_link mt8183_mt6358_ts3a227_dai_links[] = { 39511c02690SShunli Wang /* FE */ 39611c02690SShunli Wang { 39711c02690SShunli Wang .name = "Playback_1", 39811c02690SShunli Wang .stream_name = "Playback_1", 39911c02690SShunli Wang .trigger = {SND_SOC_DPCM_TRIGGER_PRE, 40011c02690SShunli Wang SND_SOC_DPCM_TRIGGER_PRE}, 40111c02690SShunli Wang .dynamic = 1, 40211c02690SShunli Wang .dpcm_playback = 1, 40319657a60SJiaxin Yu .ops = &mt8183_mt6358_ops, 404fa284fd0SKuninori Morimoto SND_SOC_DAILINK_REG(playback1), 40511c02690SShunli Wang }, 40611c02690SShunli Wang { 40711c02690SShunli Wang .name = "Playback_2", 40811c02690SShunli Wang .stream_name = "Playback_2", 40911c02690SShunli Wang .trigger = {SND_SOC_DPCM_TRIGGER_PRE, 41011c02690SShunli Wang SND_SOC_DPCM_TRIGGER_PRE}, 41111c02690SShunli Wang .dynamic = 1, 41211c02690SShunli Wang .dpcm_playback = 1, 4131df1e545STzung-Bi Shih .ops = &mt8183_mt6358_ts3a227_max98357_bt_sco_ops, 414fa284fd0SKuninori Morimoto SND_SOC_DAILINK_REG(playback2), 41511c02690SShunli Wang }, 41611c02690SShunli Wang { 41711c02690SShunli Wang .name = "Playback_3", 41811c02690SShunli Wang .stream_name = "Playback_3", 41911c02690SShunli Wang .trigger = {SND_SOC_DPCM_TRIGGER_PRE, 42011c02690SShunli Wang SND_SOC_DPCM_TRIGGER_PRE}, 42111c02690SShunli Wang .dynamic = 1, 42211c02690SShunli Wang .dpcm_playback = 1, 423fa284fd0SKuninori Morimoto SND_SOC_DAILINK_REG(playback3), 42411c02690SShunli Wang }, 42511c02690SShunli Wang { 42611c02690SShunli Wang .name = "Capture_1", 42711c02690SShunli Wang .stream_name = "Capture_1", 42811c02690SShunli Wang .trigger = {SND_SOC_DPCM_TRIGGER_PRE, 42911c02690SShunli Wang SND_SOC_DPCM_TRIGGER_PRE}, 43011c02690SShunli Wang .dynamic = 1, 43111c02690SShunli Wang .dpcm_capture = 1, 4321df1e545STzung-Bi Shih .ops = &mt8183_mt6358_ts3a227_max98357_bt_sco_ops, 433fa284fd0SKuninori Morimoto SND_SOC_DAILINK_REG(capture1), 43411c02690SShunli Wang }, 43511c02690SShunli Wang { 43611c02690SShunli Wang .name = "Capture_2", 43711c02690SShunli Wang .stream_name = "Capture_2", 43811c02690SShunli Wang .trigger = {SND_SOC_DPCM_TRIGGER_PRE, 43911c02690SShunli Wang SND_SOC_DPCM_TRIGGER_PRE}, 44011c02690SShunli Wang .dynamic = 1, 44111c02690SShunli Wang .dpcm_capture = 1, 442fa284fd0SKuninori Morimoto SND_SOC_DAILINK_REG(capture2), 44311c02690SShunli Wang }, 44411c02690SShunli Wang { 44511c02690SShunli Wang .name = "Capture_3", 44611c02690SShunli Wang .stream_name = "Capture_3", 44711c02690SShunli Wang .trigger = {SND_SOC_DPCM_TRIGGER_PRE, 44811c02690SShunli Wang SND_SOC_DPCM_TRIGGER_PRE}, 44911c02690SShunli Wang .dynamic = 1, 45011c02690SShunli Wang .dpcm_capture = 1, 45119657a60SJiaxin Yu .ops = &mt8183_mt6358_ops, 452fa284fd0SKuninori Morimoto SND_SOC_DAILINK_REG(capture3), 45311c02690SShunli Wang }, 45411c02690SShunli Wang { 45511c02690SShunli Wang .name = "Capture_Mono_1", 45611c02690SShunli Wang .stream_name = "Capture_Mono_1", 45711c02690SShunli Wang .trigger = {SND_SOC_DPCM_TRIGGER_PRE, 45811c02690SShunli Wang SND_SOC_DPCM_TRIGGER_PRE}, 45911c02690SShunli Wang .dynamic = 1, 46011c02690SShunli Wang .dpcm_capture = 1, 461fa284fd0SKuninori Morimoto SND_SOC_DAILINK_REG(capture_mono), 46211c02690SShunli Wang }, 46311c02690SShunli Wang { 46411c02690SShunli Wang .name = "Playback_HDMI", 46511c02690SShunli Wang .stream_name = "Playback_HDMI", 46611c02690SShunli Wang .trigger = {SND_SOC_DPCM_TRIGGER_PRE, 46711c02690SShunli Wang SND_SOC_DPCM_TRIGGER_PRE}, 46811c02690SShunli Wang .dynamic = 1, 46911c02690SShunli Wang .dpcm_playback = 1, 470fa284fd0SKuninori Morimoto SND_SOC_DAILINK_REG(playback_hdmi), 47111c02690SShunli Wang }, 4722cc3cd5fSTzung-Bi Shih { 4732cc3cd5fSTzung-Bi Shih .name = "Wake on Voice", 4742cc3cd5fSTzung-Bi Shih .stream_name = "Wake on Voice", 4752cc3cd5fSTzung-Bi Shih .ignore_suspend = 1, 4762cc3cd5fSTzung-Bi Shih .ignore = 1, 4772cc3cd5fSTzung-Bi Shih SND_SOC_DAILINK_REG(wake_on_voice), 4782cc3cd5fSTzung-Bi Shih .ops = &mt8183_mt6358_ts3a227_max98357_wov_ops, 4792cc3cd5fSTzung-Bi Shih }, 4802cc3cd5fSTzung-Bi Shih 48111c02690SShunli Wang /* BE */ 48211c02690SShunli Wang { 48311c02690SShunli Wang .name = "Primary Codec", 48411c02690SShunli Wang .no_pcm = 1, 48511c02690SShunli Wang .dpcm_playback = 1, 48611c02690SShunli Wang .dpcm_capture = 1, 48711c02690SShunli Wang .ignore_suspend = 1, 488fa284fd0SKuninori Morimoto SND_SOC_DAILINK_REG(primary_codec), 48911c02690SShunli Wang }, 49011c02690SShunli Wang { 49111c02690SShunli Wang .name = "PCM 1", 49211c02690SShunli Wang .no_pcm = 1, 49311c02690SShunli Wang .dpcm_playback = 1, 49411c02690SShunli Wang .dpcm_capture = 1, 49511c02690SShunli Wang .ignore_suspend = 1, 496fa284fd0SKuninori Morimoto SND_SOC_DAILINK_REG(pcm1), 49711c02690SShunli Wang }, 49811c02690SShunli Wang { 49911c02690SShunli Wang .name = "PCM 2", 50011c02690SShunli Wang .no_pcm = 1, 50111c02690SShunli Wang .dpcm_playback = 1, 50211c02690SShunli Wang .dpcm_capture = 1, 50311c02690SShunli Wang .ignore_suspend = 1, 504fa284fd0SKuninori Morimoto SND_SOC_DAILINK_REG(pcm2), 50511c02690SShunli Wang }, 50611c02690SShunli Wang { 50711c02690SShunli Wang .name = "I2S0", 50811c02690SShunli Wang .no_pcm = 1, 50911c02690SShunli Wang .dpcm_capture = 1, 51011c02690SShunli Wang .ignore_suspend = 1, 51111c02690SShunli Wang .be_hw_params_fixup = mt8183_i2s_hw_params_fixup, 51211c02690SShunli Wang .ops = &mt8183_mt6358_i2s_ops, 513fa284fd0SKuninori Morimoto SND_SOC_DAILINK_REG(i2s0), 51411c02690SShunli Wang }, 51511c02690SShunli Wang { 51611c02690SShunli Wang .name = "I2S1", 51711c02690SShunli Wang .no_pcm = 1, 51811c02690SShunli Wang .dpcm_playback = 1, 51911c02690SShunli Wang .ignore_suspend = 1, 52011c02690SShunli Wang .be_hw_params_fixup = mt8183_i2s_hw_params_fixup, 52111c02690SShunli Wang .ops = &mt8183_mt6358_i2s_ops, 522fa284fd0SKuninori Morimoto SND_SOC_DAILINK_REG(i2s1), 52311c02690SShunli Wang }, 52411c02690SShunli Wang { 52511c02690SShunli Wang .name = "I2S2", 52611c02690SShunli Wang .no_pcm = 1, 52711c02690SShunli Wang .dpcm_capture = 1, 52811c02690SShunli Wang .ignore_suspend = 1, 52911c02690SShunli Wang .be_hw_params_fixup = mt8183_i2s_hw_params_fixup, 53011c02690SShunli Wang .ops = &mt8183_mt6358_i2s_ops, 531fa284fd0SKuninori Morimoto SND_SOC_DAILINK_REG(i2s2), 53211c02690SShunli Wang }, 53311c02690SShunli Wang { 53411c02690SShunli Wang .name = "I2S3", 53511c02690SShunli Wang .no_pcm = 1, 53611c02690SShunli Wang .dpcm_playback = 1, 53711c02690SShunli Wang .ignore_suspend = 1, 53811c02690SShunli Wang }, 53911c02690SShunli Wang { 54011c02690SShunli Wang .name = "I2S5", 54111c02690SShunli Wang .no_pcm = 1, 54211c02690SShunli Wang .dpcm_playback = 1, 54311c02690SShunli Wang .ignore_suspend = 1, 54411c02690SShunli Wang .be_hw_params_fixup = mt8183_i2s_hw_params_fixup, 54511c02690SShunli Wang .ops = &mt8183_mt6358_i2s_ops, 546fa284fd0SKuninori Morimoto SND_SOC_DAILINK_REG(i2s5), 54711c02690SShunli Wang }, 54811c02690SShunli Wang { 54911c02690SShunli Wang .name = "TDM", 55011c02690SShunli Wang .no_pcm = 1, 5518e58c521SJiaxin Yu .dai_fmt = SND_SOC_DAIFMT_I2S | 5528e58c521SJiaxin Yu SND_SOC_DAIFMT_IB_IF | 5538e58c521SJiaxin Yu SND_SOC_DAIFMT_CBM_CFM, 55411c02690SShunli Wang .dpcm_playback = 1, 55511c02690SShunli Wang .ignore_suspend = 1, 5566191cbdeSJiaxin Yu .be_hw_params_fixup = mt8183_i2s_hw_params_fixup, 5576191cbdeSJiaxin Yu .ops = &mt8183_mt6358_tdm_ops, 5585ac15444STzung-Bi Shih .ignore = 1, 55988abbf62STzung-Bi Shih .init = mt8183_mt6358_ts3a227_max98357_hdmi_init, 560fa284fd0SKuninori Morimoto SND_SOC_DAILINK_REG(tdm), 56111c02690SShunli Wang }, 56211c02690SShunli Wang }; 56311c02690SShunli Wang 56411c02690SShunli Wang static struct snd_soc_card mt8183_mt6358_ts3a227_max98357_card = { 56511c02690SShunli Wang .name = "mt8183_mt6358_ts3a227_max98357", 56611c02690SShunli Wang .owner = THIS_MODULE, 567f4fb4fefSTzung-Bi Shih .dai_link = mt8183_mt6358_ts3a227_dai_links, 568f4fb4fefSTzung-Bi Shih .num_links = ARRAY_SIZE(mt8183_mt6358_ts3a227_dai_links), 569f4fb4fefSTzung-Bi Shih }; 570f4fb4fefSTzung-Bi Shih 57108145535STzung-Bi Shih static struct snd_soc_card mt8183_mt6358_ts3a227_max98357b_card = { 57208145535STzung-Bi Shih .name = "mt8183_mt6358_ts3a227_max98357b", 57308145535STzung-Bi Shih .owner = THIS_MODULE, 57408145535STzung-Bi Shih .dai_link = mt8183_mt6358_ts3a227_dai_links, 57508145535STzung-Bi Shih .num_links = ARRAY_SIZE(mt8183_mt6358_ts3a227_dai_links), 57608145535STzung-Bi Shih }; 57708145535STzung-Bi Shih 578f4fb4fefSTzung-Bi Shih static struct snd_soc_codec_conf mt8183_mt6358_ts3a227_rt1015_amp_conf[] = { 579f4fb4fefSTzung-Bi Shih { 580f4fb4fefSTzung-Bi Shih .dlc = COMP_CODEC_CONF(RT1015_DEV0_NAME), 581f4fb4fefSTzung-Bi Shih .name_prefix = "Left", 582f4fb4fefSTzung-Bi Shih }, 583f4fb4fefSTzung-Bi Shih { 584f4fb4fefSTzung-Bi Shih .dlc = COMP_CODEC_CONF(RT1015_DEV1_NAME), 585f4fb4fefSTzung-Bi Shih .name_prefix = "Right", 586f4fb4fefSTzung-Bi Shih }, 587f4fb4fefSTzung-Bi Shih }; 588f4fb4fefSTzung-Bi Shih 589f4fb4fefSTzung-Bi Shih static struct snd_soc_card mt8183_mt6358_ts3a227_rt1015_card = { 590f4fb4fefSTzung-Bi Shih .name = "mt8183_mt6358_ts3a227_rt1015", 591f4fb4fefSTzung-Bi Shih .owner = THIS_MODULE, 592f4fb4fefSTzung-Bi Shih .dai_link = mt8183_mt6358_ts3a227_dai_links, 593f4fb4fefSTzung-Bi Shih .num_links = ARRAY_SIZE(mt8183_mt6358_ts3a227_dai_links), 594f4fb4fefSTzung-Bi Shih .codec_conf = mt8183_mt6358_ts3a227_rt1015_amp_conf, 595f4fb4fefSTzung-Bi Shih .num_configs = ARRAY_SIZE(mt8183_mt6358_ts3a227_rt1015_amp_conf), 59611c02690SShunli Wang }; 59711c02690SShunli Wang 598*9dc21a06STzung-Bi Shih static struct snd_soc_card mt8183_mt6358_ts3a227_rt1015p_card = { 599*9dc21a06STzung-Bi Shih .name = "mt8183_mt6358_ts3a227_rt1015p", 600*9dc21a06STzung-Bi Shih .owner = THIS_MODULE, 601*9dc21a06STzung-Bi Shih .dai_link = mt8183_mt6358_ts3a227_dai_links, 602*9dc21a06STzung-Bi Shih .num_links = ARRAY_SIZE(mt8183_mt6358_ts3a227_dai_links), 603*9dc21a06STzung-Bi Shih }; 604*9dc21a06STzung-Bi Shih 60511c02690SShunli Wang static int 60611c02690SShunli Wang mt8183_mt6358_ts3a227_max98357_headset_init(struct snd_soc_component *component) 60711c02690SShunli Wang { 60811c02690SShunli Wang int ret; 60995d779b4STzung-Bi Shih struct mt8183_mt6358_ts3a227_max98357_priv *priv = 61095d779b4STzung-Bi Shih snd_soc_card_get_drvdata(component->card); 61111c02690SShunli Wang 61211c02690SShunli Wang /* Enable Headset and 4 Buttons Jack detection */ 613f4fb4fefSTzung-Bi Shih ret = snd_soc_card_jack_new(component->card, 61411c02690SShunli Wang "Headset Jack", 61511c02690SShunli Wang SND_JACK_HEADSET | 61611c02690SShunli Wang SND_JACK_BTN_0 | SND_JACK_BTN_1 | 61711c02690SShunli Wang SND_JACK_BTN_2 | SND_JACK_BTN_3, 61895d779b4STzung-Bi Shih &priv->headset_jack, 619108d0d40STzung-Bi Shih NULL, 0); 62011c02690SShunli Wang if (ret) 62111c02690SShunli Wang return ret; 62211c02690SShunli Wang 62395d779b4STzung-Bi Shih ret = ts3a227e_enable_jack_detect(component, &priv->headset_jack); 62411c02690SShunli Wang 62511c02690SShunli Wang return ret; 62611c02690SShunli Wang } 62711c02690SShunli Wang 628fc347483STzung-Bi Shih static struct snd_soc_aux_dev mt8183_mt6358_ts3a227_max98357_headset_dev = { 629fc347483STzung-Bi Shih .dlc = COMP_EMPTY(), 630fc347483STzung-Bi Shih .init = mt8183_mt6358_ts3a227_max98357_headset_init, 631fc347483STzung-Bi Shih }; 632fc347483STzung-Bi Shih 63311c02690SShunli Wang static int 63411c02690SShunli Wang mt8183_mt6358_ts3a227_max98357_dev_probe(struct platform_device *pdev) 63511c02690SShunli Wang { 636f4fb4fefSTzung-Bi Shih struct snd_soc_card *card; 637f2024dc5STzung-Bi Shih struct device_node *platform_node, *ec_codec, *hdmi_codec; 63811c02690SShunli Wang struct snd_soc_dai_link *dai_link; 6396191cbdeSJiaxin Yu struct mt8183_mt6358_ts3a227_max98357_priv *priv; 640f4fb4fefSTzung-Bi Shih const struct of_device_id *match; 641f4fb4fefSTzung-Bi Shih int ret, i; 64211c02690SShunli Wang 64311c02690SShunli Wang platform_node = of_parse_phandle(pdev->dev.of_node, 64411c02690SShunli Wang "mediatek,platform", 0); 64511c02690SShunli Wang if (!platform_node) { 64611c02690SShunli Wang dev_err(&pdev->dev, "Property 'platform' missing or invalid\n"); 64711c02690SShunli Wang return -EINVAL; 64811c02690SShunli Wang } 64911c02690SShunli Wang 650f4fb4fefSTzung-Bi Shih match = of_match_device(pdev->dev.driver->of_match_table, &pdev->dev); 651f4fb4fefSTzung-Bi Shih if (!match || !match->data) 652f4fb4fefSTzung-Bi Shih return -EINVAL; 653f4fb4fefSTzung-Bi Shih 654f4fb4fefSTzung-Bi Shih card = (struct snd_soc_card *)match->data; 655f4fb4fefSTzung-Bi Shih card->dev = &pdev->dev; 656f4fb4fefSTzung-Bi Shih 6572cc3cd5fSTzung-Bi Shih ec_codec = of_parse_phandle(pdev->dev.of_node, "mediatek,ec-codec", 0); 658f2024dc5STzung-Bi Shih hdmi_codec = of_parse_phandle(pdev->dev.of_node, 659f2024dc5STzung-Bi Shih "mediatek,hdmi-codec", 0); 6602cc3cd5fSTzung-Bi Shih 66111c02690SShunli Wang for_each_card_prelinks(card, i, dai_link) { 6622cc3cd5fSTzung-Bi Shih if (ec_codec && strcmp(dai_link->name, "Wake on Voice") == 0) { 6632cc3cd5fSTzung-Bi Shih dai_link->cpus[0].name = NULL; 6642cc3cd5fSTzung-Bi Shih dai_link->cpus[0].of_node = ec_codec; 6652cc3cd5fSTzung-Bi Shih dai_link->cpus[0].dai_name = NULL; 6662cc3cd5fSTzung-Bi Shih dai_link->codecs[0].name = NULL; 6672cc3cd5fSTzung-Bi Shih dai_link->codecs[0].of_node = ec_codec; 6682cc3cd5fSTzung-Bi Shih dai_link->codecs[0].dai_name = "Wake on Voice"; 6692cc3cd5fSTzung-Bi Shih dai_link->platforms[0].of_node = ec_codec; 6702cc3cd5fSTzung-Bi Shih dai_link->ignore = 0; 67111c02690SShunli Wang } 672f4fb4fefSTzung-Bi Shih 673f4fb4fefSTzung-Bi Shih if (strcmp(dai_link->name, "I2S3") == 0) { 67408145535STzung-Bi Shih if (card == &mt8183_mt6358_ts3a227_max98357_card || 67508145535STzung-Bi Shih card == &mt8183_mt6358_ts3a227_max98357b_card) { 676f4fb4fefSTzung-Bi Shih dai_link->be_hw_params_fixup = 677f4fb4fefSTzung-Bi Shih mt8183_i2s_hw_params_fixup; 678f4fb4fefSTzung-Bi Shih dai_link->ops = &mt8183_mt6358_i2s_ops; 679f4fb4fefSTzung-Bi Shih dai_link->cpus = i2s3_max98357a_cpus; 680f4fb4fefSTzung-Bi Shih dai_link->num_cpus = 681f4fb4fefSTzung-Bi Shih ARRAY_SIZE(i2s3_max98357a_cpus); 682f4fb4fefSTzung-Bi Shih dai_link->codecs = i2s3_max98357a_codecs; 683f4fb4fefSTzung-Bi Shih dai_link->num_codecs = 684f4fb4fefSTzung-Bi Shih ARRAY_SIZE(i2s3_max98357a_codecs); 685f4fb4fefSTzung-Bi Shih dai_link->platforms = i2s3_max98357a_platforms; 686f4fb4fefSTzung-Bi Shih dai_link->num_platforms = 687f4fb4fefSTzung-Bi Shih ARRAY_SIZE(i2s3_max98357a_platforms); 688f4fb4fefSTzung-Bi Shih } else if (card == &mt8183_mt6358_ts3a227_rt1015_card) { 689f4fb4fefSTzung-Bi Shih dai_link->be_hw_params_fixup = 690f4fb4fefSTzung-Bi Shih mt8183_rt1015_i2s_hw_params_fixup; 691f4fb4fefSTzung-Bi Shih dai_link->ops = &mt8183_mt6358_rt1015_i2s_ops; 692f4fb4fefSTzung-Bi Shih dai_link->cpus = i2s3_rt1015_cpus; 693f4fb4fefSTzung-Bi Shih dai_link->num_cpus = 694f4fb4fefSTzung-Bi Shih ARRAY_SIZE(i2s3_rt1015_cpus); 695f4fb4fefSTzung-Bi Shih dai_link->codecs = i2s3_rt1015_codecs; 696f4fb4fefSTzung-Bi Shih dai_link->num_codecs = 697f4fb4fefSTzung-Bi Shih ARRAY_SIZE(i2s3_rt1015_codecs); 698f4fb4fefSTzung-Bi Shih dai_link->platforms = i2s3_rt1015_platforms; 699f4fb4fefSTzung-Bi Shih dai_link->num_platforms = 700f4fb4fefSTzung-Bi Shih ARRAY_SIZE(i2s3_rt1015_platforms); 701*9dc21a06STzung-Bi Shih } else if (card == &mt8183_mt6358_ts3a227_rt1015p_card) { 702*9dc21a06STzung-Bi Shih dai_link->be_hw_params_fixup = 703*9dc21a06STzung-Bi Shih mt8183_rt1015_i2s_hw_params_fixup; 704*9dc21a06STzung-Bi Shih dai_link->ops = &mt8183_mt6358_i2s_ops; 705*9dc21a06STzung-Bi Shih dai_link->cpus = i2s3_rt1015p_cpus; 706*9dc21a06STzung-Bi Shih dai_link->num_cpus = 707*9dc21a06STzung-Bi Shih ARRAY_SIZE(i2s3_rt1015p_cpus); 708*9dc21a06STzung-Bi Shih dai_link->codecs = i2s3_rt1015p_codecs; 709*9dc21a06STzung-Bi Shih dai_link->num_codecs = 710*9dc21a06STzung-Bi Shih ARRAY_SIZE(i2s3_rt1015p_codecs); 711*9dc21a06STzung-Bi Shih dai_link->platforms = i2s3_rt1015p_platforms; 712*9dc21a06STzung-Bi Shih dai_link->num_platforms = 713*9dc21a06STzung-Bi Shih ARRAY_SIZE(i2s3_rt1015p_platforms); 714f4fb4fefSTzung-Bi Shih } 715f4fb4fefSTzung-Bi Shih } 716f4fb4fefSTzung-Bi Shih 71708145535STzung-Bi Shih if (card == &mt8183_mt6358_ts3a227_max98357b_card) { 71808145535STzung-Bi Shih if (strcmp(dai_link->name, "I2S2") == 0 || 71908145535STzung-Bi Shih strcmp(dai_link->name, "I2S3") == 0) 72008145535STzung-Bi Shih dai_link->dai_fmt = SND_SOC_DAIFMT_LEFT_J | 72108145535STzung-Bi Shih SND_SOC_DAIFMT_NB_NF | 72208145535STzung-Bi Shih SND_SOC_DAIFMT_CBM_CFM; 72308145535STzung-Bi Shih } 72408145535STzung-Bi Shih 7255ac15444STzung-Bi Shih if (hdmi_codec && strcmp(dai_link->name, "TDM") == 0) { 726f2024dc5STzung-Bi Shih dai_link->codecs->of_node = hdmi_codec; 7275ac15444STzung-Bi Shih dai_link->ignore = 0; 7285ac15444STzung-Bi Shih } 729f2024dc5STzung-Bi Shih 730f4fb4fefSTzung-Bi Shih if (!dai_link->platforms->name) 731f4fb4fefSTzung-Bi Shih dai_link->platforms->of_node = platform_node; 7322cc3cd5fSTzung-Bi Shih } 73311c02690SShunli Wang 734b812cd58SKuninori Morimoto mt8183_mt6358_ts3a227_max98357_headset_dev.dlc.of_node = 73511c02690SShunli Wang of_parse_phandle(pdev->dev.of_node, 73611c02690SShunli Wang "mediatek,headset-codec", 0); 737b812cd58SKuninori Morimoto if (mt8183_mt6358_ts3a227_max98357_headset_dev.dlc.of_node) { 738a962a809STzung-Bi Shih card->aux_dev = &mt8183_mt6358_ts3a227_max98357_headset_dev; 739a962a809STzung-Bi Shih card->num_aux_devs = 1; 74011c02690SShunli Wang } 74111c02690SShunli Wang 7426191cbdeSJiaxin Yu priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL); 7436191cbdeSJiaxin Yu if (!priv) 7446191cbdeSJiaxin Yu return -ENOMEM; 7456191cbdeSJiaxin Yu 7466191cbdeSJiaxin Yu snd_soc_card_set_drvdata(card, priv); 7476191cbdeSJiaxin Yu 7486191cbdeSJiaxin Yu priv->pinctrl = devm_pinctrl_get(&pdev->dev); 7496191cbdeSJiaxin Yu if (IS_ERR(priv->pinctrl)) { 7506191cbdeSJiaxin Yu dev_err(&pdev->dev, "%s devm_pinctrl_get failed\n", 75111c02690SShunli Wang __func__); 7526191cbdeSJiaxin Yu return PTR_ERR(priv->pinctrl); 7536191cbdeSJiaxin Yu } 7546191cbdeSJiaxin Yu 7556191cbdeSJiaxin Yu for (i = 0; i < PIN_STATE_MAX; i++) { 7566191cbdeSJiaxin Yu priv->pin_states[i] = pinctrl_lookup_state(priv->pinctrl, 7576191cbdeSJiaxin Yu mt8183_pin_str[i]); 7586191cbdeSJiaxin Yu if (IS_ERR(priv->pin_states[i])) { 7596191cbdeSJiaxin Yu ret = PTR_ERR(priv->pin_states[i]); 7606191cbdeSJiaxin Yu dev_info(&pdev->dev, "%s Can't find pin state %s %d\n", 7616191cbdeSJiaxin Yu __func__, mt8183_pin_str[i], ret); 7626191cbdeSJiaxin Yu } 7636191cbdeSJiaxin Yu } 7646191cbdeSJiaxin Yu 7656191cbdeSJiaxin Yu if (!IS_ERR(priv->pin_states[PIN_TDM_OUT_OFF])) { 7666191cbdeSJiaxin Yu ret = pinctrl_select_state(priv->pinctrl, 7676191cbdeSJiaxin Yu priv->pin_states[PIN_TDM_OUT_OFF]); 7686191cbdeSJiaxin Yu if (ret) 7696191cbdeSJiaxin Yu dev_info(&pdev->dev, 7706191cbdeSJiaxin Yu "%s failed to select state %d\n", 7716191cbdeSJiaxin Yu __func__, ret); 7726191cbdeSJiaxin Yu } 7736191cbdeSJiaxin Yu 7746191cbdeSJiaxin Yu if (!IS_ERR(priv->pin_states[PIN_STATE_DEFAULT])) { 7756191cbdeSJiaxin Yu ret = pinctrl_select_state(priv->pinctrl, 7766191cbdeSJiaxin Yu priv->pin_states[PIN_STATE_DEFAULT]); 7776191cbdeSJiaxin Yu if (ret) 7786191cbdeSJiaxin Yu dev_info(&pdev->dev, 7796191cbdeSJiaxin Yu "%s failed to select state %d\n", 7806191cbdeSJiaxin Yu __func__, ret); 78111c02690SShunli Wang } 78211c02690SShunli Wang 78363ba8e4dSTzung-Bi Shih return devm_snd_soc_register_card(&pdev->dev, card); 78411c02690SShunli Wang } 78511c02690SShunli Wang 78611c02690SShunli Wang #ifdef CONFIG_OF 78711c02690SShunli Wang static const struct of_device_id mt8183_mt6358_ts3a227_max98357_dt_match[] = { 788f4fb4fefSTzung-Bi Shih { 789f4fb4fefSTzung-Bi Shih .compatible = "mediatek,mt8183_mt6358_ts3a227_max98357", 790f4fb4fefSTzung-Bi Shih .data = &mt8183_mt6358_ts3a227_max98357_card, 791f4fb4fefSTzung-Bi Shih }, 792f4fb4fefSTzung-Bi Shih { 79308145535STzung-Bi Shih .compatible = "mediatek,mt8183_mt6358_ts3a227_max98357b", 79408145535STzung-Bi Shih .data = &mt8183_mt6358_ts3a227_max98357b_card, 79508145535STzung-Bi Shih }, 79608145535STzung-Bi Shih { 797f4fb4fefSTzung-Bi Shih .compatible = "mediatek,mt8183_mt6358_ts3a227_rt1015", 798f4fb4fefSTzung-Bi Shih .data = &mt8183_mt6358_ts3a227_rt1015_card, 799f4fb4fefSTzung-Bi Shih }, 800*9dc21a06STzung-Bi Shih { 801*9dc21a06STzung-Bi Shih .compatible = "mediatek,mt8183_mt6358_ts3a227_rt1015p", 802*9dc21a06STzung-Bi Shih .data = &mt8183_mt6358_ts3a227_rt1015p_card, 803*9dc21a06STzung-Bi Shih }, 80411c02690SShunli Wang {} 80511c02690SShunli Wang }; 80611c02690SShunli Wang #endif 80711c02690SShunli Wang 80811c02690SShunli Wang static struct platform_driver mt8183_mt6358_ts3a227_max98357_driver = { 80911c02690SShunli Wang .driver = { 810f4fb4fefSTzung-Bi Shih .name = "mt8183_mt6358_ts3a227", 81111c02690SShunli Wang #ifdef CONFIG_OF 81211c02690SShunli Wang .of_match_table = mt8183_mt6358_ts3a227_max98357_dt_match, 81311c02690SShunli Wang #endif 814de96bd7bSTzung-Bi Shih .pm = &snd_soc_pm_ops, 81511c02690SShunli Wang }, 81611c02690SShunli Wang .probe = mt8183_mt6358_ts3a227_max98357_dev_probe, 81711c02690SShunli Wang }; 81811c02690SShunli Wang 81911c02690SShunli Wang module_platform_driver(mt8183_mt6358_ts3a227_max98357_driver); 82011c02690SShunli Wang 82111c02690SShunli Wang /* Module information */ 82211c02690SShunli Wang MODULE_DESCRIPTION("MT8183-MT6358-TS3A227-MAX98357 ALSA SoC machine driver"); 82311c02690SShunli Wang MODULE_AUTHOR("Shunli Wang <shunli.wang@mediatek.com>"); 82411c02690SShunli Wang MODULE_LICENSE("GPL v2"); 82511c02690SShunli Wang MODULE_ALIAS("mt8183_mt6358_ts3a227_max98357 soc card"); 826