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