18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0
28c2ecf20Sopenharmony_ci//
38c2ecf20Sopenharmony_ci// MediaTek ALSA SoC Audio DAI TDM Control
48c2ecf20Sopenharmony_ci//
58c2ecf20Sopenharmony_ci// Copyright (c) 2018 MediaTek Inc.
68c2ecf20Sopenharmony_ci// Author: KaiChieh Chuang <kaichieh.chuang@mediatek.com>
78c2ecf20Sopenharmony_ci
88c2ecf20Sopenharmony_ci#include <linux/regmap.h>
98c2ecf20Sopenharmony_ci#include <sound/pcm_params.h>
108c2ecf20Sopenharmony_ci#include "mt8183-afe-clk.h"
118c2ecf20Sopenharmony_ci#include "mt8183-afe-common.h"
128c2ecf20Sopenharmony_ci#include "mt8183-interconnection.h"
138c2ecf20Sopenharmony_ci#include "mt8183-reg.h"
148c2ecf20Sopenharmony_ci
158c2ecf20Sopenharmony_cistruct mtk_afe_tdm_priv {
168c2ecf20Sopenharmony_ci	int bck_id;
178c2ecf20Sopenharmony_ci	int bck_rate;
188c2ecf20Sopenharmony_ci	int tdm_out_mode;
198c2ecf20Sopenharmony_ci	int bck_invert;
208c2ecf20Sopenharmony_ci	int lck_invert;
218c2ecf20Sopenharmony_ci	int mclk_id;
228c2ecf20Sopenharmony_ci	int mclk_multiple; /* according to sample rate */
238c2ecf20Sopenharmony_ci	int mclk_rate;
248c2ecf20Sopenharmony_ci	int mclk_apll;
258c2ecf20Sopenharmony_ci};
268c2ecf20Sopenharmony_ci
278c2ecf20Sopenharmony_cienum {
288c2ecf20Sopenharmony_ci	TDM_OUT_I2S = 0,
298c2ecf20Sopenharmony_ci	TDM_OUT_TDM = 1,
308c2ecf20Sopenharmony_ci};
318c2ecf20Sopenharmony_ci
328c2ecf20Sopenharmony_cienum {
338c2ecf20Sopenharmony_ci	TDM_BCK_NON_INV = 0,
348c2ecf20Sopenharmony_ci	TDM_BCK_INV = 1,
358c2ecf20Sopenharmony_ci};
368c2ecf20Sopenharmony_ci
378c2ecf20Sopenharmony_cienum {
388c2ecf20Sopenharmony_ci	TDM_LCK_NON_INV = 0,
398c2ecf20Sopenharmony_ci	TDM_LCK_INV = 1,
408c2ecf20Sopenharmony_ci};
418c2ecf20Sopenharmony_ci
428c2ecf20Sopenharmony_cienum {
438c2ecf20Sopenharmony_ci	TDM_WLEN_16_BIT = 1,
448c2ecf20Sopenharmony_ci	TDM_WLEN_32_BIT = 2,
458c2ecf20Sopenharmony_ci};
468c2ecf20Sopenharmony_ci
478c2ecf20Sopenharmony_cienum {
488c2ecf20Sopenharmony_ci	TDM_CHANNEL_BCK_16 = 0,
498c2ecf20Sopenharmony_ci	TDM_CHANNEL_BCK_24 = 1,
508c2ecf20Sopenharmony_ci	TDM_CHANNEL_BCK_32 = 2,
518c2ecf20Sopenharmony_ci};
528c2ecf20Sopenharmony_ci
538c2ecf20Sopenharmony_cienum {
548c2ecf20Sopenharmony_ci	TDM_CHANNEL_NUM_2 = 0,
558c2ecf20Sopenharmony_ci	TDM_CHANNEL_NUM_4 = 1,
568c2ecf20Sopenharmony_ci	TDM_CHANNEL_NUM_8 = 2,
578c2ecf20Sopenharmony_ci};
588c2ecf20Sopenharmony_ci
598c2ecf20Sopenharmony_cienum  {
608c2ecf20Sopenharmony_ci	TDM_CH_START_O30_O31 = 0,
618c2ecf20Sopenharmony_ci	TDM_CH_START_O32_O33,
628c2ecf20Sopenharmony_ci	TDM_CH_START_O34_O35,
638c2ecf20Sopenharmony_ci	TDM_CH_START_O36_O37,
648c2ecf20Sopenharmony_ci	TDM_CH_ZERO,
658c2ecf20Sopenharmony_ci};
668c2ecf20Sopenharmony_ci
678c2ecf20Sopenharmony_cienum {
688c2ecf20Sopenharmony_ci	HDMI_BIT_WIDTH_16_BIT = 0,
698c2ecf20Sopenharmony_ci	HDMI_BIT_WIDTH_32_BIT = 1,
708c2ecf20Sopenharmony_ci};
718c2ecf20Sopenharmony_ci
728c2ecf20Sopenharmony_cistatic unsigned int get_hdmi_wlen(snd_pcm_format_t format)
738c2ecf20Sopenharmony_ci{
748c2ecf20Sopenharmony_ci	return snd_pcm_format_physical_width(format) <= 16 ?
758c2ecf20Sopenharmony_ci	       HDMI_BIT_WIDTH_16_BIT : HDMI_BIT_WIDTH_32_BIT;
768c2ecf20Sopenharmony_ci}
778c2ecf20Sopenharmony_ci
788c2ecf20Sopenharmony_cistatic unsigned int get_tdm_wlen(snd_pcm_format_t format)
798c2ecf20Sopenharmony_ci{
808c2ecf20Sopenharmony_ci	return snd_pcm_format_physical_width(format) <= 16 ?
818c2ecf20Sopenharmony_ci	       TDM_WLEN_16_BIT : TDM_WLEN_32_BIT;
828c2ecf20Sopenharmony_ci}
838c2ecf20Sopenharmony_ci
848c2ecf20Sopenharmony_cistatic unsigned int get_tdm_channel_bck(snd_pcm_format_t format)
858c2ecf20Sopenharmony_ci{
868c2ecf20Sopenharmony_ci	return snd_pcm_format_physical_width(format) <= 16 ?
878c2ecf20Sopenharmony_ci	       TDM_CHANNEL_BCK_16 : TDM_CHANNEL_BCK_32;
888c2ecf20Sopenharmony_ci}
898c2ecf20Sopenharmony_ci
908c2ecf20Sopenharmony_cistatic unsigned int get_tdm_lrck_width(snd_pcm_format_t format)
918c2ecf20Sopenharmony_ci{
928c2ecf20Sopenharmony_ci	return snd_pcm_format_physical_width(format) - 1;
938c2ecf20Sopenharmony_ci}
948c2ecf20Sopenharmony_ci
958c2ecf20Sopenharmony_cistatic unsigned int get_tdm_ch(unsigned int ch)
968c2ecf20Sopenharmony_ci{
978c2ecf20Sopenharmony_ci	switch (ch) {
988c2ecf20Sopenharmony_ci	case 1:
998c2ecf20Sopenharmony_ci	case 2:
1008c2ecf20Sopenharmony_ci		return TDM_CHANNEL_NUM_2;
1018c2ecf20Sopenharmony_ci	case 3:
1028c2ecf20Sopenharmony_ci	case 4:
1038c2ecf20Sopenharmony_ci		return TDM_CHANNEL_NUM_4;
1048c2ecf20Sopenharmony_ci	case 5:
1058c2ecf20Sopenharmony_ci	case 6:
1068c2ecf20Sopenharmony_ci	case 7:
1078c2ecf20Sopenharmony_ci	case 8:
1088c2ecf20Sopenharmony_ci	default:
1098c2ecf20Sopenharmony_ci		return TDM_CHANNEL_NUM_8;
1108c2ecf20Sopenharmony_ci	}
1118c2ecf20Sopenharmony_ci}
1128c2ecf20Sopenharmony_ci
1138c2ecf20Sopenharmony_cistatic unsigned int get_tdm_ch_fixup(unsigned int channels)
1148c2ecf20Sopenharmony_ci{
1158c2ecf20Sopenharmony_ci	if (channels > 4)
1168c2ecf20Sopenharmony_ci		return 8;
1178c2ecf20Sopenharmony_ci	else if (channels > 2)
1188c2ecf20Sopenharmony_ci		return 4;
1198c2ecf20Sopenharmony_ci	else
1208c2ecf20Sopenharmony_ci		return 2;
1218c2ecf20Sopenharmony_ci}
1228c2ecf20Sopenharmony_ci
1238c2ecf20Sopenharmony_cistatic unsigned int get_tdm_ch_per_sdata(unsigned int mode,
1248c2ecf20Sopenharmony_ci					 unsigned int channels)
1258c2ecf20Sopenharmony_ci{
1268c2ecf20Sopenharmony_ci	if (mode == TDM_OUT_TDM)
1278c2ecf20Sopenharmony_ci		return get_tdm_ch_fixup(channels);
1288c2ecf20Sopenharmony_ci	else
1298c2ecf20Sopenharmony_ci		return 2;
1308c2ecf20Sopenharmony_ci}
1318c2ecf20Sopenharmony_ci
1328c2ecf20Sopenharmony_ci/* interconnection */
1338c2ecf20Sopenharmony_cienum {
1348c2ecf20Sopenharmony_ci	HDMI_CONN_CH0 = 0,
1358c2ecf20Sopenharmony_ci	HDMI_CONN_CH1,
1368c2ecf20Sopenharmony_ci	HDMI_CONN_CH2,
1378c2ecf20Sopenharmony_ci	HDMI_CONN_CH3,
1388c2ecf20Sopenharmony_ci	HDMI_CONN_CH4,
1398c2ecf20Sopenharmony_ci	HDMI_CONN_CH5,
1408c2ecf20Sopenharmony_ci	HDMI_CONN_CH6,
1418c2ecf20Sopenharmony_ci	HDMI_CONN_CH7,
1428c2ecf20Sopenharmony_ci};
1438c2ecf20Sopenharmony_ci
1448c2ecf20Sopenharmony_cistatic const char *const hdmi_conn_mux_map[] = {
1458c2ecf20Sopenharmony_ci	"CH0", "CH1", "CH2", "CH3",
1468c2ecf20Sopenharmony_ci	"CH4", "CH5", "CH6", "CH7",
1478c2ecf20Sopenharmony_ci};
1488c2ecf20Sopenharmony_ci
1498c2ecf20Sopenharmony_cistatic int hdmi_conn_mux_map_value[] = {
1508c2ecf20Sopenharmony_ci	HDMI_CONN_CH0,
1518c2ecf20Sopenharmony_ci	HDMI_CONN_CH1,
1528c2ecf20Sopenharmony_ci	HDMI_CONN_CH2,
1538c2ecf20Sopenharmony_ci	HDMI_CONN_CH3,
1548c2ecf20Sopenharmony_ci	HDMI_CONN_CH4,
1558c2ecf20Sopenharmony_ci	HDMI_CONN_CH5,
1568c2ecf20Sopenharmony_ci	HDMI_CONN_CH6,
1578c2ecf20Sopenharmony_ci	HDMI_CONN_CH7,
1588c2ecf20Sopenharmony_ci};
1598c2ecf20Sopenharmony_ci
1608c2ecf20Sopenharmony_cistatic SOC_VALUE_ENUM_SINGLE_DECL(hdmi_ch0_mux_map_enum,
1618c2ecf20Sopenharmony_ci				  AFE_HDMI_CONN0,
1628c2ecf20Sopenharmony_ci				  HDMI_O_0_SFT,
1638c2ecf20Sopenharmony_ci				  HDMI_O_0_MASK,
1648c2ecf20Sopenharmony_ci				  hdmi_conn_mux_map,
1658c2ecf20Sopenharmony_ci				  hdmi_conn_mux_map_value);
1668c2ecf20Sopenharmony_ci
1678c2ecf20Sopenharmony_cistatic const struct snd_kcontrol_new hdmi_ch0_mux_control =
1688c2ecf20Sopenharmony_ci	SOC_DAPM_ENUM("HDMI_CH0_MUX", hdmi_ch0_mux_map_enum);
1698c2ecf20Sopenharmony_ci
1708c2ecf20Sopenharmony_cistatic SOC_VALUE_ENUM_SINGLE_DECL(hdmi_ch1_mux_map_enum,
1718c2ecf20Sopenharmony_ci				  AFE_HDMI_CONN0,
1728c2ecf20Sopenharmony_ci				  HDMI_O_1_SFT,
1738c2ecf20Sopenharmony_ci				  HDMI_O_1_MASK,
1748c2ecf20Sopenharmony_ci				  hdmi_conn_mux_map,
1758c2ecf20Sopenharmony_ci				  hdmi_conn_mux_map_value);
1768c2ecf20Sopenharmony_ci
1778c2ecf20Sopenharmony_cistatic const struct snd_kcontrol_new hdmi_ch1_mux_control =
1788c2ecf20Sopenharmony_ci	SOC_DAPM_ENUM("HDMI_CH1_MUX", hdmi_ch1_mux_map_enum);
1798c2ecf20Sopenharmony_ci
1808c2ecf20Sopenharmony_cistatic SOC_VALUE_ENUM_SINGLE_DECL(hdmi_ch2_mux_map_enum,
1818c2ecf20Sopenharmony_ci				  AFE_HDMI_CONN0,
1828c2ecf20Sopenharmony_ci				  HDMI_O_2_SFT,
1838c2ecf20Sopenharmony_ci				  HDMI_O_2_MASK,
1848c2ecf20Sopenharmony_ci				  hdmi_conn_mux_map,
1858c2ecf20Sopenharmony_ci				  hdmi_conn_mux_map_value);
1868c2ecf20Sopenharmony_ci
1878c2ecf20Sopenharmony_cistatic const struct snd_kcontrol_new hdmi_ch2_mux_control =
1888c2ecf20Sopenharmony_ci	SOC_DAPM_ENUM("HDMI_CH2_MUX", hdmi_ch2_mux_map_enum);
1898c2ecf20Sopenharmony_ci
1908c2ecf20Sopenharmony_cistatic SOC_VALUE_ENUM_SINGLE_DECL(hdmi_ch3_mux_map_enum,
1918c2ecf20Sopenharmony_ci				  AFE_HDMI_CONN0,
1928c2ecf20Sopenharmony_ci				  HDMI_O_3_SFT,
1938c2ecf20Sopenharmony_ci				  HDMI_O_3_MASK,
1948c2ecf20Sopenharmony_ci				  hdmi_conn_mux_map,
1958c2ecf20Sopenharmony_ci				  hdmi_conn_mux_map_value);
1968c2ecf20Sopenharmony_ci
1978c2ecf20Sopenharmony_cistatic const struct snd_kcontrol_new hdmi_ch3_mux_control =
1988c2ecf20Sopenharmony_ci	SOC_DAPM_ENUM("HDMI_CH3_MUX", hdmi_ch3_mux_map_enum);
1998c2ecf20Sopenharmony_ci
2008c2ecf20Sopenharmony_cistatic SOC_VALUE_ENUM_SINGLE_DECL(hdmi_ch4_mux_map_enum,
2018c2ecf20Sopenharmony_ci				  AFE_HDMI_CONN0,
2028c2ecf20Sopenharmony_ci				  HDMI_O_4_SFT,
2038c2ecf20Sopenharmony_ci				  HDMI_O_4_MASK,
2048c2ecf20Sopenharmony_ci				  hdmi_conn_mux_map,
2058c2ecf20Sopenharmony_ci				  hdmi_conn_mux_map_value);
2068c2ecf20Sopenharmony_ci
2078c2ecf20Sopenharmony_cistatic const struct snd_kcontrol_new hdmi_ch4_mux_control =
2088c2ecf20Sopenharmony_ci	SOC_DAPM_ENUM("HDMI_CH4_MUX", hdmi_ch4_mux_map_enum);
2098c2ecf20Sopenharmony_ci
2108c2ecf20Sopenharmony_cistatic SOC_VALUE_ENUM_SINGLE_DECL(hdmi_ch5_mux_map_enum,
2118c2ecf20Sopenharmony_ci				  AFE_HDMI_CONN0,
2128c2ecf20Sopenharmony_ci				  HDMI_O_5_SFT,
2138c2ecf20Sopenharmony_ci				  HDMI_O_5_MASK,
2148c2ecf20Sopenharmony_ci				  hdmi_conn_mux_map,
2158c2ecf20Sopenharmony_ci				  hdmi_conn_mux_map_value);
2168c2ecf20Sopenharmony_ci
2178c2ecf20Sopenharmony_cistatic const struct snd_kcontrol_new hdmi_ch5_mux_control =
2188c2ecf20Sopenharmony_ci	SOC_DAPM_ENUM("HDMI_CH5_MUX", hdmi_ch5_mux_map_enum);
2198c2ecf20Sopenharmony_ci
2208c2ecf20Sopenharmony_cistatic SOC_VALUE_ENUM_SINGLE_DECL(hdmi_ch6_mux_map_enum,
2218c2ecf20Sopenharmony_ci				  AFE_HDMI_CONN0,
2228c2ecf20Sopenharmony_ci				  HDMI_O_6_SFT,
2238c2ecf20Sopenharmony_ci				  HDMI_O_6_MASK,
2248c2ecf20Sopenharmony_ci				  hdmi_conn_mux_map,
2258c2ecf20Sopenharmony_ci				  hdmi_conn_mux_map_value);
2268c2ecf20Sopenharmony_ci
2278c2ecf20Sopenharmony_cistatic const struct snd_kcontrol_new hdmi_ch6_mux_control =
2288c2ecf20Sopenharmony_ci	SOC_DAPM_ENUM("HDMI_CH6_MUX", hdmi_ch6_mux_map_enum);
2298c2ecf20Sopenharmony_ci
2308c2ecf20Sopenharmony_cistatic SOC_VALUE_ENUM_SINGLE_DECL(hdmi_ch7_mux_map_enum,
2318c2ecf20Sopenharmony_ci				  AFE_HDMI_CONN0,
2328c2ecf20Sopenharmony_ci				  HDMI_O_7_SFT,
2338c2ecf20Sopenharmony_ci				  HDMI_O_7_MASK,
2348c2ecf20Sopenharmony_ci				  hdmi_conn_mux_map,
2358c2ecf20Sopenharmony_ci				  hdmi_conn_mux_map_value);
2368c2ecf20Sopenharmony_ci
2378c2ecf20Sopenharmony_cistatic const struct snd_kcontrol_new hdmi_ch7_mux_control =
2388c2ecf20Sopenharmony_ci	SOC_DAPM_ENUM("HDMI_CH7_MUX", hdmi_ch7_mux_map_enum);
2398c2ecf20Sopenharmony_ci
2408c2ecf20Sopenharmony_cienum {
2418c2ecf20Sopenharmony_ci	SUPPLY_SEQ_APLL,
2428c2ecf20Sopenharmony_ci	SUPPLY_SEQ_TDM_MCK_EN,
2438c2ecf20Sopenharmony_ci	SUPPLY_SEQ_TDM_BCK_EN,
2448c2ecf20Sopenharmony_ci};
2458c2ecf20Sopenharmony_ci
2468c2ecf20Sopenharmony_cistatic int mtk_tdm_bck_en_event(struct snd_soc_dapm_widget *w,
2478c2ecf20Sopenharmony_ci				struct snd_kcontrol *kcontrol,
2488c2ecf20Sopenharmony_ci				int event)
2498c2ecf20Sopenharmony_ci{
2508c2ecf20Sopenharmony_ci	struct snd_soc_component *cmpnt = snd_soc_dapm_to_component(w->dapm);
2518c2ecf20Sopenharmony_ci	struct mtk_base_afe *afe = snd_soc_component_get_drvdata(cmpnt);
2528c2ecf20Sopenharmony_ci	struct mt8183_afe_private *afe_priv = afe->platform_priv;
2538c2ecf20Sopenharmony_ci	struct mtk_afe_tdm_priv *tdm_priv = afe_priv->dai_priv[MT8183_DAI_TDM];
2548c2ecf20Sopenharmony_ci
2558c2ecf20Sopenharmony_ci	dev_info(cmpnt->dev, "%s(), name %s, event 0x%x\n",
2568c2ecf20Sopenharmony_ci		 __func__, w->name, event);
2578c2ecf20Sopenharmony_ci
2588c2ecf20Sopenharmony_ci	switch (event) {
2598c2ecf20Sopenharmony_ci	case SND_SOC_DAPM_PRE_PMU:
2608c2ecf20Sopenharmony_ci		mt8183_mck_enable(afe, tdm_priv->bck_id, tdm_priv->bck_rate);
2618c2ecf20Sopenharmony_ci		break;
2628c2ecf20Sopenharmony_ci	case SND_SOC_DAPM_POST_PMD:
2638c2ecf20Sopenharmony_ci		mt8183_mck_disable(afe, tdm_priv->bck_id);
2648c2ecf20Sopenharmony_ci		break;
2658c2ecf20Sopenharmony_ci	default:
2668c2ecf20Sopenharmony_ci		break;
2678c2ecf20Sopenharmony_ci	}
2688c2ecf20Sopenharmony_ci
2698c2ecf20Sopenharmony_ci	return 0;
2708c2ecf20Sopenharmony_ci}
2718c2ecf20Sopenharmony_ci
2728c2ecf20Sopenharmony_cistatic int mtk_tdm_mck_en_event(struct snd_soc_dapm_widget *w,
2738c2ecf20Sopenharmony_ci				struct snd_kcontrol *kcontrol,
2748c2ecf20Sopenharmony_ci				int event)
2758c2ecf20Sopenharmony_ci{
2768c2ecf20Sopenharmony_ci	struct snd_soc_component *cmpnt = snd_soc_dapm_to_component(w->dapm);
2778c2ecf20Sopenharmony_ci	struct mtk_base_afe *afe = snd_soc_component_get_drvdata(cmpnt);
2788c2ecf20Sopenharmony_ci	struct mt8183_afe_private *afe_priv = afe->platform_priv;
2798c2ecf20Sopenharmony_ci	struct mtk_afe_tdm_priv *tdm_priv = afe_priv->dai_priv[MT8183_DAI_TDM];
2808c2ecf20Sopenharmony_ci
2818c2ecf20Sopenharmony_ci	dev_info(cmpnt->dev, "%s(), name %s, event 0x%x\n",
2828c2ecf20Sopenharmony_ci		 __func__, w->name, event);
2838c2ecf20Sopenharmony_ci
2848c2ecf20Sopenharmony_ci	switch (event) {
2858c2ecf20Sopenharmony_ci	case SND_SOC_DAPM_PRE_PMU:
2868c2ecf20Sopenharmony_ci		mt8183_mck_enable(afe, tdm_priv->mclk_id, tdm_priv->mclk_rate);
2878c2ecf20Sopenharmony_ci		break;
2888c2ecf20Sopenharmony_ci	case SND_SOC_DAPM_POST_PMD:
2898c2ecf20Sopenharmony_ci		tdm_priv->mclk_rate = 0;
2908c2ecf20Sopenharmony_ci		mt8183_mck_disable(afe, tdm_priv->mclk_id);
2918c2ecf20Sopenharmony_ci		break;
2928c2ecf20Sopenharmony_ci	default:
2938c2ecf20Sopenharmony_ci		break;
2948c2ecf20Sopenharmony_ci	}
2958c2ecf20Sopenharmony_ci
2968c2ecf20Sopenharmony_ci	return 0;
2978c2ecf20Sopenharmony_ci}
2988c2ecf20Sopenharmony_ci
2998c2ecf20Sopenharmony_cistatic const struct snd_soc_dapm_widget mtk_dai_tdm_widgets[] = {
3008c2ecf20Sopenharmony_ci	SND_SOC_DAPM_MUX("HDMI_CH0_MUX", SND_SOC_NOPM, 0, 0,
3018c2ecf20Sopenharmony_ci			 &hdmi_ch0_mux_control),
3028c2ecf20Sopenharmony_ci	SND_SOC_DAPM_MUX("HDMI_CH1_MUX", SND_SOC_NOPM, 0, 0,
3038c2ecf20Sopenharmony_ci			 &hdmi_ch1_mux_control),
3048c2ecf20Sopenharmony_ci	SND_SOC_DAPM_MUX("HDMI_CH2_MUX", SND_SOC_NOPM, 0, 0,
3058c2ecf20Sopenharmony_ci			 &hdmi_ch2_mux_control),
3068c2ecf20Sopenharmony_ci	SND_SOC_DAPM_MUX("HDMI_CH3_MUX", SND_SOC_NOPM, 0, 0,
3078c2ecf20Sopenharmony_ci			 &hdmi_ch3_mux_control),
3088c2ecf20Sopenharmony_ci	SND_SOC_DAPM_MUX("HDMI_CH4_MUX", SND_SOC_NOPM, 0, 0,
3098c2ecf20Sopenharmony_ci			 &hdmi_ch4_mux_control),
3108c2ecf20Sopenharmony_ci	SND_SOC_DAPM_MUX("HDMI_CH5_MUX", SND_SOC_NOPM, 0, 0,
3118c2ecf20Sopenharmony_ci			 &hdmi_ch5_mux_control),
3128c2ecf20Sopenharmony_ci	SND_SOC_DAPM_MUX("HDMI_CH6_MUX", SND_SOC_NOPM, 0, 0,
3138c2ecf20Sopenharmony_ci			 &hdmi_ch6_mux_control),
3148c2ecf20Sopenharmony_ci	SND_SOC_DAPM_MUX("HDMI_CH7_MUX", SND_SOC_NOPM, 0, 0,
3158c2ecf20Sopenharmony_ci			 &hdmi_ch7_mux_control),
3168c2ecf20Sopenharmony_ci
3178c2ecf20Sopenharmony_ci	SND_SOC_DAPM_CLOCK_SUPPLY("aud_tdm_clk"),
3188c2ecf20Sopenharmony_ci
3198c2ecf20Sopenharmony_ci	SND_SOC_DAPM_SUPPLY_S("TDM_BCK", SUPPLY_SEQ_TDM_BCK_EN,
3208c2ecf20Sopenharmony_ci			      SND_SOC_NOPM, 0, 0,
3218c2ecf20Sopenharmony_ci			      mtk_tdm_bck_en_event,
3228c2ecf20Sopenharmony_ci			      SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
3238c2ecf20Sopenharmony_ci
3248c2ecf20Sopenharmony_ci	SND_SOC_DAPM_SUPPLY_S("TDM_MCK", SUPPLY_SEQ_TDM_MCK_EN,
3258c2ecf20Sopenharmony_ci			      SND_SOC_NOPM, 0, 0,
3268c2ecf20Sopenharmony_ci			      mtk_tdm_mck_en_event,
3278c2ecf20Sopenharmony_ci			      SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
3288c2ecf20Sopenharmony_ci};
3298c2ecf20Sopenharmony_ci
3308c2ecf20Sopenharmony_cistatic int mtk_afe_tdm_apll_connect(struct snd_soc_dapm_widget *source,
3318c2ecf20Sopenharmony_ci				    struct snd_soc_dapm_widget *sink)
3328c2ecf20Sopenharmony_ci{
3338c2ecf20Sopenharmony_ci	struct snd_soc_dapm_widget *w = sink;
3348c2ecf20Sopenharmony_ci	struct snd_soc_component *cmpnt = snd_soc_dapm_to_component(w->dapm);
3358c2ecf20Sopenharmony_ci	struct mtk_base_afe *afe = snd_soc_component_get_drvdata(cmpnt);
3368c2ecf20Sopenharmony_ci	struct mt8183_afe_private *afe_priv = afe->platform_priv;
3378c2ecf20Sopenharmony_ci	struct mtk_afe_tdm_priv *tdm_priv = afe_priv->dai_priv[MT8183_DAI_TDM];
3388c2ecf20Sopenharmony_ci	int cur_apll;
3398c2ecf20Sopenharmony_ci
3408c2ecf20Sopenharmony_ci	/* which apll */
3418c2ecf20Sopenharmony_ci	cur_apll = mt8183_get_apll_by_name(afe, source->name);
3428c2ecf20Sopenharmony_ci
3438c2ecf20Sopenharmony_ci	return (tdm_priv->mclk_apll == cur_apll) ? 1 : 0;
3448c2ecf20Sopenharmony_ci}
3458c2ecf20Sopenharmony_ci
3468c2ecf20Sopenharmony_cistatic const struct snd_soc_dapm_route mtk_dai_tdm_routes[] = {
3478c2ecf20Sopenharmony_ci	{"HDMI_CH0_MUX", "CH0", "HDMI"},
3488c2ecf20Sopenharmony_ci	{"HDMI_CH0_MUX", "CH1", "HDMI"},
3498c2ecf20Sopenharmony_ci	{"HDMI_CH0_MUX", "CH2", "HDMI"},
3508c2ecf20Sopenharmony_ci	{"HDMI_CH0_MUX", "CH3", "HDMI"},
3518c2ecf20Sopenharmony_ci	{"HDMI_CH0_MUX", "CH4", "HDMI"},
3528c2ecf20Sopenharmony_ci	{"HDMI_CH0_MUX", "CH5", "HDMI"},
3538c2ecf20Sopenharmony_ci	{"HDMI_CH0_MUX", "CH6", "HDMI"},
3548c2ecf20Sopenharmony_ci	{"HDMI_CH0_MUX", "CH7", "HDMI"},
3558c2ecf20Sopenharmony_ci
3568c2ecf20Sopenharmony_ci	{"HDMI_CH1_MUX", "CH0", "HDMI"},
3578c2ecf20Sopenharmony_ci	{"HDMI_CH1_MUX", "CH1", "HDMI"},
3588c2ecf20Sopenharmony_ci	{"HDMI_CH1_MUX", "CH2", "HDMI"},
3598c2ecf20Sopenharmony_ci	{"HDMI_CH1_MUX", "CH3", "HDMI"},
3608c2ecf20Sopenharmony_ci	{"HDMI_CH1_MUX", "CH4", "HDMI"},
3618c2ecf20Sopenharmony_ci	{"HDMI_CH1_MUX", "CH5", "HDMI"},
3628c2ecf20Sopenharmony_ci	{"HDMI_CH1_MUX", "CH6", "HDMI"},
3638c2ecf20Sopenharmony_ci	{"HDMI_CH1_MUX", "CH7", "HDMI"},
3648c2ecf20Sopenharmony_ci
3658c2ecf20Sopenharmony_ci	{"HDMI_CH2_MUX", "CH0", "HDMI"},
3668c2ecf20Sopenharmony_ci	{"HDMI_CH2_MUX", "CH1", "HDMI"},
3678c2ecf20Sopenharmony_ci	{"HDMI_CH2_MUX", "CH2", "HDMI"},
3688c2ecf20Sopenharmony_ci	{"HDMI_CH2_MUX", "CH3", "HDMI"},
3698c2ecf20Sopenharmony_ci	{"HDMI_CH2_MUX", "CH4", "HDMI"},
3708c2ecf20Sopenharmony_ci	{"HDMI_CH2_MUX", "CH5", "HDMI"},
3718c2ecf20Sopenharmony_ci	{"HDMI_CH2_MUX", "CH6", "HDMI"},
3728c2ecf20Sopenharmony_ci	{"HDMI_CH2_MUX", "CH7", "HDMI"},
3738c2ecf20Sopenharmony_ci
3748c2ecf20Sopenharmony_ci	{"HDMI_CH3_MUX", "CH0", "HDMI"},
3758c2ecf20Sopenharmony_ci	{"HDMI_CH3_MUX", "CH1", "HDMI"},
3768c2ecf20Sopenharmony_ci	{"HDMI_CH3_MUX", "CH2", "HDMI"},
3778c2ecf20Sopenharmony_ci	{"HDMI_CH3_MUX", "CH3", "HDMI"},
3788c2ecf20Sopenharmony_ci	{"HDMI_CH3_MUX", "CH4", "HDMI"},
3798c2ecf20Sopenharmony_ci	{"HDMI_CH3_MUX", "CH5", "HDMI"},
3808c2ecf20Sopenharmony_ci	{"HDMI_CH3_MUX", "CH6", "HDMI"},
3818c2ecf20Sopenharmony_ci	{"HDMI_CH3_MUX", "CH7", "HDMI"},
3828c2ecf20Sopenharmony_ci
3838c2ecf20Sopenharmony_ci	{"HDMI_CH4_MUX", "CH0", "HDMI"},
3848c2ecf20Sopenharmony_ci	{"HDMI_CH4_MUX", "CH1", "HDMI"},
3858c2ecf20Sopenharmony_ci	{"HDMI_CH4_MUX", "CH2", "HDMI"},
3868c2ecf20Sopenharmony_ci	{"HDMI_CH4_MUX", "CH3", "HDMI"},
3878c2ecf20Sopenharmony_ci	{"HDMI_CH4_MUX", "CH4", "HDMI"},
3888c2ecf20Sopenharmony_ci	{"HDMI_CH4_MUX", "CH5", "HDMI"},
3898c2ecf20Sopenharmony_ci	{"HDMI_CH4_MUX", "CH6", "HDMI"},
3908c2ecf20Sopenharmony_ci	{"HDMI_CH4_MUX", "CH7", "HDMI"},
3918c2ecf20Sopenharmony_ci
3928c2ecf20Sopenharmony_ci	{"HDMI_CH5_MUX", "CH0", "HDMI"},
3938c2ecf20Sopenharmony_ci	{"HDMI_CH5_MUX", "CH1", "HDMI"},
3948c2ecf20Sopenharmony_ci	{"HDMI_CH5_MUX", "CH2", "HDMI"},
3958c2ecf20Sopenharmony_ci	{"HDMI_CH5_MUX", "CH3", "HDMI"},
3968c2ecf20Sopenharmony_ci	{"HDMI_CH5_MUX", "CH4", "HDMI"},
3978c2ecf20Sopenharmony_ci	{"HDMI_CH5_MUX", "CH5", "HDMI"},
3988c2ecf20Sopenharmony_ci	{"HDMI_CH5_MUX", "CH6", "HDMI"},
3998c2ecf20Sopenharmony_ci	{"HDMI_CH5_MUX", "CH7", "HDMI"},
4008c2ecf20Sopenharmony_ci
4018c2ecf20Sopenharmony_ci	{"HDMI_CH6_MUX", "CH0", "HDMI"},
4028c2ecf20Sopenharmony_ci	{"HDMI_CH6_MUX", "CH1", "HDMI"},
4038c2ecf20Sopenharmony_ci	{"HDMI_CH6_MUX", "CH2", "HDMI"},
4048c2ecf20Sopenharmony_ci	{"HDMI_CH6_MUX", "CH3", "HDMI"},
4058c2ecf20Sopenharmony_ci	{"HDMI_CH6_MUX", "CH4", "HDMI"},
4068c2ecf20Sopenharmony_ci	{"HDMI_CH6_MUX", "CH5", "HDMI"},
4078c2ecf20Sopenharmony_ci	{"HDMI_CH6_MUX", "CH6", "HDMI"},
4088c2ecf20Sopenharmony_ci	{"HDMI_CH6_MUX", "CH7", "HDMI"},
4098c2ecf20Sopenharmony_ci
4108c2ecf20Sopenharmony_ci	{"HDMI_CH7_MUX", "CH0", "HDMI"},
4118c2ecf20Sopenharmony_ci	{"HDMI_CH7_MUX", "CH1", "HDMI"},
4128c2ecf20Sopenharmony_ci	{"HDMI_CH7_MUX", "CH2", "HDMI"},
4138c2ecf20Sopenharmony_ci	{"HDMI_CH7_MUX", "CH3", "HDMI"},
4148c2ecf20Sopenharmony_ci	{"HDMI_CH7_MUX", "CH4", "HDMI"},
4158c2ecf20Sopenharmony_ci	{"HDMI_CH7_MUX", "CH5", "HDMI"},
4168c2ecf20Sopenharmony_ci	{"HDMI_CH7_MUX", "CH6", "HDMI"},
4178c2ecf20Sopenharmony_ci	{"HDMI_CH7_MUX", "CH7", "HDMI"},
4188c2ecf20Sopenharmony_ci
4198c2ecf20Sopenharmony_ci	{"TDM", NULL, "HDMI_CH0_MUX"},
4208c2ecf20Sopenharmony_ci	{"TDM", NULL, "HDMI_CH1_MUX"},
4218c2ecf20Sopenharmony_ci	{"TDM", NULL, "HDMI_CH2_MUX"},
4228c2ecf20Sopenharmony_ci	{"TDM", NULL, "HDMI_CH3_MUX"},
4238c2ecf20Sopenharmony_ci	{"TDM", NULL, "HDMI_CH4_MUX"},
4248c2ecf20Sopenharmony_ci	{"TDM", NULL, "HDMI_CH5_MUX"},
4258c2ecf20Sopenharmony_ci	{"TDM", NULL, "HDMI_CH6_MUX"},
4268c2ecf20Sopenharmony_ci	{"TDM", NULL, "HDMI_CH7_MUX"},
4278c2ecf20Sopenharmony_ci
4288c2ecf20Sopenharmony_ci	{"TDM", NULL, "aud_tdm_clk"},
4298c2ecf20Sopenharmony_ci	{"TDM", NULL, "TDM_BCK"},
4308c2ecf20Sopenharmony_ci	{"TDM_BCK", NULL, "TDM_MCK"},
4318c2ecf20Sopenharmony_ci	{"TDM_MCK", NULL, APLL1_W_NAME, mtk_afe_tdm_apll_connect},
4328c2ecf20Sopenharmony_ci	{"TDM_MCK", NULL, APLL2_W_NAME, mtk_afe_tdm_apll_connect},
4338c2ecf20Sopenharmony_ci};
4348c2ecf20Sopenharmony_ci
4358c2ecf20Sopenharmony_ci/* dai ops */
4368c2ecf20Sopenharmony_cistatic int mtk_dai_tdm_cal_mclk(struct mtk_base_afe *afe,
4378c2ecf20Sopenharmony_ci				struct mtk_afe_tdm_priv *tdm_priv,
4388c2ecf20Sopenharmony_ci				int freq)
4398c2ecf20Sopenharmony_ci{
4408c2ecf20Sopenharmony_ci	int apll;
4418c2ecf20Sopenharmony_ci	int apll_rate;
4428c2ecf20Sopenharmony_ci
4438c2ecf20Sopenharmony_ci	apll = mt8183_get_apll_by_rate(afe, freq);
4448c2ecf20Sopenharmony_ci	apll_rate = mt8183_get_apll_rate(afe, apll);
4458c2ecf20Sopenharmony_ci
4468c2ecf20Sopenharmony_ci	if (!freq || freq > apll_rate) {
4478c2ecf20Sopenharmony_ci		dev_warn(afe->dev,
4488c2ecf20Sopenharmony_ci			 "%s(), freq(%d Hz) invalid\n", __func__, freq);
4498c2ecf20Sopenharmony_ci		return -EINVAL;
4508c2ecf20Sopenharmony_ci	}
4518c2ecf20Sopenharmony_ci
4528c2ecf20Sopenharmony_ci	if (apll_rate % freq != 0) {
4538c2ecf20Sopenharmony_ci		dev_warn(afe->dev,
4548c2ecf20Sopenharmony_ci			 "%s(), APLL cannot generate %d Hz", __func__, freq);
4558c2ecf20Sopenharmony_ci		return -EINVAL;
4568c2ecf20Sopenharmony_ci	}
4578c2ecf20Sopenharmony_ci
4588c2ecf20Sopenharmony_ci	tdm_priv->mclk_rate = freq;
4598c2ecf20Sopenharmony_ci	tdm_priv->mclk_apll = apll;
4608c2ecf20Sopenharmony_ci
4618c2ecf20Sopenharmony_ci	return 0;
4628c2ecf20Sopenharmony_ci}
4638c2ecf20Sopenharmony_ci
4648c2ecf20Sopenharmony_cistatic int mtk_dai_tdm_hw_params(struct snd_pcm_substream *substream,
4658c2ecf20Sopenharmony_ci				 struct snd_pcm_hw_params *params,
4668c2ecf20Sopenharmony_ci				 struct snd_soc_dai *dai)
4678c2ecf20Sopenharmony_ci{
4688c2ecf20Sopenharmony_ci	struct mtk_base_afe *afe = snd_soc_dai_get_drvdata(dai);
4698c2ecf20Sopenharmony_ci	struct mt8183_afe_private *afe_priv = afe->platform_priv;
4708c2ecf20Sopenharmony_ci	int tdm_id = dai->id;
4718c2ecf20Sopenharmony_ci	struct mtk_afe_tdm_priv *tdm_priv = afe_priv->dai_priv[tdm_id];
4728c2ecf20Sopenharmony_ci	unsigned int tdm_out_mode = tdm_priv->tdm_out_mode;
4738c2ecf20Sopenharmony_ci	unsigned int rate = params_rate(params);
4748c2ecf20Sopenharmony_ci	unsigned int channels = params_channels(params);
4758c2ecf20Sopenharmony_ci	unsigned int out_channels_per_sdata =
4768c2ecf20Sopenharmony_ci		get_tdm_ch_per_sdata(tdm_out_mode, channels);
4778c2ecf20Sopenharmony_ci	snd_pcm_format_t format = params_format(params);
4788c2ecf20Sopenharmony_ci	unsigned int tdm_con = 0;
4798c2ecf20Sopenharmony_ci
4808c2ecf20Sopenharmony_ci	/* calculate mclk_rate, if not set explicitly */
4818c2ecf20Sopenharmony_ci	if (!tdm_priv->mclk_rate) {
4828c2ecf20Sopenharmony_ci		tdm_priv->mclk_rate = rate * tdm_priv->mclk_multiple;
4838c2ecf20Sopenharmony_ci		mtk_dai_tdm_cal_mclk(afe,
4848c2ecf20Sopenharmony_ci				     tdm_priv,
4858c2ecf20Sopenharmony_ci				     tdm_priv->mclk_rate);
4868c2ecf20Sopenharmony_ci	}
4878c2ecf20Sopenharmony_ci
4888c2ecf20Sopenharmony_ci	/* calculate bck */
4898c2ecf20Sopenharmony_ci	tdm_priv->bck_rate = rate *
4908c2ecf20Sopenharmony_ci			     out_channels_per_sdata *
4918c2ecf20Sopenharmony_ci			     snd_pcm_format_physical_width(format);
4928c2ecf20Sopenharmony_ci
4938c2ecf20Sopenharmony_ci	if (tdm_priv->bck_rate > tdm_priv->mclk_rate)
4948c2ecf20Sopenharmony_ci		dev_warn(afe->dev, "%s(), bck_rate > mclk_rate rate", __func__);
4958c2ecf20Sopenharmony_ci
4968c2ecf20Sopenharmony_ci	if (tdm_priv->mclk_rate % tdm_priv->bck_rate != 0)
4978c2ecf20Sopenharmony_ci		dev_warn(afe->dev, "%s(), bck cannot generate", __func__);
4988c2ecf20Sopenharmony_ci
4998c2ecf20Sopenharmony_ci	dev_info(afe->dev, "%s(), id %d, rate %d, channels %d, format %d, mclk_rate %d, bck_rate %d\n",
5008c2ecf20Sopenharmony_ci		 __func__,
5018c2ecf20Sopenharmony_ci		 tdm_id, rate, channels, format,
5028c2ecf20Sopenharmony_ci		 tdm_priv->mclk_rate, tdm_priv->bck_rate);
5038c2ecf20Sopenharmony_ci	dev_info(afe->dev, "%s(), out_channels_per_sdata = %d\n",
5048c2ecf20Sopenharmony_ci		 __func__, out_channels_per_sdata);
5058c2ecf20Sopenharmony_ci
5068c2ecf20Sopenharmony_ci	/* set tdm */
5078c2ecf20Sopenharmony_ci	if (tdm_priv->bck_invert)
5088c2ecf20Sopenharmony_ci		regmap_update_bits(afe->regmap, AUDIO_TOP_CON3,
5098c2ecf20Sopenharmony_ci				   BCK_INVERSE_MASK_SFT,
5108c2ecf20Sopenharmony_ci				   0x1 << BCK_INVERSE_SFT);
5118c2ecf20Sopenharmony_ci
5128c2ecf20Sopenharmony_ci	if (tdm_priv->lck_invert)
5138c2ecf20Sopenharmony_ci		tdm_con |= 1 << LRCK_INVERSE_SFT;
5148c2ecf20Sopenharmony_ci
5158c2ecf20Sopenharmony_ci	if (tdm_priv->tdm_out_mode == TDM_OUT_I2S) {
5168c2ecf20Sopenharmony_ci		tdm_con |= 1 << DELAY_DATA_SFT;
5178c2ecf20Sopenharmony_ci		tdm_con |= get_tdm_lrck_width(format) << LRCK_TDM_WIDTH_SFT;
5188c2ecf20Sopenharmony_ci	} else if (tdm_priv->tdm_out_mode == TDM_OUT_TDM) {
5198c2ecf20Sopenharmony_ci		tdm_con |= 0 << DELAY_DATA_SFT;
5208c2ecf20Sopenharmony_ci		tdm_con |= 0 << LRCK_TDM_WIDTH_SFT;
5218c2ecf20Sopenharmony_ci	}
5228c2ecf20Sopenharmony_ci
5238c2ecf20Sopenharmony_ci	tdm_con |= 1 << LEFT_ALIGN_SFT;
5248c2ecf20Sopenharmony_ci	tdm_con |= get_tdm_wlen(format) << WLEN_SFT;
5258c2ecf20Sopenharmony_ci	tdm_con |= get_tdm_ch(out_channels_per_sdata) << CHANNEL_NUM_SFT;
5268c2ecf20Sopenharmony_ci	tdm_con |= get_tdm_channel_bck(format) << CHANNEL_BCK_CYCLES_SFT;
5278c2ecf20Sopenharmony_ci	regmap_write(afe->regmap, AFE_TDM_CON1, tdm_con);
5288c2ecf20Sopenharmony_ci
5298c2ecf20Sopenharmony_ci	if (out_channels_per_sdata == 2) {
5308c2ecf20Sopenharmony_ci		switch (channels) {
5318c2ecf20Sopenharmony_ci		case 1:
5328c2ecf20Sopenharmony_ci		case 2:
5338c2ecf20Sopenharmony_ci			tdm_con = TDM_CH_START_O30_O31 << ST_CH_PAIR_SOUT0_SFT;
5348c2ecf20Sopenharmony_ci			tdm_con |= TDM_CH_ZERO << ST_CH_PAIR_SOUT1_SFT;
5358c2ecf20Sopenharmony_ci			tdm_con |= TDM_CH_ZERO << ST_CH_PAIR_SOUT2_SFT;
5368c2ecf20Sopenharmony_ci			tdm_con |= TDM_CH_ZERO << ST_CH_PAIR_SOUT3_SFT;
5378c2ecf20Sopenharmony_ci			break;
5388c2ecf20Sopenharmony_ci		case 3:
5398c2ecf20Sopenharmony_ci		case 4:
5408c2ecf20Sopenharmony_ci			tdm_con = TDM_CH_START_O30_O31 << ST_CH_PAIR_SOUT0_SFT;
5418c2ecf20Sopenharmony_ci			tdm_con |= TDM_CH_START_O32_O33 << ST_CH_PAIR_SOUT1_SFT;
5428c2ecf20Sopenharmony_ci			tdm_con |= TDM_CH_ZERO << ST_CH_PAIR_SOUT2_SFT;
5438c2ecf20Sopenharmony_ci			tdm_con |= TDM_CH_ZERO << ST_CH_PAIR_SOUT3_SFT;
5448c2ecf20Sopenharmony_ci			break;
5458c2ecf20Sopenharmony_ci		case 5:
5468c2ecf20Sopenharmony_ci		case 6:
5478c2ecf20Sopenharmony_ci			tdm_con = TDM_CH_START_O30_O31 << ST_CH_PAIR_SOUT0_SFT;
5488c2ecf20Sopenharmony_ci			tdm_con |= TDM_CH_START_O32_O33 << ST_CH_PAIR_SOUT1_SFT;
5498c2ecf20Sopenharmony_ci			tdm_con |= TDM_CH_START_O34_O35 << ST_CH_PAIR_SOUT2_SFT;
5508c2ecf20Sopenharmony_ci			tdm_con |= TDM_CH_ZERO << ST_CH_PAIR_SOUT3_SFT;
5518c2ecf20Sopenharmony_ci			break;
5528c2ecf20Sopenharmony_ci		case 7:
5538c2ecf20Sopenharmony_ci		case 8:
5548c2ecf20Sopenharmony_ci			tdm_con = TDM_CH_START_O30_O31 << ST_CH_PAIR_SOUT0_SFT;
5558c2ecf20Sopenharmony_ci			tdm_con |= TDM_CH_START_O32_O33 << ST_CH_PAIR_SOUT1_SFT;
5568c2ecf20Sopenharmony_ci			tdm_con |= TDM_CH_START_O34_O35 << ST_CH_PAIR_SOUT2_SFT;
5578c2ecf20Sopenharmony_ci			tdm_con |= TDM_CH_START_O36_O37 << ST_CH_PAIR_SOUT3_SFT;
5588c2ecf20Sopenharmony_ci			break;
5598c2ecf20Sopenharmony_ci		default:
5608c2ecf20Sopenharmony_ci			tdm_con = 0;
5618c2ecf20Sopenharmony_ci		}
5628c2ecf20Sopenharmony_ci	} else {
5638c2ecf20Sopenharmony_ci		tdm_con = TDM_CH_START_O30_O31 << ST_CH_PAIR_SOUT0_SFT;
5648c2ecf20Sopenharmony_ci		tdm_con |= TDM_CH_ZERO << ST_CH_PAIR_SOUT1_SFT;
5658c2ecf20Sopenharmony_ci		tdm_con |= TDM_CH_ZERO << ST_CH_PAIR_SOUT2_SFT;
5668c2ecf20Sopenharmony_ci		tdm_con |= TDM_CH_ZERO << ST_CH_PAIR_SOUT3_SFT;
5678c2ecf20Sopenharmony_ci	}
5688c2ecf20Sopenharmony_ci
5698c2ecf20Sopenharmony_ci	regmap_write(afe->regmap, AFE_TDM_CON2, tdm_con);
5708c2ecf20Sopenharmony_ci
5718c2ecf20Sopenharmony_ci	regmap_update_bits(afe->regmap, AFE_HDMI_OUT_CON0,
5728c2ecf20Sopenharmony_ci			   AFE_HDMI_OUT_CH_NUM_MASK_SFT,
5738c2ecf20Sopenharmony_ci			   channels << AFE_HDMI_OUT_CH_NUM_SFT);
5748c2ecf20Sopenharmony_ci
5758c2ecf20Sopenharmony_ci	regmap_update_bits(afe->regmap, AFE_HDMI_OUT_CON0,
5768c2ecf20Sopenharmony_ci			   AFE_HDMI_OUT_BIT_WIDTH_MASK_SFT,
5778c2ecf20Sopenharmony_ci			   get_hdmi_wlen(format) << AFE_HDMI_OUT_BIT_WIDTH_SFT);
5788c2ecf20Sopenharmony_ci	return 0;
5798c2ecf20Sopenharmony_ci}
5808c2ecf20Sopenharmony_ci
5818c2ecf20Sopenharmony_cistatic int mtk_dai_tdm_trigger(struct snd_pcm_substream *substream,
5828c2ecf20Sopenharmony_ci			       int cmd,
5838c2ecf20Sopenharmony_ci			       struct snd_soc_dai *dai)
5848c2ecf20Sopenharmony_ci{
5858c2ecf20Sopenharmony_ci	struct mtk_base_afe *afe = snd_soc_dai_get_drvdata(dai);
5868c2ecf20Sopenharmony_ci
5878c2ecf20Sopenharmony_ci	switch (cmd) {
5888c2ecf20Sopenharmony_ci	case SNDRV_PCM_TRIGGER_START:
5898c2ecf20Sopenharmony_ci	case SNDRV_PCM_TRIGGER_RESUME:
5908c2ecf20Sopenharmony_ci		/* enable Out control */
5918c2ecf20Sopenharmony_ci		regmap_update_bits(afe->regmap, AFE_HDMI_OUT_CON0,
5928c2ecf20Sopenharmony_ci				   AFE_HDMI_OUT_ON_MASK_SFT,
5938c2ecf20Sopenharmony_ci				   0x1 << AFE_HDMI_OUT_ON_SFT);
5948c2ecf20Sopenharmony_ci		/* enable tdm */
5958c2ecf20Sopenharmony_ci		regmap_update_bits(afe->regmap, AFE_TDM_CON1,
5968c2ecf20Sopenharmony_ci				   TDM_EN_MASK_SFT, 0x1 << TDM_EN_SFT);
5978c2ecf20Sopenharmony_ci		break;
5988c2ecf20Sopenharmony_ci	case SNDRV_PCM_TRIGGER_STOP:
5998c2ecf20Sopenharmony_ci	case SNDRV_PCM_TRIGGER_SUSPEND:
6008c2ecf20Sopenharmony_ci		/* disable tdm */
6018c2ecf20Sopenharmony_ci		regmap_update_bits(afe->regmap, AFE_TDM_CON1,
6028c2ecf20Sopenharmony_ci				   TDM_EN_MASK_SFT, 0);
6038c2ecf20Sopenharmony_ci		/* disable Out control */
6048c2ecf20Sopenharmony_ci		regmap_update_bits(afe->regmap, AFE_HDMI_OUT_CON0,
6058c2ecf20Sopenharmony_ci				   AFE_HDMI_OUT_ON_MASK_SFT,
6068c2ecf20Sopenharmony_ci				   0);
6078c2ecf20Sopenharmony_ci		break;
6088c2ecf20Sopenharmony_ci	default:
6098c2ecf20Sopenharmony_ci		return -EINVAL;
6108c2ecf20Sopenharmony_ci	}
6118c2ecf20Sopenharmony_ci
6128c2ecf20Sopenharmony_ci	return 0;
6138c2ecf20Sopenharmony_ci}
6148c2ecf20Sopenharmony_ci
6158c2ecf20Sopenharmony_cistatic int mtk_dai_tdm_set_sysclk(struct snd_soc_dai *dai,
6168c2ecf20Sopenharmony_ci				  int clk_id, unsigned int freq, int dir)
6178c2ecf20Sopenharmony_ci{
6188c2ecf20Sopenharmony_ci	struct mtk_base_afe *afe = dev_get_drvdata(dai->dev);
6198c2ecf20Sopenharmony_ci	struct mt8183_afe_private *afe_priv = afe->platform_priv;
6208c2ecf20Sopenharmony_ci	struct mtk_afe_tdm_priv *tdm_priv = afe_priv->dai_priv[dai->id];
6218c2ecf20Sopenharmony_ci
6228c2ecf20Sopenharmony_ci	if (!tdm_priv) {
6238c2ecf20Sopenharmony_ci		dev_warn(afe->dev, "%s(), tdm_priv == NULL", __func__);
6248c2ecf20Sopenharmony_ci		return -EINVAL;
6258c2ecf20Sopenharmony_ci	}
6268c2ecf20Sopenharmony_ci
6278c2ecf20Sopenharmony_ci	if (dir != SND_SOC_CLOCK_OUT) {
6288c2ecf20Sopenharmony_ci		dev_warn(afe->dev, "%s(), dir != SND_SOC_CLOCK_OUT", __func__);
6298c2ecf20Sopenharmony_ci		return -EINVAL;
6308c2ecf20Sopenharmony_ci	}
6318c2ecf20Sopenharmony_ci
6328c2ecf20Sopenharmony_ci	dev_info(afe->dev, "%s(), freq %d\n", __func__, freq);
6338c2ecf20Sopenharmony_ci
6348c2ecf20Sopenharmony_ci	return mtk_dai_tdm_cal_mclk(afe, tdm_priv, freq);
6358c2ecf20Sopenharmony_ci}
6368c2ecf20Sopenharmony_ci
6378c2ecf20Sopenharmony_cistatic int mtk_dai_tdm_set_fmt(struct snd_soc_dai *dai, unsigned int fmt)
6388c2ecf20Sopenharmony_ci{
6398c2ecf20Sopenharmony_ci	struct mtk_base_afe *afe = dev_get_drvdata(dai->dev);
6408c2ecf20Sopenharmony_ci	struct mt8183_afe_private *afe_priv = afe->platform_priv;
6418c2ecf20Sopenharmony_ci	struct mtk_afe_tdm_priv *tdm_priv = afe_priv->dai_priv[dai->id];
6428c2ecf20Sopenharmony_ci
6438c2ecf20Sopenharmony_ci	if (!tdm_priv) {
6448c2ecf20Sopenharmony_ci		dev_warn(afe->dev, "%s(), tdm_priv == NULL", __func__);
6458c2ecf20Sopenharmony_ci		return -EINVAL;
6468c2ecf20Sopenharmony_ci	}
6478c2ecf20Sopenharmony_ci
6488c2ecf20Sopenharmony_ci	/* DAI mode*/
6498c2ecf20Sopenharmony_ci	switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
6508c2ecf20Sopenharmony_ci	case SND_SOC_DAIFMT_I2S:
6518c2ecf20Sopenharmony_ci		tdm_priv->tdm_out_mode = TDM_OUT_I2S;
6528c2ecf20Sopenharmony_ci		break;
6538c2ecf20Sopenharmony_ci	case SND_SOC_DAIFMT_DSP_A:
6548c2ecf20Sopenharmony_ci		tdm_priv->tdm_out_mode = TDM_OUT_TDM;
6558c2ecf20Sopenharmony_ci		break;
6568c2ecf20Sopenharmony_ci	default:
6578c2ecf20Sopenharmony_ci		tdm_priv->tdm_out_mode = TDM_OUT_I2S;
6588c2ecf20Sopenharmony_ci	}
6598c2ecf20Sopenharmony_ci
6608c2ecf20Sopenharmony_ci	/* DAI clock inversion*/
6618c2ecf20Sopenharmony_ci	switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
6628c2ecf20Sopenharmony_ci	case SND_SOC_DAIFMT_NB_NF:
6638c2ecf20Sopenharmony_ci		tdm_priv->bck_invert = TDM_BCK_NON_INV;
6648c2ecf20Sopenharmony_ci		tdm_priv->lck_invert = TDM_LCK_NON_INV;
6658c2ecf20Sopenharmony_ci		break;
6668c2ecf20Sopenharmony_ci	case SND_SOC_DAIFMT_NB_IF:
6678c2ecf20Sopenharmony_ci		tdm_priv->bck_invert = TDM_BCK_NON_INV;
6688c2ecf20Sopenharmony_ci		tdm_priv->lck_invert = TDM_LCK_INV;
6698c2ecf20Sopenharmony_ci		break;
6708c2ecf20Sopenharmony_ci	case SND_SOC_DAIFMT_IB_NF:
6718c2ecf20Sopenharmony_ci		tdm_priv->bck_invert = TDM_BCK_INV;
6728c2ecf20Sopenharmony_ci		tdm_priv->lck_invert = TDM_LCK_NON_INV;
6738c2ecf20Sopenharmony_ci		break;
6748c2ecf20Sopenharmony_ci	case SND_SOC_DAIFMT_IB_IF:
6758c2ecf20Sopenharmony_ci	default:
6768c2ecf20Sopenharmony_ci		tdm_priv->bck_invert = TDM_BCK_INV;
6778c2ecf20Sopenharmony_ci		tdm_priv->lck_invert = TDM_LCK_INV;
6788c2ecf20Sopenharmony_ci		break;
6798c2ecf20Sopenharmony_ci	}
6808c2ecf20Sopenharmony_ci
6818c2ecf20Sopenharmony_ci	return 0;
6828c2ecf20Sopenharmony_ci}
6838c2ecf20Sopenharmony_ci
6848c2ecf20Sopenharmony_cistatic const struct snd_soc_dai_ops mtk_dai_tdm_ops = {
6858c2ecf20Sopenharmony_ci	.hw_params = mtk_dai_tdm_hw_params,
6868c2ecf20Sopenharmony_ci	.trigger = mtk_dai_tdm_trigger,
6878c2ecf20Sopenharmony_ci	.set_sysclk = mtk_dai_tdm_set_sysclk,
6888c2ecf20Sopenharmony_ci	.set_fmt = mtk_dai_tdm_set_fmt,
6898c2ecf20Sopenharmony_ci};
6908c2ecf20Sopenharmony_ci
6918c2ecf20Sopenharmony_ci/* dai driver */
6928c2ecf20Sopenharmony_ci#define MTK_TDM_RATES (SNDRV_PCM_RATE_8000_48000 |\
6938c2ecf20Sopenharmony_ci		       SNDRV_PCM_RATE_88200 |\
6948c2ecf20Sopenharmony_ci		       SNDRV_PCM_RATE_96000 |\
6958c2ecf20Sopenharmony_ci		       SNDRV_PCM_RATE_176400 |\
6968c2ecf20Sopenharmony_ci		       SNDRV_PCM_RATE_192000)
6978c2ecf20Sopenharmony_ci
6988c2ecf20Sopenharmony_ci#define MTK_TDM_FORMATS (SNDRV_PCM_FMTBIT_S16_LE |\
6998c2ecf20Sopenharmony_ci			 SNDRV_PCM_FMTBIT_S24_LE |\
7008c2ecf20Sopenharmony_ci			 SNDRV_PCM_FMTBIT_S32_LE)
7018c2ecf20Sopenharmony_ci
7028c2ecf20Sopenharmony_cistatic struct snd_soc_dai_driver mtk_dai_tdm_driver[] = {
7038c2ecf20Sopenharmony_ci	{
7048c2ecf20Sopenharmony_ci		.name = "TDM",
7058c2ecf20Sopenharmony_ci		.id = MT8183_DAI_TDM,
7068c2ecf20Sopenharmony_ci		.playback = {
7078c2ecf20Sopenharmony_ci			.stream_name = "TDM",
7088c2ecf20Sopenharmony_ci			.channels_min = 2,
7098c2ecf20Sopenharmony_ci			.channels_max = 8,
7108c2ecf20Sopenharmony_ci			.rates = MTK_TDM_RATES,
7118c2ecf20Sopenharmony_ci			.formats = MTK_TDM_FORMATS,
7128c2ecf20Sopenharmony_ci		},
7138c2ecf20Sopenharmony_ci		.ops = &mtk_dai_tdm_ops,
7148c2ecf20Sopenharmony_ci	},
7158c2ecf20Sopenharmony_ci};
7168c2ecf20Sopenharmony_ci
7178c2ecf20Sopenharmony_ciint mt8183_dai_tdm_register(struct mtk_base_afe *afe)
7188c2ecf20Sopenharmony_ci{
7198c2ecf20Sopenharmony_ci	struct mt8183_afe_private *afe_priv = afe->platform_priv;
7208c2ecf20Sopenharmony_ci	struct mtk_afe_tdm_priv *tdm_priv;
7218c2ecf20Sopenharmony_ci	struct mtk_base_afe_dai *dai;
7228c2ecf20Sopenharmony_ci
7238c2ecf20Sopenharmony_ci	dai = devm_kzalloc(afe->dev, sizeof(*dai), GFP_KERNEL);
7248c2ecf20Sopenharmony_ci	if (!dai)
7258c2ecf20Sopenharmony_ci		return -ENOMEM;
7268c2ecf20Sopenharmony_ci
7278c2ecf20Sopenharmony_ci	list_add(&dai->list, &afe->sub_dais);
7288c2ecf20Sopenharmony_ci
7298c2ecf20Sopenharmony_ci	dai->dai_drivers = mtk_dai_tdm_driver;
7308c2ecf20Sopenharmony_ci	dai->num_dai_drivers = ARRAY_SIZE(mtk_dai_tdm_driver);
7318c2ecf20Sopenharmony_ci
7328c2ecf20Sopenharmony_ci	dai->dapm_widgets = mtk_dai_tdm_widgets;
7338c2ecf20Sopenharmony_ci	dai->num_dapm_widgets = ARRAY_SIZE(mtk_dai_tdm_widgets);
7348c2ecf20Sopenharmony_ci	dai->dapm_routes = mtk_dai_tdm_routes;
7358c2ecf20Sopenharmony_ci	dai->num_dapm_routes = ARRAY_SIZE(mtk_dai_tdm_routes);
7368c2ecf20Sopenharmony_ci
7378c2ecf20Sopenharmony_ci	tdm_priv = devm_kzalloc(afe->dev, sizeof(struct mtk_afe_tdm_priv),
7388c2ecf20Sopenharmony_ci				GFP_KERNEL);
7398c2ecf20Sopenharmony_ci	if (!tdm_priv)
7408c2ecf20Sopenharmony_ci		return -ENOMEM;
7418c2ecf20Sopenharmony_ci
7428c2ecf20Sopenharmony_ci	tdm_priv->mclk_multiple = 128;
7438c2ecf20Sopenharmony_ci	tdm_priv->bck_id = MT8183_I2S4_BCK;
7448c2ecf20Sopenharmony_ci	tdm_priv->mclk_id = MT8183_I2S4_MCK;
7458c2ecf20Sopenharmony_ci
7468c2ecf20Sopenharmony_ci	afe_priv->dai_priv[MT8183_DAI_TDM] = tdm_priv;
7478c2ecf20Sopenharmony_ci	return 0;
7488c2ecf20Sopenharmony_ci}
749