18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0 28c2ecf20Sopenharmony_ci// 38c2ecf20Sopenharmony_ci// mt8183-mt6358.c -- 48c2ecf20Sopenharmony_ci// MT8183-MT6358-TS3A227-MAX98357 ALSA SoC machine driver 58c2ecf20Sopenharmony_ci// 68c2ecf20Sopenharmony_ci// Copyright (c) 2018 MediaTek Inc. 78c2ecf20Sopenharmony_ci// Author: Shunli Wang <shunli.wang@mediatek.com> 88c2ecf20Sopenharmony_ci 98c2ecf20Sopenharmony_ci#include <linux/module.h> 108c2ecf20Sopenharmony_ci#include <linux/of_device.h> 118c2ecf20Sopenharmony_ci#include <linux/pinctrl/consumer.h> 128c2ecf20Sopenharmony_ci#include <sound/jack.h> 138c2ecf20Sopenharmony_ci#include <sound/pcm_params.h> 148c2ecf20Sopenharmony_ci#include <sound/soc.h> 158c2ecf20Sopenharmony_ci 168c2ecf20Sopenharmony_ci#include "../../codecs/rt1015.h" 178c2ecf20Sopenharmony_ci#include "../../codecs/ts3a227e.h" 188c2ecf20Sopenharmony_ci#include "mt8183-afe-common.h" 198c2ecf20Sopenharmony_ci 208c2ecf20Sopenharmony_ci#define RT1015_CODEC_DAI "rt1015-aif" 218c2ecf20Sopenharmony_ci#define RT1015_DEV0_NAME "rt1015.6-0028" 228c2ecf20Sopenharmony_ci#define RT1015_DEV1_NAME "rt1015.6-0029" 238c2ecf20Sopenharmony_ci 248c2ecf20Sopenharmony_cienum PINCTRL_PIN_STATE { 258c2ecf20Sopenharmony_ci PIN_STATE_DEFAULT = 0, 268c2ecf20Sopenharmony_ci PIN_TDM_OUT_ON, 278c2ecf20Sopenharmony_ci PIN_TDM_OUT_OFF, 288c2ecf20Sopenharmony_ci PIN_WOV, 298c2ecf20Sopenharmony_ci PIN_STATE_MAX 308c2ecf20Sopenharmony_ci}; 318c2ecf20Sopenharmony_ci 328c2ecf20Sopenharmony_cistatic const char * const mt8183_pin_str[PIN_STATE_MAX] = { 338c2ecf20Sopenharmony_ci "default", "aud_tdm_out_on", "aud_tdm_out_off", "wov", 348c2ecf20Sopenharmony_ci}; 358c2ecf20Sopenharmony_ci 368c2ecf20Sopenharmony_cistruct mt8183_mt6358_ts3a227_max98357_priv { 378c2ecf20Sopenharmony_ci struct pinctrl *pinctrl; 388c2ecf20Sopenharmony_ci struct pinctrl_state *pin_states[PIN_STATE_MAX]; 398c2ecf20Sopenharmony_ci struct snd_soc_jack headset_jack, hdmi_jack; 408c2ecf20Sopenharmony_ci}; 418c2ecf20Sopenharmony_ci 428c2ecf20Sopenharmony_cistatic int mt8183_mt6358_i2s_hw_params(struct snd_pcm_substream *substream, 438c2ecf20Sopenharmony_ci struct snd_pcm_hw_params *params) 448c2ecf20Sopenharmony_ci{ 458c2ecf20Sopenharmony_ci struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); 468c2ecf20Sopenharmony_ci unsigned int rate = params_rate(params); 478c2ecf20Sopenharmony_ci unsigned int mclk_fs_ratio = 128; 488c2ecf20Sopenharmony_ci unsigned int mclk_fs = rate * mclk_fs_ratio; 498c2ecf20Sopenharmony_ci 508c2ecf20Sopenharmony_ci return snd_soc_dai_set_sysclk(asoc_rtd_to_cpu(rtd, 0), 518c2ecf20Sopenharmony_ci 0, mclk_fs, SND_SOC_CLOCK_OUT); 528c2ecf20Sopenharmony_ci} 538c2ecf20Sopenharmony_ci 548c2ecf20Sopenharmony_cistatic const struct snd_soc_ops mt8183_mt6358_i2s_ops = { 558c2ecf20Sopenharmony_ci .hw_params = mt8183_mt6358_i2s_hw_params, 568c2ecf20Sopenharmony_ci}; 578c2ecf20Sopenharmony_ci 588c2ecf20Sopenharmony_cistatic int 598c2ecf20Sopenharmony_cimt8183_mt6358_rt1015_i2s_hw_params(struct snd_pcm_substream *substream, 608c2ecf20Sopenharmony_ci struct snd_pcm_hw_params *params) 618c2ecf20Sopenharmony_ci{ 628c2ecf20Sopenharmony_ci struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); 638c2ecf20Sopenharmony_ci unsigned int rate = params_rate(params); 648c2ecf20Sopenharmony_ci unsigned int mclk_fs_ratio = 128; 658c2ecf20Sopenharmony_ci unsigned int mclk_fs = rate * mclk_fs_ratio; 668c2ecf20Sopenharmony_ci struct snd_soc_card *card = rtd->card; 678c2ecf20Sopenharmony_ci struct snd_soc_dai *codec_dai; 688c2ecf20Sopenharmony_ci int ret, i; 698c2ecf20Sopenharmony_ci 708c2ecf20Sopenharmony_ci for_each_rtd_codec_dais(rtd, i, codec_dai) { 718c2ecf20Sopenharmony_ci ret = snd_soc_dai_set_bclk_ratio(codec_dai, 64); 728c2ecf20Sopenharmony_ci if (ret < 0) { 738c2ecf20Sopenharmony_ci dev_err(card->dev, "failed to set bclk ratio\n"); 748c2ecf20Sopenharmony_ci return ret; 758c2ecf20Sopenharmony_ci } 768c2ecf20Sopenharmony_ci 778c2ecf20Sopenharmony_ci ret = snd_soc_dai_set_pll(codec_dai, 0, RT1015_PLL_S_BCLK, 788c2ecf20Sopenharmony_ci rate * 64, rate * 256); 798c2ecf20Sopenharmony_ci if (ret < 0) { 808c2ecf20Sopenharmony_ci dev_err(card->dev, "failed to set pll\n"); 818c2ecf20Sopenharmony_ci return ret; 828c2ecf20Sopenharmony_ci } 838c2ecf20Sopenharmony_ci 848c2ecf20Sopenharmony_ci ret = snd_soc_dai_set_sysclk(codec_dai, RT1015_SCLK_S_PLL, 858c2ecf20Sopenharmony_ci rate * 256, SND_SOC_CLOCK_IN); 868c2ecf20Sopenharmony_ci if (ret < 0) { 878c2ecf20Sopenharmony_ci dev_err(card->dev, "failed to set sysclk\n"); 888c2ecf20Sopenharmony_ci return ret; 898c2ecf20Sopenharmony_ci } 908c2ecf20Sopenharmony_ci } 918c2ecf20Sopenharmony_ci 928c2ecf20Sopenharmony_ci return snd_soc_dai_set_sysclk(asoc_rtd_to_cpu(rtd, 0), 938c2ecf20Sopenharmony_ci 0, mclk_fs, SND_SOC_CLOCK_OUT); 948c2ecf20Sopenharmony_ci} 958c2ecf20Sopenharmony_ci 968c2ecf20Sopenharmony_cistatic const struct snd_soc_ops mt8183_mt6358_rt1015_i2s_ops = { 978c2ecf20Sopenharmony_ci .hw_params = mt8183_mt6358_rt1015_i2s_hw_params, 988c2ecf20Sopenharmony_ci}; 998c2ecf20Sopenharmony_ci 1008c2ecf20Sopenharmony_cistatic int mt8183_i2s_hw_params_fixup(struct snd_soc_pcm_runtime *rtd, 1018c2ecf20Sopenharmony_ci struct snd_pcm_hw_params *params) 1028c2ecf20Sopenharmony_ci{ 1038c2ecf20Sopenharmony_ci dev_dbg(rtd->dev, "%s(), fix format to 32bit\n", __func__); 1048c2ecf20Sopenharmony_ci 1058c2ecf20Sopenharmony_ci /* fix BE i2s format to 32bit, clean param mask first */ 1068c2ecf20Sopenharmony_ci snd_mask_reset_range(hw_param_mask(params, SNDRV_PCM_HW_PARAM_FORMAT), 1078c2ecf20Sopenharmony_ci 0, SNDRV_PCM_FORMAT_LAST); 1088c2ecf20Sopenharmony_ci 1098c2ecf20Sopenharmony_ci params_set_format(params, SNDRV_PCM_FORMAT_S32_LE); 1108c2ecf20Sopenharmony_ci return 0; 1118c2ecf20Sopenharmony_ci} 1128c2ecf20Sopenharmony_ci 1138c2ecf20Sopenharmony_cistatic int mt8183_rt1015_i2s_hw_params_fixup(struct snd_soc_pcm_runtime *rtd, 1148c2ecf20Sopenharmony_ci struct snd_pcm_hw_params *params) 1158c2ecf20Sopenharmony_ci{ 1168c2ecf20Sopenharmony_ci dev_dbg(rtd->dev, "%s(), fix format to 32bit\n", __func__); 1178c2ecf20Sopenharmony_ci 1188c2ecf20Sopenharmony_ci /* fix BE i2s format to 32bit, clean param mask first */ 1198c2ecf20Sopenharmony_ci snd_mask_reset_range(hw_param_mask(params, SNDRV_PCM_HW_PARAM_FORMAT), 1208c2ecf20Sopenharmony_ci 0, SNDRV_PCM_FORMAT_LAST); 1218c2ecf20Sopenharmony_ci 1228c2ecf20Sopenharmony_ci params_set_format(params, SNDRV_PCM_FORMAT_S24_LE); 1238c2ecf20Sopenharmony_ci return 0; 1248c2ecf20Sopenharmony_ci} 1258c2ecf20Sopenharmony_ci 1268c2ecf20Sopenharmony_cistatic int 1278c2ecf20Sopenharmony_cimt8183_mt6358_ts3a227_max98357_bt_sco_startup( 1288c2ecf20Sopenharmony_ci struct snd_pcm_substream *substream) 1298c2ecf20Sopenharmony_ci{ 1308c2ecf20Sopenharmony_ci static const unsigned int rates[] = { 1318c2ecf20Sopenharmony_ci 8000, 16000 1328c2ecf20Sopenharmony_ci }; 1338c2ecf20Sopenharmony_ci static const struct snd_pcm_hw_constraint_list constraints_rates = { 1348c2ecf20Sopenharmony_ci .count = ARRAY_SIZE(rates), 1358c2ecf20Sopenharmony_ci .list = rates, 1368c2ecf20Sopenharmony_ci .mask = 0, 1378c2ecf20Sopenharmony_ci }; 1388c2ecf20Sopenharmony_ci static const unsigned int channels[] = { 1398c2ecf20Sopenharmony_ci 1, 1408c2ecf20Sopenharmony_ci }; 1418c2ecf20Sopenharmony_ci static const struct snd_pcm_hw_constraint_list constraints_channels = { 1428c2ecf20Sopenharmony_ci .count = ARRAY_SIZE(channels), 1438c2ecf20Sopenharmony_ci .list = channels, 1448c2ecf20Sopenharmony_ci .mask = 0, 1458c2ecf20Sopenharmony_ci }; 1468c2ecf20Sopenharmony_ci 1478c2ecf20Sopenharmony_ci struct snd_pcm_runtime *runtime = substream->runtime; 1488c2ecf20Sopenharmony_ci 1498c2ecf20Sopenharmony_ci snd_pcm_hw_constraint_list(runtime, 0, 1508c2ecf20Sopenharmony_ci SNDRV_PCM_HW_PARAM_RATE, &constraints_rates); 1518c2ecf20Sopenharmony_ci runtime->hw.channels_max = 1; 1528c2ecf20Sopenharmony_ci snd_pcm_hw_constraint_list(runtime, 0, 1538c2ecf20Sopenharmony_ci SNDRV_PCM_HW_PARAM_CHANNELS, 1548c2ecf20Sopenharmony_ci &constraints_channels); 1558c2ecf20Sopenharmony_ci 1568c2ecf20Sopenharmony_ci runtime->hw.formats = SNDRV_PCM_FMTBIT_S16_LE; 1578c2ecf20Sopenharmony_ci snd_pcm_hw_constraint_msbits(runtime, 0, 16, 16); 1588c2ecf20Sopenharmony_ci 1598c2ecf20Sopenharmony_ci return 0; 1608c2ecf20Sopenharmony_ci} 1618c2ecf20Sopenharmony_ci 1628c2ecf20Sopenharmony_cistatic const struct snd_soc_ops mt8183_mt6358_ts3a227_max98357_bt_sco_ops = { 1638c2ecf20Sopenharmony_ci .startup = mt8183_mt6358_ts3a227_max98357_bt_sco_startup, 1648c2ecf20Sopenharmony_ci}; 1658c2ecf20Sopenharmony_ci 1668c2ecf20Sopenharmony_ci/* FE */ 1678c2ecf20Sopenharmony_ciSND_SOC_DAILINK_DEFS(playback1, 1688c2ecf20Sopenharmony_ci DAILINK_COMP_ARRAY(COMP_CPU("DL1")), 1698c2ecf20Sopenharmony_ci DAILINK_COMP_ARRAY(COMP_DUMMY()), 1708c2ecf20Sopenharmony_ci DAILINK_COMP_ARRAY(COMP_EMPTY())); 1718c2ecf20Sopenharmony_ci 1728c2ecf20Sopenharmony_ciSND_SOC_DAILINK_DEFS(playback2, 1738c2ecf20Sopenharmony_ci DAILINK_COMP_ARRAY(COMP_CPU("DL2")), 1748c2ecf20Sopenharmony_ci DAILINK_COMP_ARRAY(COMP_DUMMY()), 1758c2ecf20Sopenharmony_ci DAILINK_COMP_ARRAY(COMP_EMPTY())); 1768c2ecf20Sopenharmony_ci 1778c2ecf20Sopenharmony_ciSND_SOC_DAILINK_DEFS(playback3, 1788c2ecf20Sopenharmony_ci DAILINK_COMP_ARRAY(COMP_CPU("DL3")), 1798c2ecf20Sopenharmony_ci DAILINK_COMP_ARRAY(COMP_DUMMY()), 1808c2ecf20Sopenharmony_ci DAILINK_COMP_ARRAY(COMP_EMPTY())); 1818c2ecf20Sopenharmony_ci 1828c2ecf20Sopenharmony_ciSND_SOC_DAILINK_DEFS(capture1, 1838c2ecf20Sopenharmony_ci DAILINK_COMP_ARRAY(COMP_CPU("UL1")), 1848c2ecf20Sopenharmony_ci DAILINK_COMP_ARRAY(COMP_DUMMY()), 1858c2ecf20Sopenharmony_ci DAILINK_COMP_ARRAY(COMP_EMPTY())); 1868c2ecf20Sopenharmony_ci 1878c2ecf20Sopenharmony_ciSND_SOC_DAILINK_DEFS(capture2, 1888c2ecf20Sopenharmony_ci DAILINK_COMP_ARRAY(COMP_CPU("UL2")), 1898c2ecf20Sopenharmony_ci DAILINK_COMP_ARRAY(COMP_DUMMY()), 1908c2ecf20Sopenharmony_ci DAILINK_COMP_ARRAY(COMP_EMPTY())); 1918c2ecf20Sopenharmony_ci 1928c2ecf20Sopenharmony_ciSND_SOC_DAILINK_DEFS(capture3, 1938c2ecf20Sopenharmony_ci DAILINK_COMP_ARRAY(COMP_CPU("UL3")), 1948c2ecf20Sopenharmony_ci DAILINK_COMP_ARRAY(COMP_DUMMY()), 1958c2ecf20Sopenharmony_ci DAILINK_COMP_ARRAY(COMP_EMPTY())); 1968c2ecf20Sopenharmony_ci 1978c2ecf20Sopenharmony_ciSND_SOC_DAILINK_DEFS(capture_mono, 1988c2ecf20Sopenharmony_ci DAILINK_COMP_ARRAY(COMP_CPU("UL_MONO_1")), 1998c2ecf20Sopenharmony_ci DAILINK_COMP_ARRAY(COMP_DUMMY()), 2008c2ecf20Sopenharmony_ci DAILINK_COMP_ARRAY(COMP_EMPTY())); 2018c2ecf20Sopenharmony_ci 2028c2ecf20Sopenharmony_ciSND_SOC_DAILINK_DEFS(playback_hdmi, 2038c2ecf20Sopenharmony_ci DAILINK_COMP_ARRAY(COMP_CPU("HDMI")), 2048c2ecf20Sopenharmony_ci DAILINK_COMP_ARRAY(COMP_DUMMY()), 2058c2ecf20Sopenharmony_ci DAILINK_COMP_ARRAY(COMP_EMPTY())); 2068c2ecf20Sopenharmony_ci 2078c2ecf20Sopenharmony_ciSND_SOC_DAILINK_DEFS(wake_on_voice, 2088c2ecf20Sopenharmony_ci DAILINK_COMP_ARRAY(COMP_DUMMY()), 2098c2ecf20Sopenharmony_ci DAILINK_COMP_ARRAY(COMP_DUMMY()), 2108c2ecf20Sopenharmony_ci DAILINK_COMP_ARRAY(COMP_EMPTY())); 2118c2ecf20Sopenharmony_ci 2128c2ecf20Sopenharmony_ci/* BE */ 2138c2ecf20Sopenharmony_ciSND_SOC_DAILINK_DEFS(primary_codec, 2148c2ecf20Sopenharmony_ci DAILINK_COMP_ARRAY(COMP_CPU("ADDA")), 2158c2ecf20Sopenharmony_ci DAILINK_COMP_ARRAY(COMP_CODEC("mt6358-sound", "mt6358-snd-codec-aif1")), 2168c2ecf20Sopenharmony_ci DAILINK_COMP_ARRAY(COMP_EMPTY())); 2178c2ecf20Sopenharmony_ci 2188c2ecf20Sopenharmony_ciSND_SOC_DAILINK_DEFS(pcm1, 2198c2ecf20Sopenharmony_ci DAILINK_COMP_ARRAY(COMP_CPU("PCM 1")), 2208c2ecf20Sopenharmony_ci DAILINK_COMP_ARRAY(COMP_DUMMY()), 2218c2ecf20Sopenharmony_ci DAILINK_COMP_ARRAY(COMP_EMPTY())); 2228c2ecf20Sopenharmony_ci 2238c2ecf20Sopenharmony_ciSND_SOC_DAILINK_DEFS(pcm2, 2248c2ecf20Sopenharmony_ci DAILINK_COMP_ARRAY(COMP_CPU("PCM 2")), 2258c2ecf20Sopenharmony_ci DAILINK_COMP_ARRAY(COMP_DUMMY()), 2268c2ecf20Sopenharmony_ci DAILINK_COMP_ARRAY(COMP_EMPTY())); 2278c2ecf20Sopenharmony_ci 2288c2ecf20Sopenharmony_ciSND_SOC_DAILINK_DEFS(i2s0, 2298c2ecf20Sopenharmony_ci DAILINK_COMP_ARRAY(COMP_CPU("I2S0")), 2308c2ecf20Sopenharmony_ci DAILINK_COMP_ARRAY(COMP_CODEC("bt-sco", "bt-sco-pcm")), 2318c2ecf20Sopenharmony_ci DAILINK_COMP_ARRAY(COMP_EMPTY())); 2328c2ecf20Sopenharmony_ci 2338c2ecf20Sopenharmony_ciSND_SOC_DAILINK_DEFS(i2s1, 2348c2ecf20Sopenharmony_ci DAILINK_COMP_ARRAY(COMP_CPU("I2S1")), 2358c2ecf20Sopenharmony_ci DAILINK_COMP_ARRAY(COMP_DUMMY()), 2368c2ecf20Sopenharmony_ci DAILINK_COMP_ARRAY(COMP_EMPTY())); 2378c2ecf20Sopenharmony_ci 2388c2ecf20Sopenharmony_ciSND_SOC_DAILINK_DEFS(i2s2, 2398c2ecf20Sopenharmony_ci DAILINK_COMP_ARRAY(COMP_CPU("I2S2")), 2408c2ecf20Sopenharmony_ci DAILINK_COMP_ARRAY(COMP_DUMMY()), 2418c2ecf20Sopenharmony_ci DAILINK_COMP_ARRAY(COMP_EMPTY())); 2428c2ecf20Sopenharmony_ci 2438c2ecf20Sopenharmony_ciSND_SOC_DAILINK_DEFS(i2s3_max98357a, 2448c2ecf20Sopenharmony_ci DAILINK_COMP_ARRAY(COMP_CPU("I2S3")), 2458c2ecf20Sopenharmony_ci DAILINK_COMP_ARRAY(COMP_CODEC("max98357a", "HiFi")), 2468c2ecf20Sopenharmony_ci DAILINK_COMP_ARRAY(COMP_EMPTY())); 2478c2ecf20Sopenharmony_ci 2488c2ecf20Sopenharmony_ciSND_SOC_DAILINK_DEFS(i2s3_rt1015, 2498c2ecf20Sopenharmony_ci DAILINK_COMP_ARRAY(COMP_CPU("I2S3")), 2508c2ecf20Sopenharmony_ci DAILINK_COMP_ARRAY(COMP_CODEC(RT1015_DEV0_NAME, RT1015_CODEC_DAI), 2518c2ecf20Sopenharmony_ci COMP_CODEC(RT1015_DEV1_NAME, RT1015_CODEC_DAI)), 2528c2ecf20Sopenharmony_ci DAILINK_COMP_ARRAY(COMP_EMPTY())); 2538c2ecf20Sopenharmony_ci 2548c2ecf20Sopenharmony_ciSND_SOC_DAILINK_DEFS(i2s5, 2558c2ecf20Sopenharmony_ci DAILINK_COMP_ARRAY(COMP_CPU("I2S5")), 2568c2ecf20Sopenharmony_ci DAILINK_COMP_ARRAY(COMP_CODEC("bt-sco", "bt-sco-pcm")), 2578c2ecf20Sopenharmony_ci DAILINK_COMP_ARRAY(COMP_EMPTY())); 2588c2ecf20Sopenharmony_ci 2598c2ecf20Sopenharmony_ciSND_SOC_DAILINK_DEFS(tdm, 2608c2ecf20Sopenharmony_ci DAILINK_COMP_ARRAY(COMP_CPU("TDM")), 2618c2ecf20Sopenharmony_ci DAILINK_COMP_ARRAY(COMP_CODEC(NULL, "i2s-hifi")), 2628c2ecf20Sopenharmony_ci DAILINK_COMP_ARRAY(COMP_EMPTY())); 2638c2ecf20Sopenharmony_ci 2648c2ecf20Sopenharmony_cistatic int mt8183_mt6358_tdm_startup(struct snd_pcm_substream *substream) 2658c2ecf20Sopenharmony_ci{ 2668c2ecf20Sopenharmony_ci struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); 2678c2ecf20Sopenharmony_ci struct mt8183_mt6358_ts3a227_max98357_priv *priv = 2688c2ecf20Sopenharmony_ci snd_soc_card_get_drvdata(rtd->card); 2698c2ecf20Sopenharmony_ci int ret; 2708c2ecf20Sopenharmony_ci 2718c2ecf20Sopenharmony_ci if (IS_ERR(priv->pin_states[PIN_TDM_OUT_ON])) 2728c2ecf20Sopenharmony_ci return PTR_ERR(priv->pin_states[PIN_TDM_OUT_ON]); 2738c2ecf20Sopenharmony_ci 2748c2ecf20Sopenharmony_ci ret = pinctrl_select_state(priv->pinctrl, 2758c2ecf20Sopenharmony_ci priv->pin_states[PIN_TDM_OUT_ON]); 2768c2ecf20Sopenharmony_ci if (ret) 2778c2ecf20Sopenharmony_ci dev_err(rtd->card->dev, "%s failed to select state %d\n", 2788c2ecf20Sopenharmony_ci __func__, ret); 2798c2ecf20Sopenharmony_ci 2808c2ecf20Sopenharmony_ci return ret; 2818c2ecf20Sopenharmony_ci} 2828c2ecf20Sopenharmony_ci 2838c2ecf20Sopenharmony_cistatic void mt8183_mt6358_tdm_shutdown(struct snd_pcm_substream *substream) 2848c2ecf20Sopenharmony_ci{ 2858c2ecf20Sopenharmony_ci struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); 2868c2ecf20Sopenharmony_ci struct mt8183_mt6358_ts3a227_max98357_priv *priv = 2878c2ecf20Sopenharmony_ci snd_soc_card_get_drvdata(rtd->card); 2888c2ecf20Sopenharmony_ci int ret; 2898c2ecf20Sopenharmony_ci 2908c2ecf20Sopenharmony_ci if (IS_ERR(priv->pin_states[PIN_TDM_OUT_OFF])) 2918c2ecf20Sopenharmony_ci return; 2928c2ecf20Sopenharmony_ci 2938c2ecf20Sopenharmony_ci ret = pinctrl_select_state(priv->pinctrl, 2948c2ecf20Sopenharmony_ci priv->pin_states[PIN_TDM_OUT_OFF]); 2958c2ecf20Sopenharmony_ci if (ret) 2968c2ecf20Sopenharmony_ci dev_err(rtd->card->dev, "%s failed to select state %d\n", 2978c2ecf20Sopenharmony_ci __func__, ret); 2988c2ecf20Sopenharmony_ci} 2998c2ecf20Sopenharmony_ci 3008c2ecf20Sopenharmony_cistatic struct snd_soc_ops mt8183_mt6358_tdm_ops = { 3018c2ecf20Sopenharmony_ci .startup = mt8183_mt6358_tdm_startup, 3028c2ecf20Sopenharmony_ci .shutdown = mt8183_mt6358_tdm_shutdown, 3038c2ecf20Sopenharmony_ci}; 3048c2ecf20Sopenharmony_ci 3058c2ecf20Sopenharmony_cistatic int 3068c2ecf20Sopenharmony_cimt8183_mt6358_ts3a227_max98357_wov_startup( 3078c2ecf20Sopenharmony_ci struct snd_pcm_substream *substream) 3088c2ecf20Sopenharmony_ci{ 3098c2ecf20Sopenharmony_ci struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); 3108c2ecf20Sopenharmony_ci struct snd_soc_card *card = rtd->card; 3118c2ecf20Sopenharmony_ci struct mt8183_mt6358_ts3a227_max98357_priv *priv = 3128c2ecf20Sopenharmony_ci snd_soc_card_get_drvdata(card); 3138c2ecf20Sopenharmony_ci 3148c2ecf20Sopenharmony_ci return pinctrl_select_state(priv->pinctrl, 3158c2ecf20Sopenharmony_ci priv->pin_states[PIN_WOV]); 3168c2ecf20Sopenharmony_ci} 3178c2ecf20Sopenharmony_ci 3188c2ecf20Sopenharmony_cistatic void 3198c2ecf20Sopenharmony_cimt8183_mt6358_ts3a227_max98357_wov_shutdown( 3208c2ecf20Sopenharmony_ci struct snd_pcm_substream *substream) 3218c2ecf20Sopenharmony_ci{ 3228c2ecf20Sopenharmony_ci struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); 3238c2ecf20Sopenharmony_ci struct snd_soc_card *card = rtd->card; 3248c2ecf20Sopenharmony_ci struct mt8183_mt6358_ts3a227_max98357_priv *priv = 3258c2ecf20Sopenharmony_ci snd_soc_card_get_drvdata(card); 3268c2ecf20Sopenharmony_ci int ret; 3278c2ecf20Sopenharmony_ci 3288c2ecf20Sopenharmony_ci ret = pinctrl_select_state(priv->pinctrl, 3298c2ecf20Sopenharmony_ci priv->pin_states[PIN_STATE_DEFAULT]); 3308c2ecf20Sopenharmony_ci if (ret) 3318c2ecf20Sopenharmony_ci dev_err(card->dev, "%s failed to select state %d\n", 3328c2ecf20Sopenharmony_ci __func__, ret); 3338c2ecf20Sopenharmony_ci} 3348c2ecf20Sopenharmony_ci 3358c2ecf20Sopenharmony_cistatic const struct snd_soc_ops mt8183_mt6358_ts3a227_max98357_wov_ops = { 3368c2ecf20Sopenharmony_ci .startup = mt8183_mt6358_ts3a227_max98357_wov_startup, 3378c2ecf20Sopenharmony_ci .shutdown = mt8183_mt6358_ts3a227_max98357_wov_shutdown, 3388c2ecf20Sopenharmony_ci}; 3398c2ecf20Sopenharmony_ci 3408c2ecf20Sopenharmony_cistatic int 3418c2ecf20Sopenharmony_cimt8183_mt6358_ts3a227_max98357_hdmi_init(struct snd_soc_pcm_runtime *rtd) 3428c2ecf20Sopenharmony_ci{ 3438c2ecf20Sopenharmony_ci struct mt8183_mt6358_ts3a227_max98357_priv *priv = 3448c2ecf20Sopenharmony_ci snd_soc_card_get_drvdata(rtd->card); 3458c2ecf20Sopenharmony_ci int ret; 3468c2ecf20Sopenharmony_ci 3478c2ecf20Sopenharmony_ci ret = snd_soc_card_jack_new(rtd->card, "HDMI Jack", SND_JACK_LINEOUT, 3488c2ecf20Sopenharmony_ci &priv->hdmi_jack, NULL, 0); 3498c2ecf20Sopenharmony_ci if (ret) 3508c2ecf20Sopenharmony_ci return ret; 3518c2ecf20Sopenharmony_ci 3528c2ecf20Sopenharmony_ci return snd_soc_component_set_jack(asoc_rtd_to_codec(rtd, 0)->component, 3538c2ecf20Sopenharmony_ci &priv->hdmi_jack, NULL); 3548c2ecf20Sopenharmony_ci} 3558c2ecf20Sopenharmony_ci 3568c2ecf20Sopenharmony_cistatic struct snd_soc_dai_link mt8183_mt6358_ts3a227_dai_links[] = { 3578c2ecf20Sopenharmony_ci /* FE */ 3588c2ecf20Sopenharmony_ci { 3598c2ecf20Sopenharmony_ci .name = "Playback_1", 3608c2ecf20Sopenharmony_ci .stream_name = "Playback_1", 3618c2ecf20Sopenharmony_ci .trigger = {SND_SOC_DPCM_TRIGGER_PRE, 3628c2ecf20Sopenharmony_ci SND_SOC_DPCM_TRIGGER_PRE}, 3638c2ecf20Sopenharmony_ci .dynamic = 1, 3648c2ecf20Sopenharmony_ci .dpcm_playback = 1, 3658c2ecf20Sopenharmony_ci SND_SOC_DAILINK_REG(playback1), 3668c2ecf20Sopenharmony_ci }, 3678c2ecf20Sopenharmony_ci { 3688c2ecf20Sopenharmony_ci .name = "Playback_2", 3698c2ecf20Sopenharmony_ci .stream_name = "Playback_2", 3708c2ecf20Sopenharmony_ci .trigger = {SND_SOC_DPCM_TRIGGER_PRE, 3718c2ecf20Sopenharmony_ci SND_SOC_DPCM_TRIGGER_PRE}, 3728c2ecf20Sopenharmony_ci .dynamic = 1, 3738c2ecf20Sopenharmony_ci .dpcm_playback = 1, 3748c2ecf20Sopenharmony_ci .ops = &mt8183_mt6358_ts3a227_max98357_bt_sco_ops, 3758c2ecf20Sopenharmony_ci SND_SOC_DAILINK_REG(playback2), 3768c2ecf20Sopenharmony_ci }, 3778c2ecf20Sopenharmony_ci { 3788c2ecf20Sopenharmony_ci .name = "Playback_3", 3798c2ecf20Sopenharmony_ci .stream_name = "Playback_3", 3808c2ecf20Sopenharmony_ci .trigger = {SND_SOC_DPCM_TRIGGER_PRE, 3818c2ecf20Sopenharmony_ci SND_SOC_DPCM_TRIGGER_PRE}, 3828c2ecf20Sopenharmony_ci .dynamic = 1, 3838c2ecf20Sopenharmony_ci .dpcm_playback = 1, 3848c2ecf20Sopenharmony_ci SND_SOC_DAILINK_REG(playback3), 3858c2ecf20Sopenharmony_ci }, 3868c2ecf20Sopenharmony_ci { 3878c2ecf20Sopenharmony_ci .name = "Capture_1", 3888c2ecf20Sopenharmony_ci .stream_name = "Capture_1", 3898c2ecf20Sopenharmony_ci .trigger = {SND_SOC_DPCM_TRIGGER_PRE, 3908c2ecf20Sopenharmony_ci SND_SOC_DPCM_TRIGGER_PRE}, 3918c2ecf20Sopenharmony_ci .dynamic = 1, 3928c2ecf20Sopenharmony_ci .dpcm_capture = 1, 3938c2ecf20Sopenharmony_ci .ops = &mt8183_mt6358_ts3a227_max98357_bt_sco_ops, 3948c2ecf20Sopenharmony_ci SND_SOC_DAILINK_REG(capture1), 3958c2ecf20Sopenharmony_ci }, 3968c2ecf20Sopenharmony_ci { 3978c2ecf20Sopenharmony_ci .name = "Capture_2", 3988c2ecf20Sopenharmony_ci .stream_name = "Capture_2", 3998c2ecf20Sopenharmony_ci .trigger = {SND_SOC_DPCM_TRIGGER_PRE, 4008c2ecf20Sopenharmony_ci SND_SOC_DPCM_TRIGGER_PRE}, 4018c2ecf20Sopenharmony_ci .dynamic = 1, 4028c2ecf20Sopenharmony_ci .dpcm_capture = 1, 4038c2ecf20Sopenharmony_ci SND_SOC_DAILINK_REG(capture2), 4048c2ecf20Sopenharmony_ci }, 4058c2ecf20Sopenharmony_ci { 4068c2ecf20Sopenharmony_ci .name = "Capture_3", 4078c2ecf20Sopenharmony_ci .stream_name = "Capture_3", 4088c2ecf20Sopenharmony_ci .trigger = {SND_SOC_DPCM_TRIGGER_PRE, 4098c2ecf20Sopenharmony_ci SND_SOC_DPCM_TRIGGER_PRE}, 4108c2ecf20Sopenharmony_ci .dynamic = 1, 4118c2ecf20Sopenharmony_ci .dpcm_capture = 1, 4128c2ecf20Sopenharmony_ci SND_SOC_DAILINK_REG(capture3), 4138c2ecf20Sopenharmony_ci }, 4148c2ecf20Sopenharmony_ci { 4158c2ecf20Sopenharmony_ci .name = "Capture_Mono_1", 4168c2ecf20Sopenharmony_ci .stream_name = "Capture_Mono_1", 4178c2ecf20Sopenharmony_ci .trigger = {SND_SOC_DPCM_TRIGGER_PRE, 4188c2ecf20Sopenharmony_ci SND_SOC_DPCM_TRIGGER_PRE}, 4198c2ecf20Sopenharmony_ci .dynamic = 1, 4208c2ecf20Sopenharmony_ci .dpcm_capture = 1, 4218c2ecf20Sopenharmony_ci SND_SOC_DAILINK_REG(capture_mono), 4228c2ecf20Sopenharmony_ci }, 4238c2ecf20Sopenharmony_ci { 4248c2ecf20Sopenharmony_ci .name = "Playback_HDMI", 4258c2ecf20Sopenharmony_ci .stream_name = "Playback_HDMI", 4268c2ecf20Sopenharmony_ci .trigger = {SND_SOC_DPCM_TRIGGER_PRE, 4278c2ecf20Sopenharmony_ci SND_SOC_DPCM_TRIGGER_PRE}, 4288c2ecf20Sopenharmony_ci .dynamic = 1, 4298c2ecf20Sopenharmony_ci .dpcm_playback = 1, 4308c2ecf20Sopenharmony_ci SND_SOC_DAILINK_REG(playback_hdmi), 4318c2ecf20Sopenharmony_ci }, 4328c2ecf20Sopenharmony_ci { 4338c2ecf20Sopenharmony_ci .name = "Wake on Voice", 4348c2ecf20Sopenharmony_ci .stream_name = "Wake on Voice", 4358c2ecf20Sopenharmony_ci .ignore_suspend = 1, 4368c2ecf20Sopenharmony_ci .ignore = 1, 4378c2ecf20Sopenharmony_ci SND_SOC_DAILINK_REG(wake_on_voice), 4388c2ecf20Sopenharmony_ci .ops = &mt8183_mt6358_ts3a227_max98357_wov_ops, 4398c2ecf20Sopenharmony_ci }, 4408c2ecf20Sopenharmony_ci 4418c2ecf20Sopenharmony_ci /* BE */ 4428c2ecf20Sopenharmony_ci { 4438c2ecf20Sopenharmony_ci .name = "Primary Codec", 4448c2ecf20Sopenharmony_ci .no_pcm = 1, 4458c2ecf20Sopenharmony_ci .dpcm_playback = 1, 4468c2ecf20Sopenharmony_ci .dpcm_capture = 1, 4478c2ecf20Sopenharmony_ci .ignore_suspend = 1, 4488c2ecf20Sopenharmony_ci SND_SOC_DAILINK_REG(primary_codec), 4498c2ecf20Sopenharmony_ci }, 4508c2ecf20Sopenharmony_ci { 4518c2ecf20Sopenharmony_ci .name = "PCM 1", 4528c2ecf20Sopenharmony_ci .no_pcm = 1, 4538c2ecf20Sopenharmony_ci .dpcm_playback = 1, 4548c2ecf20Sopenharmony_ci .dpcm_capture = 1, 4558c2ecf20Sopenharmony_ci .ignore_suspend = 1, 4568c2ecf20Sopenharmony_ci SND_SOC_DAILINK_REG(pcm1), 4578c2ecf20Sopenharmony_ci }, 4588c2ecf20Sopenharmony_ci { 4598c2ecf20Sopenharmony_ci .name = "PCM 2", 4608c2ecf20Sopenharmony_ci .no_pcm = 1, 4618c2ecf20Sopenharmony_ci .dpcm_playback = 1, 4628c2ecf20Sopenharmony_ci .dpcm_capture = 1, 4638c2ecf20Sopenharmony_ci .ignore_suspend = 1, 4648c2ecf20Sopenharmony_ci SND_SOC_DAILINK_REG(pcm2), 4658c2ecf20Sopenharmony_ci }, 4668c2ecf20Sopenharmony_ci { 4678c2ecf20Sopenharmony_ci .name = "I2S0", 4688c2ecf20Sopenharmony_ci .no_pcm = 1, 4698c2ecf20Sopenharmony_ci .dpcm_capture = 1, 4708c2ecf20Sopenharmony_ci .ignore_suspend = 1, 4718c2ecf20Sopenharmony_ci .be_hw_params_fixup = mt8183_i2s_hw_params_fixup, 4728c2ecf20Sopenharmony_ci .ops = &mt8183_mt6358_i2s_ops, 4738c2ecf20Sopenharmony_ci SND_SOC_DAILINK_REG(i2s0), 4748c2ecf20Sopenharmony_ci }, 4758c2ecf20Sopenharmony_ci { 4768c2ecf20Sopenharmony_ci .name = "I2S1", 4778c2ecf20Sopenharmony_ci .no_pcm = 1, 4788c2ecf20Sopenharmony_ci .dpcm_playback = 1, 4798c2ecf20Sopenharmony_ci .ignore_suspend = 1, 4808c2ecf20Sopenharmony_ci .be_hw_params_fixup = mt8183_i2s_hw_params_fixup, 4818c2ecf20Sopenharmony_ci .ops = &mt8183_mt6358_i2s_ops, 4828c2ecf20Sopenharmony_ci SND_SOC_DAILINK_REG(i2s1), 4838c2ecf20Sopenharmony_ci }, 4848c2ecf20Sopenharmony_ci { 4858c2ecf20Sopenharmony_ci .name = "I2S2", 4868c2ecf20Sopenharmony_ci .no_pcm = 1, 4878c2ecf20Sopenharmony_ci .dpcm_capture = 1, 4888c2ecf20Sopenharmony_ci .ignore_suspend = 1, 4898c2ecf20Sopenharmony_ci .be_hw_params_fixup = mt8183_i2s_hw_params_fixup, 4908c2ecf20Sopenharmony_ci .ops = &mt8183_mt6358_i2s_ops, 4918c2ecf20Sopenharmony_ci SND_SOC_DAILINK_REG(i2s2), 4928c2ecf20Sopenharmony_ci }, 4938c2ecf20Sopenharmony_ci { 4948c2ecf20Sopenharmony_ci .name = "I2S3", 4958c2ecf20Sopenharmony_ci .no_pcm = 1, 4968c2ecf20Sopenharmony_ci .dpcm_playback = 1, 4978c2ecf20Sopenharmony_ci .ignore_suspend = 1, 4988c2ecf20Sopenharmony_ci }, 4998c2ecf20Sopenharmony_ci { 5008c2ecf20Sopenharmony_ci .name = "I2S5", 5018c2ecf20Sopenharmony_ci .no_pcm = 1, 5028c2ecf20Sopenharmony_ci .dpcm_playback = 1, 5038c2ecf20Sopenharmony_ci .ignore_suspend = 1, 5048c2ecf20Sopenharmony_ci .be_hw_params_fixup = mt8183_i2s_hw_params_fixup, 5058c2ecf20Sopenharmony_ci .ops = &mt8183_mt6358_i2s_ops, 5068c2ecf20Sopenharmony_ci SND_SOC_DAILINK_REG(i2s5), 5078c2ecf20Sopenharmony_ci }, 5088c2ecf20Sopenharmony_ci { 5098c2ecf20Sopenharmony_ci .name = "TDM", 5108c2ecf20Sopenharmony_ci .no_pcm = 1, 5118c2ecf20Sopenharmony_ci .dai_fmt = SND_SOC_DAIFMT_I2S | 5128c2ecf20Sopenharmony_ci SND_SOC_DAIFMT_IB_IF | 5138c2ecf20Sopenharmony_ci SND_SOC_DAIFMT_CBM_CFM, 5148c2ecf20Sopenharmony_ci .dpcm_playback = 1, 5158c2ecf20Sopenharmony_ci .ignore_suspend = 1, 5168c2ecf20Sopenharmony_ci .be_hw_params_fixup = mt8183_i2s_hw_params_fixup, 5178c2ecf20Sopenharmony_ci .ops = &mt8183_mt6358_tdm_ops, 5188c2ecf20Sopenharmony_ci .ignore = 1, 5198c2ecf20Sopenharmony_ci .init = mt8183_mt6358_ts3a227_max98357_hdmi_init, 5208c2ecf20Sopenharmony_ci SND_SOC_DAILINK_REG(tdm), 5218c2ecf20Sopenharmony_ci }, 5228c2ecf20Sopenharmony_ci}; 5238c2ecf20Sopenharmony_ci 5248c2ecf20Sopenharmony_cistatic struct snd_soc_card mt8183_mt6358_ts3a227_max98357_card = { 5258c2ecf20Sopenharmony_ci .name = "mt8183_mt6358_ts3a227_max98357", 5268c2ecf20Sopenharmony_ci .owner = THIS_MODULE, 5278c2ecf20Sopenharmony_ci .dai_link = mt8183_mt6358_ts3a227_dai_links, 5288c2ecf20Sopenharmony_ci .num_links = ARRAY_SIZE(mt8183_mt6358_ts3a227_dai_links), 5298c2ecf20Sopenharmony_ci}; 5308c2ecf20Sopenharmony_ci 5318c2ecf20Sopenharmony_cistatic struct snd_soc_card mt8183_mt6358_ts3a227_max98357b_card = { 5328c2ecf20Sopenharmony_ci .name = "mt8183_mt6358_ts3a227_max98357b", 5338c2ecf20Sopenharmony_ci .owner = THIS_MODULE, 5348c2ecf20Sopenharmony_ci .dai_link = mt8183_mt6358_ts3a227_dai_links, 5358c2ecf20Sopenharmony_ci .num_links = ARRAY_SIZE(mt8183_mt6358_ts3a227_dai_links), 5368c2ecf20Sopenharmony_ci}; 5378c2ecf20Sopenharmony_ci 5388c2ecf20Sopenharmony_cistatic struct snd_soc_codec_conf mt8183_mt6358_ts3a227_rt1015_amp_conf[] = { 5398c2ecf20Sopenharmony_ci { 5408c2ecf20Sopenharmony_ci .dlc = COMP_CODEC_CONF(RT1015_DEV0_NAME), 5418c2ecf20Sopenharmony_ci .name_prefix = "Left", 5428c2ecf20Sopenharmony_ci }, 5438c2ecf20Sopenharmony_ci { 5448c2ecf20Sopenharmony_ci .dlc = COMP_CODEC_CONF(RT1015_DEV1_NAME), 5458c2ecf20Sopenharmony_ci .name_prefix = "Right", 5468c2ecf20Sopenharmony_ci }, 5478c2ecf20Sopenharmony_ci}; 5488c2ecf20Sopenharmony_ci 5498c2ecf20Sopenharmony_cistatic struct snd_soc_card mt8183_mt6358_ts3a227_rt1015_card = { 5508c2ecf20Sopenharmony_ci .name = "mt8183_mt6358_ts3a227_rt1015", 5518c2ecf20Sopenharmony_ci .owner = THIS_MODULE, 5528c2ecf20Sopenharmony_ci .dai_link = mt8183_mt6358_ts3a227_dai_links, 5538c2ecf20Sopenharmony_ci .num_links = ARRAY_SIZE(mt8183_mt6358_ts3a227_dai_links), 5548c2ecf20Sopenharmony_ci .codec_conf = mt8183_mt6358_ts3a227_rt1015_amp_conf, 5558c2ecf20Sopenharmony_ci .num_configs = ARRAY_SIZE(mt8183_mt6358_ts3a227_rt1015_amp_conf), 5568c2ecf20Sopenharmony_ci}; 5578c2ecf20Sopenharmony_ci 5588c2ecf20Sopenharmony_cistatic int 5598c2ecf20Sopenharmony_cimt8183_mt6358_ts3a227_max98357_headset_init(struct snd_soc_component *component) 5608c2ecf20Sopenharmony_ci{ 5618c2ecf20Sopenharmony_ci int ret; 5628c2ecf20Sopenharmony_ci struct mt8183_mt6358_ts3a227_max98357_priv *priv = 5638c2ecf20Sopenharmony_ci snd_soc_card_get_drvdata(component->card); 5648c2ecf20Sopenharmony_ci 5658c2ecf20Sopenharmony_ci /* Enable Headset and 4 Buttons Jack detection */ 5668c2ecf20Sopenharmony_ci ret = snd_soc_card_jack_new(component->card, 5678c2ecf20Sopenharmony_ci "Headset Jack", 5688c2ecf20Sopenharmony_ci SND_JACK_HEADSET | 5698c2ecf20Sopenharmony_ci SND_JACK_BTN_0 | SND_JACK_BTN_1 | 5708c2ecf20Sopenharmony_ci SND_JACK_BTN_2 | SND_JACK_BTN_3, 5718c2ecf20Sopenharmony_ci &priv->headset_jack, 5728c2ecf20Sopenharmony_ci NULL, 0); 5738c2ecf20Sopenharmony_ci if (ret) 5748c2ecf20Sopenharmony_ci return ret; 5758c2ecf20Sopenharmony_ci 5768c2ecf20Sopenharmony_ci ret = ts3a227e_enable_jack_detect(component, &priv->headset_jack); 5778c2ecf20Sopenharmony_ci 5788c2ecf20Sopenharmony_ci return ret; 5798c2ecf20Sopenharmony_ci} 5808c2ecf20Sopenharmony_ci 5818c2ecf20Sopenharmony_cistatic struct snd_soc_aux_dev mt8183_mt6358_ts3a227_max98357_headset_dev = { 5828c2ecf20Sopenharmony_ci .dlc = COMP_EMPTY(), 5838c2ecf20Sopenharmony_ci .init = mt8183_mt6358_ts3a227_max98357_headset_init, 5848c2ecf20Sopenharmony_ci}; 5858c2ecf20Sopenharmony_ci 5868c2ecf20Sopenharmony_cistatic int 5878c2ecf20Sopenharmony_cimt8183_mt6358_ts3a227_max98357_dev_probe(struct platform_device *pdev) 5888c2ecf20Sopenharmony_ci{ 5898c2ecf20Sopenharmony_ci struct snd_soc_card *card; 5908c2ecf20Sopenharmony_ci struct device_node *platform_node, *ec_codec, *hdmi_codec; 5918c2ecf20Sopenharmony_ci struct snd_soc_dai_link *dai_link; 5928c2ecf20Sopenharmony_ci struct mt8183_mt6358_ts3a227_max98357_priv *priv; 5938c2ecf20Sopenharmony_ci const struct of_device_id *match; 5948c2ecf20Sopenharmony_ci int ret, i; 5958c2ecf20Sopenharmony_ci 5968c2ecf20Sopenharmony_ci platform_node = of_parse_phandle(pdev->dev.of_node, 5978c2ecf20Sopenharmony_ci "mediatek,platform", 0); 5988c2ecf20Sopenharmony_ci if (!platform_node) { 5998c2ecf20Sopenharmony_ci dev_err(&pdev->dev, "Property 'platform' missing or invalid\n"); 6008c2ecf20Sopenharmony_ci return -EINVAL; 6018c2ecf20Sopenharmony_ci } 6028c2ecf20Sopenharmony_ci 6038c2ecf20Sopenharmony_ci match = of_match_device(pdev->dev.driver->of_match_table, &pdev->dev); 6048c2ecf20Sopenharmony_ci if (!match || !match->data) 6058c2ecf20Sopenharmony_ci return -EINVAL; 6068c2ecf20Sopenharmony_ci 6078c2ecf20Sopenharmony_ci card = (struct snd_soc_card *)match->data; 6088c2ecf20Sopenharmony_ci card->dev = &pdev->dev; 6098c2ecf20Sopenharmony_ci 6108c2ecf20Sopenharmony_ci ec_codec = of_parse_phandle(pdev->dev.of_node, "mediatek,ec-codec", 0); 6118c2ecf20Sopenharmony_ci hdmi_codec = of_parse_phandle(pdev->dev.of_node, 6128c2ecf20Sopenharmony_ci "mediatek,hdmi-codec", 0); 6138c2ecf20Sopenharmony_ci 6148c2ecf20Sopenharmony_ci for_each_card_prelinks(card, i, dai_link) { 6158c2ecf20Sopenharmony_ci if (ec_codec && strcmp(dai_link->name, "Wake on Voice") == 0) { 6168c2ecf20Sopenharmony_ci dai_link->cpus[0].name = NULL; 6178c2ecf20Sopenharmony_ci dai_link->cpus[0].of_node = ec_codec; 6188c2ecf20Sopenharmony_ci dai_link->cpus[0].dai_name = NULL; 6198c2ecf20Sopenharmony_ci dai_link->codecs[0].name = NULL; 6208c2ecf20Sopenharmony_ci dai_link->codecs[0].of_node = ec_codec; 6218c2ecf20Sopenharmony_ci dai_link->codecs[0].dai_name = "Wake on Voice"; 6228c2ecf20Sopenharmony_ci dai_link->platforms[0].of_node = ec_codec; 6238c2ecf20Sopenharmony_ci dai_link->ignore = 0; 6248c2ecf20Sopenharmony_ci } 6258c2ecf20Sopenharmony_ci 6268c2ecf20Sopenharmony_ci if (strcmp(dai_link->name, "I2S3") == 0) { 6278c2ecf20Sopenharmony_ci if (card == &mt8183_mt6358_ts3a227_max98357_card || 6288c2ecf20Sopenharmony_ci card == &mt8183_mt6358_ts3a227_max98357b_card) { 6298c2ecf20Sopenharmony_ci dai_link->be_hw_params_fixup = 6308c2ecf20Sopenharmony_ci mt8183_i2s_hw_params_fixup; 6318c2ecf20Sopenharmony_ci dai_link->ops = &mt8183_mt6358_i2s_ops; 6328c2ecf20Sopenharmony_ci dai_link->cpus = i2s3_max98357a_cpus; 6338c2ecf20Sopenharmony_ci dai_link->num_cpus = 6348c2ecf20Sopenharmony_ci ARRAY_SIZE(i2s3_max98357a_cpus); 6358c2ecf20Sopenharmony_ci dai_link->codecs = i2s3_max98357a_codecs; 6368c2ecf20Sopenharmony_ci dai_link->num_codecs = 6378c2ecf20Sopenharmony_ci ARRAY_SIZE(i2s3_max98357a_codecs); 6388c2ecf20Sopenharmony_ci dai_link->platforms = i2s3_max98357a_platforms; 6398c2ecf20Sopenharmony_ci dai_link->num_platforms = 6408c2ecf20Sopenharmony_ci ARRAY_SIZE(i2s3_max98357a_platforms); 6418c2ecf20Sopenharmony_ci } else if (card == &mt8183_mt6358_ts3a227_rt1015_card) { 6428c2ecf20Sopenharmony_ci dai_link->be_hw_params_fixup = 6438c2ecf20Sopenharmony_ci mt8183_rt1015_i2s_hw_params_fixup; 6448c2ecf20Sopenharmony_ci dai_link->ops = &mt8183_mt6358_rt1015_i2s_ops; 6458c2ecf20Sopenharmony_ci dai_link->cpus = i2s3_rt1015_cpus; 6468c2ecf20Sopenharmony_ci dai_link->num_cpus = 6478c2ecf20Sopenharmony_ci ARRAY_SIZE(i2s3_rt1015_cpus); 6488c2ecf20Sopenharmony_ci dai_link->codecs = i2s3_rt1015_codecs; 6498c2ecf20Sopenharmony_ci dai_link->num_codecs = 6508c2ecf20Sopenharmony_ci ARRAY_SIZE(i2s3_rt1015_codecs); 6518c2ecf20Sopenharmony_ci dai_link->platforms = i2s3_rt1015_platforms; 6528c2ecf20Sopenharmony_ci dai_link->num_platforms = 6538c2ecf20Sopenharmony_ci ARRAY_SIZE(i2s3_rt1015_platforms); 6548c2ecf20Sopenharmony_ci } 6558c2ecf20Sopenharmony_ci } 6568c2ecf20Sopenharmony_ci 6578c2ecf20Sopenharmony_ci if (card == &mt8183_mt6358_ts3a227_max98357b_card) { 6588c2ecf20Sopenharmony_ci if (strcmp(dai_link->name, "I2S2") == 0 || 6598c2ecf20Sopenharmony_ci strcmp(dai_link->name, "I2S3") == 0) 6608c2ecf20Sopenharmony_ci dai_link->dai_fmt = SND_SOC_DAIFMT_LEFT_J | 6618c2ecf20Sopenharmony_ci SND_SOC_DAIFMT_NB_NF | 6628c2ecf20Sopenharmony_ci SND_SOC_DAIFMT_CBM_CFM; 6638c2ecf20Sopenharmony_ci } 6648c2ecf20Sopenharmony_ci 6658c2ecf20Sopenharmony_ci if (hdmi_codec && strcmp(dai_link->name, "TDM") == 0) { 6668c2ecf20Sopenharmony_ci dai_link->codecs->of_node = hdmi_codec; 6678c2ecf20Sopenharmony_ci dai_link->ignore = 0; 6688c2ecf20Sopenharmony_ci } 6698c2ecf20Sopenharmony_ci 6708c2ecf20Sopenharmony_ci if (!dai_link->platforms->name) 6718c2ecf20Sopenharmony_ci dai_link->platforms->of_node = platform_node; 6728c2ecf20Sopenharmony_ci } 6738c2ecf20Sopenharmony_ci 6748c2ecf20Sopenharmony_ci mt8183_mt6358_ts3a227_max98357_headset_dev.dlc.of_node = 6758c2ecf20Sopenharmony_ci of_parse_phandle(pdev->dev.of_node, 6768c2ecf20Sopenharmony_ci "mediatek,headset-codec", 0); 6778c2ecf20Sopenharmony_ci if (mt8183_mt6358_ts3a227_max98357_headset_dev.dlc.of_node) { 6788c2ecf20Sopenharmony_ci card->aux_dev = &mt8183_mt6358_ts3a227_max98357_headset_dev; 6798c2ecf20Sopenharmony_ci card->num_aux_devs = 1; 6808c2ecf20Sopenharmony_ci } 6818c2ecf20Sopenharmony_ci 6828c2ecf20Sopenharmony_ci priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL); 6838c2ecf20Sopenharmony_ci if (!priv) 6848c2ecf20Sopenharmony_ci return -ENOMEM; 6858c2ecf20Sopenharmony_ci 6868c2ecf20Sopenharmony_ci snd_soc_card_set_drvdata(card, priv); 6878c2ecf20Sopenharmony_ci 6888c2ecf20Sopenharmony_ci priv->pinctrl = devm_pinctrl_get(&pdev->dev); 6898c2ecf20Sopenharmony_ci if (IS_ERR(priv->pinctrl)) { 6908c2ecf20Sopenharmony_ci dev_err(&pdev->dev, "%s devm_pinctrl_get failed\n", 6918c2ecf20Sopenharmony_ci __func__); 6928c2ecf20Sopenharmony_ci return PTR_ERR(priv->pinctrl); 6938c2ecf20Sopenharmony_ci } 6948c2ecf20Sopenharmony_ci 6958c2ecf20Sopenharmony_ci for (i = 0; i < PIN_STATE_MAX; i++) { 6968c2ecf20Sopenharmony_ci priv->pin_states[i] = pinctrl_lookup_state(priv->pinctrl, 6978c2ecf20Sopenharmony_ci mt8183_pin_str[i]); 6988c2ecf20Sopenharmony_ci if (IS_ERR(priv->pin_states[i])) { 6998c2ecf20Sopenharmony_ci ret = PTR_ERR(priv->pin_states[i]); 7008c2ecf20Sopenharmony_ci dev_info(&pdev->dev, "%s Can't find pin state %s %d\n", 7018c2ecf20Sopenharmony_ci __func__, mt8183_pin_str[i], ret); 7028c2ecf20Sopenharmony_ci } 7038c2ecf20Sopenharmony_ci } 7048c2ecf20Sopenharmony_ci 7058c2ecf20Sopenharmony_ci if (!IS_ERR(priv->pin_states[PIN_TDM_OUT_OFF])) { 7068c2ecf20Sopenharmony_ci ret = pinctrl_select_state(priv->pinctrl, 7078c2ecf20Sopenharmony_ci priv->pin_states[PIN_TDM_OUT_OFF]); 7088c2ecf20Sopenharmony_ci if (ret) 7098c2ecf20Sopenharmony_ci dev_info(&pdev->dev, 7108c2ecf20Sopenharmony_ci "%s failed to select state %d\n", 7118c2ecf20Sopenharmony_ci __func__, ret); 7128c2ecf20Sopenharmony_ci } 7138c2ecf20Sopenharmony_ci 7148c2ecf20Sopenharmony_ci if (!IS_ERR(priv->pin_states[PIN_STATE_DEFAULT])) { 7158c2ecf20Sopenharmony_ci ret = pinctrl_select_state(priv->pinctrl, 7168c2ecf20Sopenharmony_ci priv->pin_states[PIN_STATE_DEFAULT]); 7178c2ecf20Sopenharmony_ci if (ret) 7188c2ecf20Sopenharmony_ci dev_info(&pdev->dev, 7198c2ecf20Sopenharmony_ci "%s failed to select state %d\n", 7208c2ecf20Sopenharmony_ci __func__, ret); 7218c2ecf20Sopenharmony_ci } 7228c2ecf20Sopenharmony_ci 7238c2ecf20Sopenharmony_ci ret = devm_snd_soc_register_card(&pdev->dev, card); 7248c2ecf20Sopenharmony_ci 7258c2ecf20Sopenharmony_ci of_node_put(platform_node); 7268c2ecf20Sopenharmony_ci of_node_put(ec_codec); 7278c2ecf20Sopenharmony_ci of_node_put(hdmi_codec); 7288c2ecf20Sopenharmony_ci return ret; 7298c2ecf20Sopenharmony_ci} 7308c2ecf20Sopenharmony_ci 7318c2ecf20Sopenharmony_ci#ifdef CONFIG_OF 7328c2ecf20Sopenharmony_cistatic const struct of_device_id mt8183_mt6358_ts3a227_max98357_dt_match[] = { 7338c2ecf20Sopenharmony_ci { 7348c2ecf20Sopenharmony_ci .compatible = "mediatek,mt8183_mt6358_ts3a227_max98357", 7358c2ecf20Sopenharmony_ci .data = &mt8183_mt6358_ts3a227_max98357_card, 7368c2ecf20Sopenharmony_ci }, 7378c2ecf20Sopenharmony_ci { 7388c2ecf20Sopenharmony_ci .compatible = "mediatek,mt8183_mt6358_ts3a227_max98357b", 7398c2ecf20Sopenharmony_ci .data = &mt8183_mt6358_ts3a227_max98357b_card, 7408c2ecf20Sopenharmony_ci }, 7418c2ecf20Sopenharmony_ci { 7428c2ecf20Sopenharmony_ci .compatible = "mediatek,mt8183_mt6358_ts3a227_rt1015", 7438c2ecf20Sopenharmony_ci .data = &mt8183_mt6358_ts3a227_rt1015_card, 7448c2ecf20Sopenharmony_ci }, 7458c2ecf20Sopenharmony_ci {} 7468c2ecf20Sopenharmony_ci}; 7478c2ecf20Sopenharmony_ci#endif 7488c2ecf20Sopenharmony_ci 7498c2ecf20Sopenharmony_cistatic struct platform_driver mt8183_mt6358_ts3a227_max98357_driver = { 7508c2ecf20Sopenharmony_ci .driver = { 7518c2ecf20Sopenharmony_ci .name = "mt8183_mt6358_ts3a227", 7528c2ecf20Sopenharmony_ci#ifdef CONFIG_OF 7538c2ecf20Sopenharmony_ci .of_match_table = mt8183_mt6358_ts3a227_max98357_dt_match, 7548c2ecf20Sopenharmony_ci#endif 7558c2ecf20Sopenharmony_ci }, 7568c2ecf20Sopenharmony_ci .probe = mt8183_mt6358_ts3a227_max98357_dev_probe, 7578c2ecf20Sopenharmony_ci}; 7588c2ecf20Sopenharmony_ci 7598c2ecf20Sopenharmony_cimodule_platform_driver(mt8183_mt6358_ts3a227_max98357_driver); 7608c2ecf20Sopenharmony_ci 7618c2ecf20Sopenharmony_ci/* Module information */ 7628c2ecf20Sopenharmony_ciMODULE_DESCRIPTION("MT8183-MT6358-TS3A227-MAX98357 ALSA SoC machine driver"); 7638c2ecf20Sopenharmony_ciMODULE_AUTHOR("Shunli Wang <shunli.wang@mediatek.com>"); 7648c2ecf20Sopenharmony_ciMODULE_LICENSE("GPL v2"); 7658c2ecf20Sopenharmony_ciMODULE_ALIAS("mt8183_mt6358_ts3a227_max98357 soc card"); 766