1ae92dcbeSJiaxin Yu // SPDX-License-Identifier: GPL-2.0
2ae92dcbeSJiaxin Yu //
3ae92dcbeSJiaxin Yu // MediaTek ALSA SoC Audio DAI TDM Control
4ae92dcbeSJiaxin Yu //
5ae92dcbeSJiaxin Yu // Copyright (c) 2022 MediaTek Inc.
6ae92dcbeSJiaxin Yu // Author: Jiaxin Yu <jiaxin.yu@mediatek.com>
7ae92dcbeSJiaxin Yu 
8ae92dcbeSJiaxin Yu #include <linux/regmap.h>
9ae92dcbeSJiaxin Yu #include <sound/pcm_params.h>
10ae92dcbeSJiaxin Yu 
11ae92dcbeSJiaxin Yu #include "mt8186-afe-clk.h"
12ae92dcbeSJiaxin Yu #include "mt8186-afe-common.h"
13ae92dcbeSJiaxin Yu #include "mt8186-afe-gpio.h"
14ae92dcbeSJiaxin Yu #include "mt8186-interconnection.h"
15ae92dcbeSJiaxin Yu 
16ae92dcbeSJiaxin Yu #define TDM_HD_EN_W_NAME "TDM_HD_EN"
17ae92dcbeSJiaxin Yu #define TDM_MCLK_EN_W_NAME "TDM_MCLK_EN"
18ae92dcbeSJiaxin Yu #define MTK_AFE_TDM_KCONTROL_NAME "TDM_HD_Mux"
19ae92dcbeSJiaxin Yu 
20ae92dcbeSJiaxin Yu struct mtk_afe_tdm_priv {
21ae92dcbeSJiaxin Yu 	unsigned int id;
22ae92dcbeSJiaxin Yu 	unsigned int rate; /* for determine which apll to use */
23ae92dcbeSJiaxin Yu 	unsigned int bck_invert;
24ae92dcbeSJiaxin Yu 	unsigned int lck_invert;
25ae92dcbeSJiaxin Yu 	unsigned int lrck_width;
26ae92dcbeSJiaxin Yu 	unsigned int mclk_id;
27ae92dcbeSJiaxin Yu 	unsigned int mclk_multiple; /* according to sample rate */
28ae92dcbeSJiaxin Yu 	unsigned int mclk_rate;
29ae92dcbeSJiaxin Yu 	unsigned int mclk_apll;
30ae92dcbeSJiaxin Yu 	unsigned int tdm_mode;
31ae92dcbeSJiaxin Yu 	unsigned int data_mode;
32ae92dcbeSJiaxin Yu 	unsigned int slave_mode;
33ae92dcbeSJiaxin Yu 	unsigned int low_jitter_en;
34ae92dcbeSJiaxin Yu };
35ae92dcbeSJiaxin Yu 
36ae92dcbeSJiaxin Yu enum {
37ae92dcbeSJiaxin Yu 	TDM_IN_I2S = 0,
38ae92dcbeSJiaxin Yu 	TDM_IN_LJ = 1,
39ae92dcbeSJiaxin Yu 	TDM_IN_RJ = 2,
40ae92dcbeSJiaxin Yu 	TDM_IN_DSP_A = 4,
41ae92dcbeSJiaxin Yu 	TDM_IN_DSP_B = 5,
42ae92dcbeSJiaxin Yu };
43ae92dcbeSJiaxin Yu 
44ae92dcbeSJiaxin Yu enum {
45ae92dcbeSJiaxin Yu 	TDM_DATA_ONE_PIN = 0,
46ae92dcbeSJiaxin Yu 	TDM_DATA_MULTI_PIN,
47ae92dcbeSJiaxin Yu };
48ae92dcbeSJiaxin Yu 
49ae92dcbeSJiaxin Yu enum {
50ae92dcbeSJiaxin Yu 	TDM_BCK_NON_INV = 0,
51ae92dcbeSJiaxin Yu 	TDM_BCK_INV = 1,
52ae92dcbeSJiaxin Yu };
53ae92dcbeSJiaxin Yu 
54ae92dcbeSJiaxin Yu enum {
55ae92dcbeSJiaxin Yu 	TDM_LCK_NON_INV = 0,
56ae92dcbeSJiaxin Yu 	TDM_LCK_INV = 1,
57ae92dcbeSJiaxin Yu };
58ae92dcbeSJiaxin Yu 
59ae92dcbeSJiaxin Yu static unsigned int get_tdm_lrck_width(snd_pcm_format_t format,
60ae92dcbeSJiaxin Yu 				       unsigned int mode)
61ae92dcbeSJiaxin Yu {
62ae92dcbeSJiaxin Yu 	if (mode == TDM_IN_DSP_A || mode == TDM_IN_DSP_B)
63ae92dcbeSJiaxin Yu 		return 0;
64ae92dcbeSJiaxin Yu 
65ae92dcbeSJiaxin Yu 	return snd_pcm_format_physical_width(format) - 1;
66ae92dcbeSJiaxin Yu }
67ae92dcbeSJiaxin Yu 
68ae92dcbeSJiaxin Yu static unsigned int get_tdm_ch_fixup(unsigned int channels)
69ae92dcbeSJiaxin Yu {
70ae92dcbeSJiaxin Yu 	if (channels > 4)
71ae92dcbeSJiaxin Yu 		return 8;
72ae92dcbeSJiaxin Yu 	else if (channels > 2)
73ae92dcbeSJiaxin Yu 		return 4;
74ae92dcbeSJiaxin Yu 
75ae92dcbeSJiaxin Yu 	return 2;
76ae92dcbeSJiaxin Yu }
77ae92dcbeSJiaxin Yu 
78ae92dcbeSJiaxin Yu static unsigned int get_tdm_ch_per_sdata(unsigned int mode,
79ae92dcbeSJiaxin Yu 					 unsigned int channels)
80ae92dcbeSJiaxin Yu {
81ae92dcbeSJiaxin Yu 	if (mode == TDM_IN_DSP_A || mode == TDM_IN_DSP_B)
82ae92dcbeSJiaxin Yu 		return get_tdm_ch_fixup(channels);
83ae92dcbeSJiaxin Yu 
84ae92dcbeSJiaxin Yu 	return 2;
85ae92dcbeSJiaxin Yu }
86ae92dcbeSJiaxin Yu 
87ae92dcbeSJiaxin Yu enum {
88ae92dcbeSJiaxin Yu 	SUPPLY_SEQ_APLL,
89ae92dcbeSJiaxin Yu 	SUPPLY_SEQ_TDM_MCK_EN,
90ae92dcbeSJiaxin Yu 	SUPPLY_SEQ_TDM_HD_EN,
91ae92dcbeSJiaxin Yu 	SUPPLY_SEQ_TDM_EN,
92ae92dcbeSJiaxin Yu };
93ae92dcbeSJiaxin Yu 
94ae92dcbeSJiaxin Yu static int get_tdm_id_by_name(const char *name)
95ae92dcbeSJiaxin Yu {
96ae92dcbeSJiaxin Yu 	return MT8186_DAI_TDM_IN;
97ae92dcbeSJiaxin Yu }
98ae92dcbeSJiaxin Yu 
99ae92dcbeSJiaxin Yu static int mtk_tdm_en_event(struct snd_soc_dapm_widget *w,
100ae92dcbeSJiaxin Yu 			    struct snd_kcontrol *kcontrol,
101ae92dcbeSJiaxin Yu 			    int event)
102ae92dcbeSJiaxin Yu {
103ae92dcbeSJiaxin Yu 	struct snd_soc_component *cmpnt = snd_soc_dapm_to_component(w->dapm);
104ae92dcbeSJiaxin Yu 	struct mtk_base_afe *afe = snd_soc_component_get_drvdata(cmpnt);
105ae92dcbeSJiaxin Yu 	struct mt8186_afe_private *afe_priv = afe->platform_priv;
106ae92dcbeSJiaxin Yu 	int dai_id = get_tdm_id_by_name(w->name);
107ae92dcbeSJiaxin Yu 	struct mtk_afe_tdm_priv *tdm_priv = afe_priv->dai_priv[dai_id];
108ae92dcbeSJiaxin Yu 
109ae92dcbeSJiaxin Yu 	if (!tdm_priv) {
110ae92dcbeSJiaxin Yu 		dev_err(afe->dev, "%s(), tdm_priv == NULL", __func__);
111ae92dcbeSJiaxin Yu 		return -EINVAL;
112ae92dcbeSJiaxin Yu 	}
113ae92dcbeSJiaxin Yu 
114ae92dcbeSJiaxin Yu 	dev_dbg(cmpnt->dev, "%s(), name %s, event 0x%x\n",
115ae92dcbeSJiaxin Yu 		__func__, w->name, event);
116ae92dcbeSJiaxin Yu 
117ae92dcbeSJiaxin Yu 	switch (event) {
118ae92dcbeSJiaxin Yu 	case SND_SOC_DAPM_PRE_PMU:
119ae92dcbeSJiaxin Yu 		mt8186_afe_gpio_request(afe->dev, true, tdm_priv->id, 0);
120ae92dcbeSJiaxin Yu 		break;
121ae92dcbeSJiaxin Yu 	case SND_SOC_DAPM_POST_PMD:
122ae92dcbeSJiaxin Yu 		mt8186_afe_gpio_request(afe->dev, false, tdm_priv->id, 0);
123ae92dcbeSJiaxin Yu 		break;
124ae92dcbeSJiaxin Yu 	default:
125ae92dcbeSJiaxin Yu 		break;
126ae92dcbeSJiaxin Yu 	}
127ae92dcbeSJiaxin Yu 
128ae92dcbeSJiaxin Yu 	return 0;
129ae92dcbeSJiaxin Yu }
130ae92dcbeSJiaxin Yu 
131ae92dcbeSJiaxin Yu static int mtk_tdm_mck_en_event(struct snd_soc_dapm_widget *w,
132ae92dcbeSJiaxin Yu 				struct snd_kcontrol *kcontrol,
133ae92dcbeSJiaxin Yu 				int event)
134ae92dcbeSJiaxin Yu {
135ae92dcbeSJiaxin Yu 	struct snd_soc_component *cmpnt = snd_soc_dapm_to_component(w->dapm);
136ae92dcbeSJiaxin Yu 	struct mtk_base_afe *afe = snd_soc_component_get_drvdata(cmpnt);
137ae92dcbeSJiaxin Yu 	struct mt8186_afe_private *afe_priv = afe->platform_priv;
138ae92dcbeSJiaxin Yu 	int dai_id = get_tdm_id_by_name(w->name);
139ae92dcbeSJiaxin Yu 	struct mtk_afe_tdm_priv *tdm_priv = afe_priv->dai_priv[dai_id];
140ae92dcbeSJiaxin Yu 
141ae92dcbeSJiaxin Yu 	if (!tdm_priv) {
142ae92dcbeSJiaxin Yu 		dev_err(afe->dev, "%s(), tdm_priv == NULL", __func__);
143ae92dcbeSJiaxin Yu 		return -EINVAL;
144ae92dcbeSJiaxin Yu 	}
145ae92dcbeSJiaxin Yu 
146ae92dcbeSJiaxin Yu 	dev_dbg(cmpnt->dev, "%s(), name %s, event 0x%x, dai_id %d\n",
147ae92dcbeSJiaxin Yu 		__func__, w->name, event, dai_id);
148ae92dcbeSJiaxin Yu 
149ae92dcbeSJiaxin Yu 	switch (event) {
150ae92dcbeSJiaxin Yu 	case SND_SOC_DAPM_PRE_PMU:
151ae92dcbeSJiaxin Yu 		mt8186_mck_enable(afe, tdm_priv->mclk_id, tdm_priv->mclk_rate);
152ae92dcbeSJiaxin Yu 		break;
153ae92dcbeSJiaxin Yu 	case SND_SOC_DAPM_POST_PMD:
154ae92dcbeSJiaxin Yu 		tdm_priv->mclk_rate = 0;
155ae92dcbeSJiaxin Yu 		mt8186_mck_disable(afe, tdm_priv->mclk_id);
156ae92dcbeSJiaxin Yu 		break;
157ae92dcbeSJiaxin Yu 	default:
158ae92dcbeSJiaxin Yu 		break;
159ae92dcbeSJiaxin Yu 	}
160ae92dcbeSJiaxin Yu 
161ae92dcbeSJiaxin Yu 	return 0;
162ae92dcbeSJiaxin Yu }
163ae92dcbeSJiaxin Yu 
164ae92dcbeSJiaxin Yu /* dai component */
165ae92dcbeSJiaxin Yu /* tdm virtual mux to output widget */
166ae92dcbeSJiaxin Yu static const char * const tdm_mux_map[] = {
167ae92dcbeSJiaxin Yu 	"Normal", "Dummy_Widget",
168ae92dcbeSJiaxin Yu };
169ae92dcbeSJiaxin Yu 
170ae92dcbeSJiaxin Yu static int tdm_mux_map_value[] = {
171ae92dcbeSJiaxin Yu 	0, 1,
172ae92dcbeSJiaxin Yu };
173ae92dcbeSJiaxin Yu 
174ae92dcbeSJiaxin Yu static SOC_VALUE_ENUM_SINGLE_AUTODISABLE_DECL(tdm_mux_map_enum,
175ae92dcbeSJiaxin Yu 					      SND_SOC_NOPM,
176ae92dcbeSJiaxin Yu 					      0,
177ae92dcbeSJiaxin Yu 					      1,
178ae92dcbeSJiaxin Yu 					      tdm_mux_map,
179ae92dcbeSJiaxin Yu 					      tdm_mux_map_value);
180ae92dcbeSJiaxin Yu 
181ae92dcbeSJiaxin Yu static const struct snd_kcontrol_new tdm_in_mux_control =
182ae92dcbeSJiaxin Yu 	SOC_DAPM_ENUM("TDM In Select", tdm_mux_map_enum);
183ae92dcbeSJiaxin Yu 
184ae92dcbeSJiaxin Yu static const struct snd_soc_dapm_widget mtk_dai_tdm_widgets[] = {
185ae92dcbeSJiaxin Yu 	SND_SOC_DAPM_CLOCK_SUPPLY("aud_tdm_clk"),
186ae92dcbeSJiaxin Yu 
187ae92dcbeSJiaxin Yu 	SND_SOC_DAPM_SUPPLY_S("TDM_EN", SUPPLY_SEQ_TDM_EN,
188ae92dcbeSJiaxin Yu 			      ETDM_IN1_CON0, ETDM_IN1_CON0_REG_ETDM_IN_EN_SFT,
189ae92dcbeSJiaxin Yu 			      0, mtk_tdm_en_event,
190ae92dcbeSJiaxin Yu 			      SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
191ae92dcbeSJiaxin Yu 	/* tdm hd en */
192ae92dcbeSJiaxin Yu 	SND_SOC_DAPM_SUPPLY_S(TDM_HD_EN_W_NAME, SUPPLY_SEQ_TDM_HD_EN,
193ae92dcbeSJiaxin Yu 			      ETDM_IN1_CON2, ETDM_IN1_CON2_REG_CLOCK_SOURCE_SEL_SFT,
194ae92dcbeSJiaxin Yu 			      0, NULL,
195ae92dcbeSJiaxin Yu 			      SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
196ae92dcbeSJiaxin Yu 
197ae92dcbeSJiaxin Yu 	SND_SOC_DAPM_SUPPLY_S(TDM_MCLK_EN_W_NAME, SUPPLY_SEQ_TDM_MCK_EN,
198ae92dcbeSJiaxin Yu 			      SND_SOC_NOPM, 0, 0,
199ae92dcbeSJiaxin Yu 			      mtk_tdm_mck_en_event,
200ae92dcbeSJiaxin Yu 			      SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
201ae92dcbeSJiaxin Yu 
202ae92dcbeSJiaxin Yu 	SND_SOC_DAPM_INPUT("TDM_DUMMY_IN"),
203ae92dcbeSJiaxin Yu 
204ae92dcbeSJiaxin Yu 	SND_SOC_DAPM_MUX("TDM_In_Mux",
205ae92dcbeSJiaxin Yu 			 SND_SOC_NOPM, 0, 0, &tdm_in_mux_control),
206ae92dcbeSJiaxin Yu };
207ae92dcbeSJiaxin Yu 
208ae92dcbeSJiaxin Yu static int mtk_afe_tdm_mclk_connect(struct snd_soc_dapm_widget *source,
209ae92dcbeSJiaxin Yu 				    struct snd_soc_dapm_widget *sink)
210ae92dcbeSJiaxin Yu {
211ae92dcbeSJiaxin Yu 	struct snd_soc_dapm_widget *w = sink;
212ae92dcbeSJiaxin Yu 	struct snd_soc_component *cmpnt = snd_soc_dapm_to_component(w->dapm);
213ae92dcbeSJiaxin Yu 	struct mtk_base_afe *afe = snd_soc_component_get_drvdata(cmpnt);
214ae92dcbeSJiaxin Yu 	struct mt8186_afe_private *afe_priv = afe->platform_priv;
215ae92dcbeSJiaxin Yu 	int dai_id = get_tdm_id_by_name(w->name);
216ae92dcbeSJiaxin Yu 	struct mtk_afe_tdm_priv *tdm_priv = afe_priv->dai_priv[dai_id];
217ae92dcbeSJiaxin Yu 
218ae92dcbeSJiaxin Yu 	if (!tdm_priv) {
219ae92dcbeSJiaxin Yu 		dev_err(afe->dev, "%s(), tdm_priv == NULL", __func__);
220ae92dcbeSJiaxin Yu 		return 0;
221ae92dcbeSJiaxin Yu 	}
222ae92dcbeSJiaxin Yu 
223ae92dcbeSJiaxin Yu 	return (tdm_priv->mclk_rate > 0) ? 1 : 0;
224ae92dcbeSJiaxin Yu }
225ae92dcbeSJiaxin Yu 
226ae92dcbeSJiaxin Yu static int mtk_afe_tdm_mclk_apll_connect(struct snd_soc_dapm_widget *source,
227ae92dcbeSJiaxin Yu 					 struct snd_soc_dapm_widget *sink)
228ae92dcbeSJiaxin Yu {
229ae92dcbeSJiaxin Yu 	struct snd_soc_dapm_widget *w = sink;
230ae92dcbeSJiaxin Yu 	struct snd_soc_component *cmpnt = snd_soc_dapm_to_component(w->dapm);
231ae92dcbeSJiaxin Yu 	struct mtk_base_afe *afe = snd_soc_component_get_drvdata(cmpnt);
232ae92dcbeSJiaxin Yu 	struct mt8186_afe_private *afe_priv = afe->platform_priv;
233ae92dcbeSJiaxin Yu 	int dai_id = get_tdm_id_by_name(w->name);
234ae92dcbeSJiaxin Yu 	struct mtk_afe_tdm_priv *tdm_priv = afe_priv->dai_priv[dai_id];
235ae92dcbeSJiaxin Yu 	int cur_apll;
236ae92dcbeSJiaxin Yu 
237ae92dcbeSJiaxin Yu 	/* which apll */
238ae92dcbeSJiaxin Yu 	cur_apll = mt8186_get_apll_by_name(afe, source->name);
239ae92dcbeSJiaxin Yu 
240ae92dcbeSJiaxin Yu 	return (tdm_priv->mclk_apll == cur_apll) ? 1 : 0;
241ae92dcbeSJiaxin Yu }
242ae92dcbeSJiaxin Yu 
243ae92dcbeSJiaxin Yu static int mtk_afe_tdm_hd_connect(struct snd_soc_dapm_widget *source,
244ae92dcbeSJiaxin Yu 				  struct snd_soc_dapm_widget *sink)
245ae92dcbeSJiaxin Yu {
246ae92dcbeSJiaxin Yu 	struct snd_soc_dapm_widget *w = sink;
247ae92dcbeSJiaxin Yu 	struct snd_soc_component *cmpnt = snd_soc_dapm_to_component(w->dapm);
248ae92dcbeSJiaxin Yu 	struct mtk_base_afe *afe = snd_soc_component_get_drvdata(cmpnt);
249ae92dcbeSJiaxin Yu 	struct mt8186_afe_private *afe_priv = afe->platform_priv;
250ae92dcbeSJiaxin Yu 	int dai_id = get_tdm_id_by_name(w->name);
251ae92dcbeSJiaxin Yu 	struct mtk_afe_tdm_priv *tdm_priv = afe_priv->dai_priv[dai_id];
252ae92dcbeSJiaxin Yu 
253ae92dcbeSJiaxin Yu 	if (!tdm_priv) {
254ae92dcbeSJiaxin Yu 		dev_err(afe->dev, "%s(), tdm_priv == NULL", __func__);
255ae92dcbeSJiaxin Yu 		return 0;
256ae92dcbeSJiaxin Yu 	}
257ae92dcbeSJiaxin Yu 
258ae92dcbeSJiaxin Yu 	return tdm_priv->low_jitter_en;
259ae92dcbeSJiaxin Yu }
260ae92dcbeSJiaxin Yu 
261ae92dcbeSJiaxin Yu static int mtk_afe_tdm_apll_connect(struct snd_soc_dapm_widget *source,
262ae92dcbeSJiaxin Yu 				    struct snd_soc_dapm_widget *sink)
263ae92dcbeSJiaxin Yu {
264ae92dcbeSJiaxin Yu 	struct snd_soc_dapm_widget *w = sink;
265ae92dcbeSJiaxin Yu 	struct snd_soc_component *cmpnt = snd_soc_dapm_to_component(w->dapm);
266ae92dcbeSJiaxin Yu 	struct mtk_base_afe *afe = snd_soc_component_get_drvdata(cmpnt);
267ae92dcbeSJiaxin Yu 	struct mt8186_afe_private *afe_priv = afe->platform_priv;
268ae92dcbeSJiaxin Yu 	int dai_id = get_tdm_id_by_name(w->name);
269ae92dcbeSJiaxin Yu 	struct mtk_afe_tdm_priv *tdm_priv = afe_priv->dai_priv[dai_id];
270ae92dcbeSJiaxin Yu 	int cur_apll;
271ae92dcbeSJiaxin Yu 	int tdm_need_apll;
272ae92dcbeSJiaxin Yu 
273ae92dcbeSJiaxin Yu 	if (!tdm_priv) {
274ae92dcbeSJiaxin Yu 		dev_err(afe->dev, "%s(), tdm_priv == NULL", __func__);
275ae92dcbeSJiaxin Yu 		return 0;
276ae92dcbeSJiaxin Yu 	}
277ae92dcbeSJiaxin Yu 
278ae92dcbeSJiaxin Yu 	/* which apll */
279ae92dcbeSJiaxin Yu 	cur_apll = mt8186_get_apll_by_name(afe, source->name);
280ae92dcbeSJiaxin Yu 
281ae92dcbeSJiaxin Yu 	/* choose APLL from tdm rate */
282ae92dcbeSJiaxin Yu 	tdm_need_apll = mt8186_get_apll_by_rate(afe, tdm_priv->rate);
283ae92dcbeSJiaxin Yu 
284ae92dcbeSJiaxin Yu 	return (tdm_need_apll == cur_apll) ? 1 : 0;
285ae92dcbeSJiaxin Yu }
286ae92dcbeSJiaxin Yu 
287ae92dcbeSJiaxin Yu /* low jitter control */
288ae92dcbeSJiaxin Yu static const char * const mt8186_tdm_hd_str[] = {
289ae92dcbeSJiaxin Yu 	"Normal", "Low_Jitter"
290ae92dcbeSJiaxin Yu };
291ae92dcbeSJiaxin Yu 
292ae92dcbeSJiaxin Yu static const struct soc_enum mt8186_tdm_enum[] = {
293ae92dcbeSJiaxin Yu 	SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(mt8186_tdm_hd_str),
294ae92dcbeSJiaxin Yu 			    mt8186_tdm_hd_str),
295ae92dcbeSJiaxin Yu };
296ae92dcbeSJiaxin Yu 
297ae92dcbeSJiaxin Yu static int mt8186_tdm_hd_get(struct snd_kcontrol *kcontrol,
298ae92dcbeSJiaxin Yu 			     struct snd_ctl_elem_value *ucontrol)
299ae92dcbeSJiaxin Yu {
300ae92dcbeSJiaxin Yu 	struct snd_soc_component *cmpnt = snd_soc_kcontrol_component(kcontrol);
301ae92dcbeSJiaxin Yu 	struct mtk_base_afe *afe = snd_soc_component_get_drvdata(cmpnt);
302ae92dcbeSJiaxin Yu 	struct mt8186_afe_private *afe_priv = afe->platform_priv;
303ae92dcbeSJiaxin Yu 	int dai_id = get_tdm_id_by_name(kcontrol->id.name);
304ae92dcbeSJiaxin Yu 	struct mtk_afe_tdm_priv *tdm_priv = afe_priv->dai_priv[dai_id];
305ae92dcbeSJiaxin Yu 
306ae92dcbeSJiaxin Yu 	if (!tdm_priv) {
307ae92dcbeSJiaxin Yu 		dev_err(afe->dev, "%s(), tdm_priv == NULL", __func__);
308ae92dcbeSJiaxin Yu 		return -EINVAL;
309ae92dcbeSJiaxin Yu 	}
310ae92dcbeSJiaxin Yu 
311ae92dcbeSJiaxin Yu 	ucontrol->value.integer.value[0] = tdm_priv->low_jitter_en;
312ae92dcbeSJiaxin Yu 
313ae92dcbeSJiaxin Yu 	return 0;
314ae92dcbeSJiaxin Yu }
315ae92dcbeSJiaxin Yu 
316ae92dcbeSJiaxin Yu static int mt8186_tdm_hd_set(struct snd_kcontrol *kcontrol,
317ae92dcbeSJiaxin Yu 			     struct snd_ctl_elem_value *ucontrol)
318ae92dcbeSJiaxin Yu {
319ae92dcbeSJiaxin Yu 	struct snd_soc_component *cmpnt = snd_soc_kcontrol_component(kcontrol);
320ae92dcbeSJiaxin Yu 	struct mtk_base_afe *afe = snd_soc_component_get_drvdata(cmpnt);
321ae92dcbeSJiaxin Yu 	struct mt8186_afe_private *afe_priv = afe->platform_priv;
322ae92dcbeSJiaxin Yu 	int dai_id = get_tdm_id_by_name(kcontrol->id.name);
323ae92dcbeSJiaxin Yu 	struct mtk_afe_tdm_priv *tdm_priv = afe_priv->dai_priv[dai_id];
324ae92dcbeSJiaxin Yu 	struct soc_enum *e = (struct soc_enum *)kcontrol->private_value;
325ae92dcbeSJiaxin Yu 	int hd_en;
326ae92dcbeSJiaxin Yu 
327ae92dcbeSJiaxin Yu 	if (ucontrol->value.enumerated.item[0] >= e->items)
328ae92dcbeSJiaxin Yu 		return -EINVAL;
329ae92dcbeSJiaxin Yu 
330ae92dcbeSJiaxin Yu 	hd_en = ucontrol->value.integer.value[0];
331ae92dcbeSJiaxin Yu 
332ae92dcbeSJiaxin Yu 	dev_dbg(afe->dev, "%s(), kcontrol name %s, hd_en %d\n",
333ae92dcbeSJiaxin Yu 		__func__, kcontrol->id.name, hd_en);
334ae92dcbeSJiaxin Yu 
335ae92dcbeSJiaxin Yu 	if (!tdm_priv) {
336ae92dcbeSJiaxin Yu 		dev_err(afe->dev, "%s(), tdm_priv == NULL", __func__);
337ae92dcbeSJiaxin Yu 		return -EINVAL;
338ae92dcbeSJiaxin Yu 	}
339ae92dcbeSJiaxin Yu 
340ae92dcbeSJiaxin Yu 	if (tdm_priv->low_jitter_en == hd_en)
341ae92dcbeSJiaxin Yu 		return 0;
342ae92dcbeSJiaxin Yu 
343ae92dcbeSJiaxin Yu 	tdm_priv->low_jitter_en = hd_en;
344ae92dcbeSJiaxin Yu 
345ae92dcbeSJiaxin Yu 	return 1;
346ae92dcbeSJiaxin Yu }
347ae92dcbeSJiaxin Yu 
348ae92dcbeSJiaxin Yu static const struct snd_kcontrol_new mtk_dai_tdm_controls[] = {
349ae92dcbeSJiaxin Yu 	SOC_ENUM_EXT(MTK_AFE_TDM_KCONTROL_NAME, mt8186_tdm_enum[0],
350ae92dcbeSJiaxin Yu 		     mt8186_tdm_hd_get, mt8186_tdm_hd_set),
351ae92dcbeSJiaxin Yu };
352ae92dcbeSJiaxin Yu 
353ae92dcbeSJiaxin Yu static const struct snd_soc_dapm_route mtk_dai_tdm_routes[] = {
354ae92dcbeSJiaxin Yu 	{"TDM IN", NULL, "aud_tdm_clk"},
355ae92dcbeSJiaxin Yu 	{"TDM IN", NULL, "TDM_EN"},
356ae92dcbeSJiaxin Yu 	{"TDM IN", NULL, TDM_HD_EN_W_NAME, mtk_afe_tdm_hd_connect},
357ae92dcbeSJiaxin Yu 	{TDM_HD_EN_W_NAME, NULL, APLL1_W_NAME, mtk_afe_tdm_apll_connect},
358ae92dcbeSJiaxin Yu 	{TDM_HD_EN_W_NAME, NULL, APLL2_W_NAME, mtk_afe_tdm_apll_connect},
359ae92dcbeSJiaxin Yu 
360ae92dcbeSJiaxin Yu 	{"TDM IN", NULL, TDM_MCLK_EN_W_NAME, mtk_afe_tdm_mclk_connect},
361ae92dcbeSJiaxin Yu 	{TDM_MCLK_EN_W_NAME, NULL, APLL1_W_NAME, mtk_afe_tdm_mclk_apll_connect},
362ae92dcbeSJiaxin Yu 	{TDM_MCLK_EN_W_NAME, NULL, APLL2_W_NAME, mtk_afe_tdm_mclk_apll_connect},
363ae92dcbeSJiaxin Yu 
364ae92dcbeSJiaxin Yu 	/* allow tdm on without codec on */
365ae92dcbeSJiaxin Yu 	{"TDM IN", NULL, "TDM_In_Mux"},
366ae92dcbeSJiaxin Yu 	{"TDM_In_Mux", "Dummy_Widget", "TDM_DUMMY_IN"},
367ae92dcbeSJiaxin Yu };
368ae92dcbeSJiaxin Yu 
369ae92dcbeSJiaxin Yu /* dai ops */
370ae92dcbeSJiaxin Yu static int mtk_dai_tdm_cal_mclk(struct mtk_base_afe *afe,
371ae92dcbeSJiaxin Yu 				struct mtk_afe_tdm_priv *tdm_priv,
372ae92dcbeSJiaxin Yu 				int freq)
373ae92dcbeSJiaxin Yu {
374ae92dcbeSJiaxin Yu 	int apll;
375ae92dcbeSJiaxin Yu 	int apll_rate;
376ae92dcbeSJiaxin Yu 
377ae92dcbeSJiaxin Yu 	apll = mt8186_get_apll_by_rate(afe, freq);
378ae92dcbeSJiaxin Yu 	apll_rate = mt8186_get_apll_rate(afe, apll);
379ae92dcbeSJiaxin Yu 
380ae92dcbeSJiaxin Yu 	if (!freq || freq > apll_rate) {
381ae92dcbeSJiaxin Yu 		dev_err(afe->dev,
382ae92dcbeSJiaxin Yu 			"%s(), freq(%d Hz) invalid\n", __func__, freq);
383ae92dcbeSJiaxin Yu 		return -EINVAL;
384ae92dcbeSJiaxin Yu 	}
385ae92dcbeSJiaxin Yu 
386ae92dcbeSJiaxin Yu 	if (apll_rate % freq != 0) {
387ae92dcbeSJiaxin Yu 		dev_err(afe->dev,
388ae92dcbeSJiaxin Yu 			"%s(), APLL cannot generate %d Hz", __func__, freq);
389ae92dcbeSJiaxin Yu 		return -EINVAL;
390ae92dcbeSJiaxin Yu 	}
391ae92dcbeSJiaxin Yu 
392ae92dcbeSJiaxin Yu 	tdm_priv->mclk_rate = freq;
393ae92dcbeSJiaxin Yu 	tdm_priv->mclk_apll = apll;
394ae92dcbeSJiaxin Yu 
395ae92dcbeSJiaxin Yu 	return 0;
396ae92dcbeSJiaxin Yu }
397ae92dcbeSJiaxin Yu 
398ae92dcbeSJiaxin Yu static int mtk_dai_tdm_hw_params(struct snd_pcm_substream *substream,
399ae92dcbeSJiaxin Yu 				 struct snd_pcm_hw_params *params,
400ae92dcbeSJiaxin Yu 				 struct snd_soc_dai *dai)
401ae92dcbeSJiaxin Yu {
402ae92dcbeSJiaxin Yu 	struct mtk_base_afe *afe = snd_soc_dai_get_drvdata(dai);
403ae92dcbeSJiaxin Yu 	struct mt8186_afe_private *afe_priv = afe->platform_priv;
404ae92dcbeSJiaxin Yu 	int tdm_id = dai->id;
405ae92dcbeSJiaxin Yu 	struct mtk_afe_tdm_priv *tdm_priv = afe_priv->dai_priv[tdm_id];
406ae92dcbeSJiaxin Yu 	unsigned int tdm_mode = tdm_priv->tdm_mode;
407ae92dcbeSJiaxin Yu 	unsigned int data_mode = tdm_priv->data_mode;
408ae92dcbeSJiaxin Yu 	unsigned int rate = params_rate(params);
409ae92dcbeSJiaxin Yu 	unsigned int channels = params_channels(params);
410ae92dcbeSJiaxin Yu 	snd_pcm_format_t format = params_format(params);
411ae92dcbeSJiaxin Yu 	unsigned int bit_width =
412ae92dcbeSJiaxin Yu 		snd_pcm_format_physical_width(format);
413ae92dcbeSJiaxin Yu 	unsigned int tdm_channels = (data_mode == TDM_DATA_ONE_PIN) ?
414ae92dcbeSJiaxin Yu 		get_tdm_ch_per_sdata(tdm_mode, channels) : 2;
415ae92dcbeSJiaxin Yu 	unsigned int lrck_width =
416ae92dcbeSJiaxin Yu 		get_tdm_lrck_width(format, tdm_mode);
417ae92dcbeSJiaxin Yu 	unsigned int tdm_con = 0;
418ae92dcbeSJiaxin Yu 	bool slave_mode = tdm_priv->slave_mode;
419ae92dcbeSJiaxin Yu 	bool lrck_inv = tdm_priv->lck_invert;
420ae92dcbeSJiaxin Yu 	bool bck_inv = tdm_priv->bck_invert;
421ae92dcbeSJiaxin Yu 	unsigned int tran_rate;
422ae92dcbeSJiaxin Yu 	unsigned int tran_relatch_rate;
423ae92dcbeSJiaxin Yu 
424ae92dcbeSJiaxin Yu 	if (!tdm_priv) {
425ae92dcbeSJiaxin Yu 		dev_err(afe->dev, "%s(), tdm_priv == NULL", __func__);
426ae92dcbeSJiaxin Yu 		return -EINVAL;
427ae92dcbeSJiaxin Yu 	}
428ae92dcbeSJiaxin Yu 
429ae92dcbeSJiaxin Yu 	tdm_priv->rate = rate;
430ae92dcbeSJiaxin Yu 
431ae92dcbeSJiaxin Yu 	tran_rate = mt8186_rate_transform(afe->dev, rate, dai->id);
432ae92dcbeSJiaxin Yu 	tran_relatch_rate = mt8186_tdm_relatch_rate_transform(afe->dev, rate);
433ae92dcbeSJiaxin Yu 
434ae92dcbeSJiaxin Yu 	/* calculate mclk_rate, if not set explicitly */
435ae92dcbeSJiaxin Yu 	if (!tdm_priv->mclk_rate) {
436ae92dcbeSJiaxin Yu 		tdm_priv->mclk_rate = rate * tdm_priv->mclk_multiple;
437ae92dcbeSJiaxin Yu 		mtk_dai_tdm_cal_mclk(afe,
438ae92dcbeSJiaxin Yu 				     tdm_priv,
439ae92dcbeSJiaxin Yu 				     tdm_priv->mclk_rate);
440ae92dcbeSJiaxin Yu 	}
441ae92dcbeSJiaxin Yu 
442ae92dcbeSJiaxin Yu 	/* ETDM_IN1_CON0 */
443ae92dcbeSJiaxin Yu 	tdm_con |= slave_mode << ETDM_IN1_CON0_REG_SLAVE_MODE_SFT;
444ae92dcbeSJiaxin Yu 	tdm_con |= tdm_mode << ETDM_IN1_CON0_REG_FMT_SFT;
445ae92dcbeSJiaxin Yu 	tdm_con |= (bit_width - 1) << ETDM_IN1_CON0_REG_BIT_LENGTH_SFT;
446ae92dcbeSJiaxin Yu 	tdm_con |= (bit_width - 1) << ETDM_IN1_CON0_REG_WORD_LENGTH_SFT;
447ae92dcbeSJiaxin Yu 	tdm_con |= (tdm_channels - 1) << ETDM_IN1_CON0_REG_CH_NUM_SFT;
448ae92dcbeSJiaxin Yu 	/* need to disable sync mode otherwise this may cause latch data error */
449ae92dcbeSJiaxin Yu 	tdm_con |= 0 << ETDM_IN1_CON0_REG_SYNC_MODE_SFT;
450ae92dcbeSJiaxin Yu 	/* relatch 1x en clock fix to h26m */
451ae92dcbeSJiaxin Yu 	tdm_con |= 0 << ETDM_IN1_CON0_REG_RELATCH_1X_EN_SEL_DOMAIN_SFT;
452ae92dcbeSJiaxin Yu 	regmap_update_bits(afe->regmap, ETDM_IN1_CON0, ETDM_IN_CON0_CTRL_MASK, tdm_con);
453ae92dcbeSJiaxin Yu 
454ae92dcbeSJiaxin Yu 	/* ETDM_IN1_CON1 */
455ae92dcbeSJiaxin Yu 	tdm_con = 0;
456ae92dcbeSJiaxin Yu 	tdm_con |= 0 << ETDM_IN1_CON1_REG_LRCK_AUTO_MODE_SFT;
457ae92dcbeSJiaxin Yu 	tdm_con |= 1 << ETDM_IN1_CON1_PINMUX_MCLK_CTRL_OE_SFT;
458ae92dcbeSJiaxin Yu 	tdm_con |= (lrck_width - 1) << ETDM_IN1_CON1_REG_LRCK_WIDTH_SFT;
459ae92dcbeSJiaxin Yu 	regmap_update_bits(afe->regmap, ETDM_IN1_CON1, ETDM_IN_CON1_CTRL_MASK, tdm_con);
460ae92dcbeSJiaxin Yu 
461ae92dcbeSJiaxin Yu 	/* ETDM_IN1_CON3 */
462ae92dcbeSJiaxin Yu 	tdm_con = 0;
463ae92dcbeSJiaxin Yu 	tdm_con = ETDM_IN_CON3_FS(tran_rate);
464ae92dcbeSJiaxin Yu 	regmap_update_bits(afe->regmap, ETDM_IN1_CON3, ETDM_IN_CON3_CTRL_MASK, tdm_con);
465ae92dcbeSJiaxin Yu 
466ae92dcbeSJiaxin Yu 	/* ETDM_IN1_CON4 */
467ae92dcbeSJiaxin Yu 	tdm_con = 0;
468ae92dcbeSJiaxin Yu 	tdm_con = ETDM_IN_CON4_FS(tran_relatch_rate);
469ae92dcbeSJiaxin Yu 	if (slave_mode) {
470ae92dcbeSJiaxin Yu 		if (lrck_inv)
471ae92dcbeSJiaxin Yu 			tdm_con |= ETDM_IN_CON4_CON0_SLAVE_LRCK_INV;
472ae92dcbeSJiaxin Yu 		if (bck_inv)
473ae92dcbeSJiaxin Yu 			tdm_con |= ETDM_IN_CON4_CON0_SLAVE_BCK_INV;
474ae92dcbeSJiaxin Yu 	} else {
475ae92dcbeSJiaxin Yu 		if (lrck_inv)
476ae92dcbeSJiaxin Yu 			tdm_con |= ETDM_IN_CON4_CON0_MASTER_LRCK_INV;
477ae92dcbeSJiaxin Yu 		if (bck_inv)
478ae92dcbeSJiaxin Yu 			tdm_con |= ETDM_IN_CON4_CON0_MASTER_BCK_INV;
479ae92dcbeSJiaxin Yu 	}
480ae92dcbeSJiaxin Yu 	regmap_update_bits(afe->regmap, ETDM_IN1_CON4, ETDM_IN_CON4_CTRL_MASK, tdm_con);
481ae92dcbeSJiaxin Yu 
482ae92dcbeSJiaxin Yu 	/* ETDM_IN1_CON2 */
483ae92dcbeSJiaxin Yu 	tdm_con = 0;
484ae92dcbeSJiaxin Yu 	if (data_mode == TDM_DATA_MULTI_PIN) {
485ae92dcbeSJiaxin Yu 		tdm_con |= ETDM_IN_CON2_MULTI_IP_2CH_MODE;
486ae92dcbeSJiaxin Yu 		tdm_con |= ETDM_IN_CON2_MULTI_IP_CH(channels);
487ae92dcbeSJiaxin Yu 	}
488ae92dcbeSJiaxin Yu 	regmap_update_bits(afe->regmap, ETDM_IN1_CON2, ETDM_IN_CON2_CTRL_MASK, tdm_con);
489ae92dcbeSJiaxin Yu 
490ae92dcbeSJiaxin Yu 	/* ETDM_IN1_CON8 */
491ae92dcbeSJiaxin Yu 	tdm_con = 0;
492ae92dcbeSJiaxin Yu 	if (slave_mode) {
493ae92dcbeSJiaxin Yu 		tdm_con |= 1 << ETDM_IN1_CON8_REG_ETDM_USE_AFIFO_SFT;
494ae92dcbeSJiaxin Yu 		tdm_con |= 0 << ETDM_IN1_CON8_REG_AFIFO_CLOCK_DOMAIN_SEL_SFT;
495ae92dcbeSJiaxin Yu 		tdm_con |= ETDM_IN_CON8_FS(tran_relatch_rate);
496ae92dcbeSJiaxin Yu 	} else {
497ae92dcbeSJiaxin Yu 		tdm_con |= 0 << ETDM_IN1_CON8_REG_ETDM_USE_AFIFO_SFT;
498ae92dcbeSJiaxin Yu 	}
499ae92dcbeSJiaxin Yu 	regmap_update_bits(afe->regmap, ETDM_IN1_CON8, ETDM_IN_CON8_CTRL_MASK, tdm_con);
500ae92dcbeSJiaxin Yu 
501ae92dcbeSJiaxin Yu 	return 0;
502ae92dcbeSJiaxin Yu }
503ae92dcbeSJiaxin Yu 
504ae92dcbeSJiaxin Yu static int mtk_dai_tdm_set_sysclk(struct snd_soc_dai *dai,
505ae92dcbeSJiaxin Yu 				  int clk_id, unsigned int freq, int dir)
506ae92dcbeSJiaxin Yu {
507ae92dcbeSJiaxin Yu 	struct mtk_base_afe *afe = dev_get_drvdata(dai->dev);
508ae92dcbeSJiaxin Yu 	struct mt8186_afe_private *afe_priv = afe->platform_priv;
509ae92dcbeSJiaxin Yu 	struct mtk_afe_tdm_priv *tdm_priv = afe_priv->dai_priv[dai->id];
510ae92dcbeSJiaxin Yu 
511ae92dcbeSJiaxin Yu 	if (!tdm_priv) {
512ae92dcbeSJiaxin Yu 		dev_err(afe->dev, "%s(), tdm_priv == NULL", __func__);
513ae92dcbeSJiaxin Yu 		return -EINVAL;
514ae92dcbeSJiaxin Yu 	}
515ae92dcbeSJiaxin Yu 
516ae92dcbeSJiaxin Yu 	if (dir != SND_SOC_CLOCK_IN) {
517ae92dcbeSJiaxin Yu 		dev_err(afe->dev, "%s(), dir != SND_SOC_CLOCK_OUT", __func__);
518ae92dcbeSJiaxin Yu 		return -EINVAL;
519ae92dcbeSJiaxin Yu 	}
520ae92dcbeSJiaxin Yu 
521ae92dcbeSJiaxin Yu 	dev_dbg(afe->dev, "%s(), freq %d\n", __func__, freq);
522ae92dcbeSJiaxin Yu 
523ae92dcbeSJiaxin Yu 	return mtk_dai_tdm_cal_mclk(afe, tdm_priv, freq);
524ae92dcbeSJiaxin Yu }
525ae92dcbeSJiaxin Yu 
526ae92dcbeSJiaxin Yu static int mtk_dai_tdm_set_fmt(struct snd_soc_dai *dai, unsigned int fmt)
527ae92dcbeSJiaxin Yu {
528ae92dcbeSJiaxin Yu 	struct mtk_base_afe *afe = dev_get_drvdata(dai->dev);
529ae92dcbeSJiaxin Yu 	struct mt8186_afe_private *afe_priv = afe->platform_priv;
530ae92dcbeSJiaxin Yu 	struct mtk_afe_tdm_priv *tdm_priv = afe_priv->dai_priv[dai->id];
531ae92dcbeSJiaxin Yu 
532ae92dcbeSJiaxin Yu 	if (!tdm_priv) {
533ae92dcbeSJiaxin Yu 		dev_err(afe->dev, "%s(), tdm_priv == NULL", __func__);
534ae92dcbeSJiaxin Yu 		return -EINVAL;
535ae92dcbeSJiaxin Yu 	}
536ae92dcbeSJiaxin Yu 
537ae92dcbeSJiaxin Yu 	/* DAI mode*/
538ae92dcbeSJiaxin Yu 	switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
539ae92dcbeSJiaxin Yu 	case SND_SOC_DAIFMT_I2S:
540ae92dcbeSJiaxin Yu 		tdm_priv->tdm_mode = TDM_IN_I2S;
541ae92dcbeSJiaxin Yu 		tdm_priv->data_mode = TDM_DATA_MULTI_PIN;
542ae92dcbeSJiaxin Yu 		break;
543ae92dcbeSJiaxin Yu 	case SND_SOC_DAIFMT_LEFT_J:
544ae92dcbeSJiaxin Yu 		tdm_priv->tdm_mode = TDM_IN_LJ;
545ae92dcbeSJiaxin Yu 		tdm_priv->data_mode = TDM_DATA_MULTI_PIN;
546ae92dcbeSJiaxin Yu 		break;
547ae92dcbeSJiaxin Yu 	case SND_SOC_DAIFMT_RIGHT_J:
548ae92dcbeSJiaxin Yu 		tdm_priv->tdm_mode = TDM_IN_RJ;
549ae92dcbeSJiaxin Yu 		tdm_priv->data_mode = TDM_DATA_MULTI_PIN;
550ae92dcbeSJiaxin Yu 		break;
551ae92dcbeSJiaxin Yu 	case SND_SOC_DAIFMT_DSP_A:
552ae92dcbeSJiaxin Yu 		tdm_priv->tdm_mode = TDM_IN_DSP_A;
553ae92dcbeSJiaxin Yu 		tdm_priv->data_mode = TDM_DATA_ONE_PIN;
554ae92dcbeSJiaxin Yu 		break;
555ae92dcbeSJiaxin Yu 	case SND_SOC_DAIFMT_DSP_B:
556ae92dcbeSJiaxin Yu 		tdm_priv->tdm_mode = TDM_IN_DSP_B;
557ae92dcbeSJiaxin Yu 		tdm_priv->data_mode = TDM_DATA_ONE_PIN;
558ae92dcbeSJiaxin Yu 		break;
559ae92dcbeSJiaxin Yu 	default:
560ae92dcbeSJiaxin Yu 		dev_err(afe->dev, "%s(), invalid DAIFMT_FORMAT_MASK", __func__);
561ae92dcbeSJiaxin Yu 		return -EINVAL;
562ae92dcbeSJiaxin Yu 	}
563ae92dcbeSJiaxin Yu 
564ae92dcbeSJiaxin Yu 	/* DAI clock inversion*/
565ae92dcbeSJiaxin Yu 	switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
566ae92dcbeSJiaxin Yu 	case SND_SOC_DAIFMT_NB_NF:
567ae92dcbeSJiaxin Yu 		tdm_priv->bck_invert = TDM_BCK_NON_INV;
568ae92dcbeSJiaxin Yu 		tdm_priv->lck_invert = TDM_LCK_NON_INV;
569ae92dcbeSJiaxin Yu 		break;
570ae92dcbeSJiaxin Yu 	case SND_SOC_DAIFMT_NB_IF:
571ae92dcbeSJiaxin Yu 		tdm_priv->bck_invert = TDM_BCK_NON_INV;
572ae92dcbeSJiaxin Yu 		tdm_priv->lck_invert = TDM_LCK_INV;
573ae92dcbeSJiaxin Yu 		break;
574ae92dcbeSJiaxin Yu 	case SND_SOC_DAIFMT_IB_NF:
575ae92dcbeSJiaxin Yu 		tdm_priv->bck_invert = TDM_BCK_INV;
576ae92dcbeSJiaxin Yu 		tdm_priv->lck_invert = TDM_LCK_NON_INV;
577ae92dcbeSJiaxin Yu 		break;
578ae92dcbeSJiaxin Yu 	case SND_SOC_DAIFMT_IB_IF:
579ae92dcbeSJiaxin Yu 		tdm_priv->bck_invert = TDM_BCK_INV;
580ae92dcbeSJiaxin Yu 		tdm_priv->lck_invert = TDM_LCK_INV;
581ae92dcbeSJiaxin Yu 		break;
582ae92dcbeSJiaxin Yu 	default:
583ae92dcbeSJiaxin Yu 		dev_err(afe->dev, "%s(), invalid DAIFMT_INV_MASK", __func__);
584ae92dcbeSJiaxin Yu 		return -EINVAL;
585ae92dcbeSJiaxin Yu 	}
586ae92dcbeSJiaxin Yu 
587ae92dcbeSJiaxin Yu 	switch (fmt & SND_SOC_DAIFMT_CLOCK_PROVIDER_MASK) {
588*845a2155SCharles Keepax 	case SND_SOC_DAIFMT_BP_FP:
589ae92dcbeSJiaxin Yu 		tdm_priv->slave_mode = false;
590ae92dcbeSJiaxin Yu 		break;
591*845a2155SCharles Keepax 	case SND_SOC_DAIFMT_BC_FC:
592ae92dcbeSJiaxin Yu 		tdm_priv->slave_mode = true;
593ae92dcbeSJiaxin Yu 		break;
594ae92dcbeSJiaxin Yu 	default:
595ae92dcbeSJiaxin Yu 		dev_err(afe->dev, "%s(), invalid DAIFMT_CLOCK_PROVIDER_MASK",
596ae92dcbeSJiaxin Yu 			__func__);
597ae92dcbeSJiaxin Yu 		return -EINVAL;
598ae92dcbeSJiaxin Yu 	}
599ae92dcbeSJiaxin Yu 
600ae92dcbeSJiaxin Yu 	return 0;
601ae92dcbeSJiaxin Yu }
602ae92dcbeSJiaxin Yu 
603ae92dcbeSJiaxin Yu static int mtk_dai_tdm_set_tdm_slot(struct snd_soc_dai *dai,
604ae92dcbeSJiaxin Yu 				    unsigned int tx_mask,
605ae92dcbeSJiaxin Yu 				    unsigned int rx_mask,
606ae92dcbeSJiaxin Yu 				    int slots,
607ae92dcbeSJiaxin Yu 				    int slot_width)
608ae92dcbeSJiaxin Yu {
609ae92dcbeSJiaxin Yu 	struct mtk_base_afe *afe = dev_get_drvdata(dai->dev);
610ae92dcbeSJiaxin Yu 	struct mt8186_afe_private *afe_priv = afe->platform_priv;
611ae92dcbeSJiaxin Yu 	struct mtk_afe_tdm_priv *tdm_priv = afe_priv->dai_priv[dai->id];
612ae92dcbeSJiaxin Yu 
613ae92dcbeSJiaxin Yu 	dev_dbg(dai->dev, "%s %d slot_width %d\n", __func__, dai->id, slot_width);
614ae92dcbeSJiaxin Yu 
615ae92dcbeSJiaxin Yu 	tdm_priv->lrck_width = slot_width;
616ae92dcbeSJiaxin Yu 
617ae92dcbeSJiaxin Yu 	return 0;
618ae92dcbeSJiaxin Yu }
619ae92dcbeSJiaxin Yu 
620ae92dcbeSJiaxin Yu static const struct snd_soc_dai_ops mtk_dai_tdm_ops = {
621ae92dcbeSJiaxin Yu 	.hw_params = mtk_dai_tdm_hw_params,
622ae92dcbeSJiaxin Yu 	.set_sysclk = mtk_dai_tdm_set_sysclk,
623ae92dcbeSJiaxin Yu 	.set_fmt = mtk_dai_tdm_set_fmt,
624ae92dcbeSJiaxin Yu 	.set_tdm_slot = mtk_dai_tdm_set_tdm_slot,
625ae92dcbeSJiaxin Yu };
626ae92dcbeSJiaxin Yu 
627ae92dcbeSJiaxin Yu /* dai driver */
628ae92dcbeSJiaxin Yu #define MTK_TDM_RATES (SNDRV_PCM_RATE_8000_48000 |\
629ae92dcbeSJiaxin Yu 		       SNDRV_PCM_RATE_88200 |\
630ae92dcbeSJiaxin Yu 		       SNDRV_PCM_RATE_96000 |\
631ae92dcbeSJiaxin Yu 		       SNDRV_PCM_RATE_176400 |\
632ae92dcbeSJiaxin Yu 		       SNDRV_PCM_RATE_192000)
633ae92dcbeSJiaxin Yu 
634ae92dcbeSJiaxin Yu #define MTK_TDM_FORMATS (SNDRV_PCM_FMTBIT_S16_LE |\
635ae92dcbeSJiaxin Yu 			 SNDRV_PCM_FMTBIT_S24_LE |\
636ae92dcbeSJiaxin Yu 			 SNDRV_PCM_FMTBIT_S32_LE)
637ae92dcbeSJiaxin Yu 
638ae92dcbeSJiaxin Yu static struct snd_soc_dai_driver mtk_dai_tdm_driver[] = {
639ae92dcbeSJiaxin Yu 	{
640ae92dcbeSJiaxin Yu 		.name = "TDM IN",
641ae92dcbeSJiaxin Yu 		.id = MT8186_DAI_TDM_IN,
642ae92dcbeSJiaxin Yu 		.capture = {
643ae92dcbeSJiaxin Yu 			.stream_name = "TDM IN",
644ae92dcbeSJiaxin Yu 			.channels_min = 2,
645ae92dcbeSJiaxin Yu 			.channels_max = 8,
646ae92dcbeSJiaxin Yu 			.rates = MTK_TDM_RATES,
647ae92dcbeSJiaxin Yu 			.formats = MTK_TDM_FORMATS,
648ae92dcbeSJiaxin Yu 		},
649ae92dcbeSJiaxin Yu 		.ops = &mtk_dai_tdm_ops,
650ae92dcbeSJiaxin Yu 	},
651ae92dcbeSJiaxin Yu };
652ae92dcbeSJiaxin Yu 
653ae92dcbeSJiaxin Yu static struct mtk_afe_tdm_priv *init_tdm_priv_data(struct mtk_base_afe *afe)
654ae92dcbeSJiaxin Yu {
655ae92dcbeSJiaxin Yu 	struct mtk_afe_tdm_priv *tdm_priv;
656ae92dcbeSJiaxin Yu 
657ae92dcbeSJiaxin Yu 	tdm_priv = devm_kzalloc(afe->dev, sizeof(struct mtk_afe_tdm_priv),
658ae92dcbeSJiaxin Yu 				GFP_KERNEL);
659ae92dcbeSJiaxin Yu 	if (!tdm_priv)
660ae92dcbeSJiaxin Yu 		return NULL;
661ae92dcbeSJiaxin Yu 
662ae92dcbeSJiaxin Yu 	tdm_priv->mclk_multiple = 512;
663ae92dcbeSJiaxin Yu 	tdm_priv->mclk_id = MT8186_TDM_MCK;
664ae92dcbeSJiaxin Yu 	tdm_priv->id = MT8186_DAI_TDM_IN;
665ae92dcbeSJiaxin Yu 
666ae92dcbeSJiaxin Yu 	return tdm_priv;
667ae92dcbeSJiaxin Yu }
668ae92dcbeSJiaxin Yu 
669ae92dcbeSJiaxin Yu int mt8186_dai_tdm_register(struct mtk_base_afe *afe)
670ae92dcbeSJiaxin Yu {
671ae92dcbeSJiaxin Yu 	struct mt8186_afe_private *afe_priv = afe->platform_priv;
672ae92dcbeSJiaxin Yu 	struct mtk_afe_tdm_priv *tdm_priv;
673ae92dcbeSJiaxin Yu 	struct mtk_base_afe_dai *dai;
674ae92dcbeSJiaxin Yu 
675ae92dcbeSJiaxin Yu 	dai = devm_kzalloc(afe->dev, sizeof(*dai), GFP_KERNEL);
676ae92dcbeSJiaxin Yu 	if (!dai)
677ae92dcbeSJiaxin Yu 		return -ENOMEM;
678ae92dcbeSJiaxin Yu 
679ae92dcbeSJiaxin Yu 	list_add(&dai->list, &afe->sub_dais);
680ae92dcbeSJiaxin Yu 
681ae92dcbeSJiaxin Yu 	dai->dai_drivers = mtk_dai_tdm_driver;
682ae92dcbeSJiaxin Yu 	dai->num_dai_drivers = ARRAY_SIZE(mtk_dai_tdm_driver);
683ae92dcbeSJiaxin Yu 
684ae92dcbeSJiaxin Yu 	dai->controls = mtk_dai_tdm_controls;
685ae92dcbeSJiaxin Yu 	dai->num_controls = ARRAY_SIZE(mtk_dai_tdm_controls);
686ae92dcbeSJiaxin Yu 	dai->dapm_widgets = mtk_dai_tdm_widgets;
687ae92dcbeSJiaxin Yu 	dai->num_dapm_widgets = ARRAY_SIZE(mtk_dai_tdm_widgets);
688ae92dcbeSJiaxin Yu 	dai->dapm_routes = mtk_dai_tdm_routes;
689ae92dcbeSJiaxin Yu 	dai->num_dapm_routes = ARRAY_SIZE(mtk_dai_tdm_routes);
690ae92dcbeSJiaxin Yu 
691ae92dcbeSJiaxin Yu 	tdm_priv = init_tdm_priv_data(afe);
692ae92dcbeSJiaxin Yu 	if (!tdm_priv)
693ae92dcbeSJiaxin Yu 		return -ENOMEM;
694ae92dcbeSJiaxin Yu 
695ae92dcbeSJiaxin Yu 	afe_priv->dai_priv[MT8186_DAI_TDM_IN] = tdm_priv;
696ae92dcbeSJiaxin Yu 
697ae92dcbeSJiaxin Yu 	return 0;
698ae92dcbeSJiaxin Yu }
699