xref: /OK3568_Linux_fs/kernel/sound/soc/mediatek/mt8183/mt8183-dai-tdm.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun // SPDX-License-Identifier: GPL-2.0
2*4882a593Smuzhiyun //
3*4882a593Smuzhiyun // MediaTek ALSA SoC Audio DAI TDM Control
4*4882a593Smuzhiyun //
5*4882a593Smuzhiyun // Copyright (c) 2018 MediaTek Inc.
6*4882a593Smuzhiyun // Author: KaiChieh Chuang <kaichieh.chuang@mediatek.com>
7*4882a593Smuzhiyun 
8*4882a593Smuzhiyun #include <linux/regmap.h>
9*4882a593Smuzhiyun #include <sound/pcm_params.h>
10*4882a593Smuzhiyun #include "mt8183-afe-clk.h"
11*4882a593Smuzhiyun #include "mt8183-afe-common.h"
12*4882a593Smuzhiyun #include "mt8183-interconnection.h"
13*4882a593Smuzhiyun #include "mt8183-reg.h"
14*4882a593Smuzhiyun 
15*4882a593Smuzhiyun struct mtk_afe_tdm_priv {
16*4882a593Smuzhiyun 	int bck_id;
17*4882a593Smuzhiyun 	int bck_rate;
18*4882a593Smuzhiyun 	int tdm_out_mode;
19*4882a593Smuzhiyun 	int bck_invert;
20*4882a593Smuzhiyun 	int lck_invert;
21*4882a593Smuzhiyun 	int mclk_id;
22*4882a593Smuzhiyun 	int mclk_multiple; /* according to sample rate */
23*4882a593Smuzhiyun 	int mclk_rate;
24*4882a593Smuzhiyun 	int mclk_apll;
25*4882a593Smuzhiyun };
26*4882a593Smuzhiyun 
27*4882a593Smuzhiyun enum {
28*4882a593Smuzhiyun 	TDM_OUT_I2S = 0,
29*4882a593Smuzhiyun 	TDM_OUT_TDM = 1,
30*4882a593Smuzhiyun };
31*4882a593Smuzhiyun 
32*4882a593Smuzhiyun enum {
33*4882a593Smuzhiyun 	TDM_BCK_NON_INV = 0,
34*4882a593Smuzhiyun 	TDM_BCK_INV = 1,
35*4882a593Smuzhiyun };
36*4882a593Smuzhiyun 
37*4882a593Smuzhiyun enum {
38*4882a593Smuzhiyun 	TDM_LCK_NON_INV = 0,
39*4882a593Smuzhiyun 	TDM_LCK_INV = 1,
40*4882a593Smuzhiyun };
41*4882a593Smuzhiyun 
42*4882a593Smuzhiyun enum {
43*4882a593Smuzhiyun 	TDM_WLEN_16_BIT = 1,
44*4882a593Smuzhiyun 	TDM_WLEN_32_BIT = 2,
45*4882a593Smuzhiyun };
46*4882a593Smuzhiyun 
47*4882a593Smuzhiyun enum {
48*4882a593Smuzhiyun 	TDM_CHANNEL_BCK_16 = 0,
49*4882a593Smuzhiyun 	TDM_CHANNEL_BCK_24 = 1,
50*4882a593Smuzhiyun 	TDM_CHANNEL_BCK_32 = 2,
51*4882a593Smuzhiyun };
52*4882a593Smuzhiyun 
53*4882a593Smuzhiyun enum {
54*4882a593Smuzhiyun 	TDM_CHANNEL_NUM_2 = 0,
55*4882a593Smuzhiyun 	TDM_CHANNEL_NUM_4 = 1,
56*4882a593Smuzhiyun 	TDM_CHANNEL_NUM_8 = 2,
57*4882a593Smuzhiyun };
58*4882a593Smuzhiyun 
59*4882a593Smuzhiyun enum  {
60*4882a593Smuzhiyun 	TDM_CH_START_O30_O31 = 0,
61*4882a593Smuzhiyun 	TDM_CH_START_O32_O33,
62*4882a593Smuzhiyun 	TDM_CH_START_O34_O35,
63*4882a593Smuzhiyun 	TDM_CH_START_O36_O37,
64*4882a593Smuzhiyun 	TDM_CH_ZERO,
65*4882a593Smuzhiyun };
66*4882a593Smuzhiyun 
67*4882a593Smuzhiyun enum {
68*4882a593Smuzhiyun 	HDMI_BIT_WIDTH_16_BIT = 0,
69*4882a593Smuzhiyun 	HDMI_BIT_WIDTH_32_BIT = 1,
70*4882a593Smuzhiyun };
71*4882a593Smuzhiyun 
get_hdmi_wlen(snd_pcm_format_t format)72*4882a593Smuzhiyun static unsigned int get_hdmi_wlen(snd_pcm_format_t format)
73*4882a593Smuzhiyun {
74*4882a593Smuzhiyun 	return snd_pcm_format_physical_width(format) <= 16 ?
75*4882a593Smuzhiyun 	       HDMI_BIT_WIDTH_16_BIT : HDMI_BIT_WIDTH_32_BIT;
76*4882a593Smuzhiyun }
77*4882a593Smuzhiyun 
get_tdm_wlen(snd_pcm_format_t format)78*4882a593Smuzhiyun static unsigned int get_tdm_wlen(snd_pcm_format_t format)
79*4882a593Smuzhiyun {
80*4882a593Smuzhiyun 	return snd_pcm_format_physical_width(format) <= 16 ?
81*4882a593Smuzhiyun 	       TDM_WLEN_16_BIT : TDM_WLEN_32_BIT;
82*4882a593Smuzhiyun }
83*4882a593Smuzhiyun 
get_tdm_channel_bck(snd_pcm_format_t format)84*4882a593Smuzhiyun static unsigned int get_tdm_channel_bck(snd_pcm_format_t format)
85*4882a593Smuzhiyun {
86*4882a593Smuzhiyun 	return snd_pcm_format_physical_width(format) <= 16 ?
87*4882a593Smuzhiyun 	       TDM_CHANNEL_BCK_16 : TDM_CHANNEL_BCK_32;
88*4882a593Smuzhiyun }
89*4882a593Smuzhiyun 
get_tdm_lrck_width(snd_pcm_format_t format)90*4882a593Smuzhiyun static unsigned int get_tdm_lrck_width(snd_pcm_format_t format)
91*4882a593Smuzhiyun {
92*4882a593Smuzhiyun 	return snd_pcm_format_physical_width(format) - 1;
93*4882a593Smuzhiyun }
94*4882a593Smuzhiyun 
get_tdm_ch(unsigned int ch)95*4882a593Smuzhiyun static unsigned int get_tdm_ch(unsigned int ch)
96*4882a593Smuzhiyun {
97*4882a593Smuzhiyun 	switch (ch) {
98*4882a593Smuzhiyun 	case 1:
99*4882a593Smuzhiyun 	case 2:
100*4882a593Smuzhiyun 		return TDM_CHANNEL_NUM_2;
101*4882a593Smuzhiyun 	case 3:
102*4882a593Smuzhiyun 	case 4:
103*4882a593Smuzhiyun 		return TDM_CHANNEL_NUM_4;
104*4882a593Smuzhiyun 	case 5:
105*4882a593Smuzhiyun 	case 6:
106*4882a593Smuzhiyun 	case 7:
107*4882a593Smuzhiyun 	case 8:
108*4882a593Smuzhiyun 	default:
109*4882a593Smuzhiyun 		return TDM_CHANNEL_NUM_8;
110*4882a593Smuzhiyun 	}
111*4882a593Smuzhiyun }
112*4882a593Smuzhiyun 
get_tdm_ch_fixup(unsigned int channels)113*4882a593Smuzhiyun static unsigned int get_tdm_ch_fixup(unsigned int channels)
114*4882a593Smuzhiyun {
115*4882a593Smuzhiyun 	if (channels > 4)
116*4882a593Smuzhiyun 		return 8;
117*4882a593Smuzhiyun 	else if (channels > 2)
118*4882a593Smuzhiyun 		return 4;
119*4882a593Smuzhiyun 	else
120*4882a593Smuzhiyun 		return 2;
121*4882a593Smuzhiyun }
122*4882a593Smuzhiyun 
get_tdm_ch_per_sdata(unsigned int mode,unsigned int channels)123*4882a593Smuzhiyun static unsigned int get_tdm_ch_per_sdata(unsigned int mode,
124*4882a593Smuzhiyun 					 unsigned int channels)
125*4882a593Smuzhiyun {
126*4882a593Smuzhiyun 	if (mode == TDM_OUT_TDM)
127*4882a593Smuzhiyun 		return get_tdm_ch_fixup(channels);
128*4882a593Smuzhiyun 	else
129*4882a593Smuzhiyun 		return 2;
130*4882a593Smuzhiyun }
131*4882a593Smuzhiyun 
132*4882a593Smuzhiyun /* interconnection */
133*4882a593Smuzhiyun enum {
134*4882a593Smuzhiyun 	HDMI_CONN_CH0 = 0,
135*4882a593Smuzhiyun 	HDMI_CONN_CH1,
136*4882a593Smuzhiyun 	HDMI_CONN_CH2,
137*4882a593Smuzhiyun 	HDMI_CONN_CH3,
138*4882a593Smuzhiyun 	HDMI_CONN_CH4,
139*4882a593Smuzhiyun 	HDMI_CONN_CH5,
140*4882a593Smuzhiyun 	HDMI_CONN_CH6,
141*4882a593Smuzhiyun 	HDMI_CONN_CH7,
142*4882a593Smuzhiyun };
143*4882a593Smuzhiyun 
144*4882a593Smuzhiyun static const char *const hdmi_conn_mux_map[] = {
145*4882a593Smuzhiyun 	"CH0", "CH1", "CH2", "CH3",
146*4882a593Smuzhiyun 	"CH4", "CH5", "CH6", "CH7",
147*4882a593Smuzhiyun };
148*4882a593Smuzhiyun 
149*4882a593Smuzhiyun static int hdmi_conn_mux_map_value[] = {
150*4882a593Smuzhiyun 	HDMI_CONN_CH0,
151*4882a593Smuzhiyun 	HDMI_CONN_CH1,
152*4882a593Smuzhiyun 	HDMI_CONN_CH2,
153*4882a593Smuzhiyun 	HDMI_CONN_CH3,
154*4882a593Smuzhiyun 	HDMI_CONN_CH4,
155*4882a593Smuzhiyun 	HDMI_CONN_CH5,
156*4882a593Smuzhiyun 	HDMI_CONN_CH6,
157*4882a593Smuzhiyun 	HDMI_CONN_CH7,
158*4882a593Smuzhiyun };
159*4882a593Smuzhiyun 
160*4882a593Smuzhiyun static SOC_VALUE_ENUM_SINGLE_DECL(hdmi_ch0_mux_map_enum,
161*4882a593Smuzhiyun 				  AFE_HDMI_CONN0,
162*4882a593Smuzhiyun 				  HDMI_O_0_SFT,
163*4882a593Smuzhiyun 				  HDMI_O_0_MASK,
164*4882a593Smuzhiyun 				  hdmi_conn_mux_map,
165*4882a593Smuzhiyun 				  hdmi_conn_mux_map_value);
166*4882a593Smuzhiyun 
167*4882a593Smuzhiyun static const struct snd_kcontrol_new hdmi_ch0_mux_control =
168*4882a593Smuzhiyun 	SOC_DAPM_ENUM("HDMI_CH0_MUX", hdmi_ch0_mux_map_enum);
169*4882a593Smuzhiyun 
170*4882a593Smuzhiyun static SOC_VALUE_ENUM_SINGLE_DECL(hdmi_ch1_mux_map_enum,
171*4882a593Smuzhiyun 				  AFE_HDMI_CONN0,
172*4882a593Smuzhiyun 				  HDMI_O_1_SFT,
173*4882a593Smuzhiyun 				  HDMI_O_1_MASK,
174*4882a593Smuzhiyun 				  hdmi_conn_mux_map,
175*4882a593Smuzhiyun 				  hdmi_conn_mux_map_value);
176*4882a593Smuzhiyun 
177*4882a593Smuzhiyun static const struct snd_kcontrol_new hdmi_ch1_mux_control =
178*4882a593Smuzhiyun 	SOC_DAPM_ENUM("HDMI_CH1_MUX", hdmi_ch1_mux_map_enum);
179*4882a593Smuzhiyun 
180*4882a593Smuzhiyun static SOC_VALUE_ENUM_SINGLE_DECL(hdmi_ch2_mux_map_enum,
181*4882a593Smuzhiyun 				  AFE_HDMI_CONN0,
182*4882a593Smuzhiyun 				  HDMI_O_2_SFT,
183*4882a593Smuzhiyun 				  HDMI_O_2_MASK,
184*4882a593Smuzhiyun 				  hdmi_conn_mux_map,
185*4882a593Smuzhiyun 				  hdmi_conn_mux_map_value);
186*4882a593Smuzhiyun 
187*4882a593Smuzhiyun static const struct snd_kcontrol_new hdmi_ch2_mux_control =
188*4882a593Smuzhiyun 	SOC_DAPM_ENUM("HDMI_CH2_MUX", hdmi_ch2_mux_map_enum);
189*4882a593Smuzhiyun 
190*4882a593Smuzhiyun static SOC_VALUE_ENUM_SINGLE_DECL(hdmi_ch3_mux_map_enum,
191*4882a593Smuzhiyun 				  AFE_HDMI_CONN0,
192*4882a593Smuzhiyun 				  HDMI_O_3_SFT,
193*4882a593Smuzhiyun 				  HDMI_O_3_MASK,
194*4882a593Smuzhiyun 				  hdmi_conn_mux_map,
195*4882a593Smuzhiyun 				  hdmi_conn_mux_map_value);
196*4882a593Smuzhiyun 
197*4882a593Smuzhiyun static const struct snd_kcontrol_new hdmi_ch3_mux_control =
198*4882a593Smuzhiyun 	SOC_DAPM_ENUM("HDMI_CH3_MUX", hdmi_ch3_mux_map_enum);
199*4882a593Smuzhiyun 
200*4882a593Smuzhiyun static SOC_VALUE_ENUM_SINGLE_DECL(hdmi_ch4_mux_map_enum,
201*4882a593Smuzhiyun 				  AFE_HDMI_CONN0,
202*4882a593Smuzhiyun 				  HDMI_O_4_SFT,
203*4882a593Smuzhiyun 				  HDMI_O_4_MASK,
204*4882a593Smuzhiyun 				  hdmi_conn_mux_map,
205*4882a593Smuzhiyun 				  hdmi_conn_mux_map_value);
206*4882a593Smuzhiyun 
207*4882a593Smuzhiyun static const struct snd_kcontrol_new hdmi_ch4_mux_control =
208*4882a593Smuzhiyun 	SOC_DAPM_ENUM("HDMI_CH4_MUX", hdmi_ch4_mux_map_enum);
209*4882a593Smuzhiyun 
210*4882a593Smuzhiyun static SOC_VALUE_ENUM_SINGLE_DECL(hdmi_ch5_mux_map_enum,
211*4882a593Smuzhiyun 				  AFE_HDMI_CONN0,
212*4882a593Smuzhiyun 				  HDMI_O_5_SFT,
213*4882a593Smuzhiyun 				  HDMI_O_5_MASK,
214*4882a593Smuzhiyun 				  hdmi_conn_mux_map,
215*4882a593Smuzhiyun 				  hdmi_conn_mux_map_value);
216*4882a593Smuzhiyun 
217*4882a593Smuzhiyun static const struct snd_kcontrol_new hdmi_ch5_mux_control =
218*4882a593Smuzhiyun 	SOC_DAPM_ENUM("HDMI_CH5_MUX", hdmi_ch5_mux_map_enum);
219*4882a593Smuzhiyun 
220*4882a593Smuzhiyun static SOC_VALUE_ENUM_SINGLE_DECL(hdmi_ch6_mux_map_enum,
221*4882a593Smuzhiyun 				  AFE_HDMI_CONN0,
222*4882a593Smuzhiyun 				  HDMI_O_6_SFT,
223*4882a593Smuzhiyun 				  HDMI_O_6_MASK,
224*4882a593Smuzhiyun 				  hdmi_conn_mux_map,
225*4882a593Smuzhiyun 				  hdmi_conn_mux_map_value);
226*4882a593Smuzhiyun 
227*4882a593Smuzhiyun static const struct snd_kcontrol_new hdmi_ch6_mux_control =
228*4882a593Smuzhiyun 	SOC_DAPM_ENUM("HDMI_CH6_MUX", hdmi_ch6_mux_map_enum);
229*4882a593Smuzhiyun 
230*4882a593Smuzhiyun static SOC_VALUE_ENUM_SINGLE_DECL(hdmi_ch7_mux_map_enum,
231*4882a593Smuzhiyun 				  AFE_HDMI_CONN0,
232*4882a593Smuzhiyun 				  HDMI_O_7_SFT,
233*4882a593Smuzhiyun 				  HDMI_O_7_MASK,
234*4882a593Smuzhiyun 				  hdmi_conn_mux_map,
235*4882a593Smuzhiyun 				  hdmi_conn_mux_map_value);
236*4882a593Smuzhiyun 
237*4882a593Smuzhiyun static const struct snd_kcontrol_new hdmi_ch7_mux_control =
238*4882a593Smuzhiyun 	SOC_DAPM_ENUM("HDMI_CH7_MUX", hdmi_ch7_mux_map_enum);
239*4882a593Smuzhiyun 
240*4882a593Smuzhiyun enum {
241*4882a593Smuzhiyun 	SUPPLY_SEQ_APLL,
242*4882a593Smuzhiyun 	SUPPLY_SEQ_TDM_MCK_EN,
243*4882a593Smuzhiyun 	SUPPLY_SEQ_TDM_BCK_EN,
244*4882a593Smuzhiyun };
245*4882a593Smuzhiyun 
mtk_tdm_bck_en_event(struct snd_soc_dapm_widget * w,struct snd_kcontrol * kcontrol,int event)246*4882a593Smuzhiyun static int mtk_tdm_bck_en_event(struct snd_soc_dapm_widget *w,
247*4882a593Smuzhiyun 				struct snd_kcontrol *kcontrol,
248*4882a593Smuzhiyun 				int event)
249*4882a593Smuzhiyun {
250*4882a593Smuzhiyun 	struct snd_soc_component *cmpnt = snd_soc_dapm_to_component(w->dapm);
251*4882a593Smuzhiyun 	struct mtk_base_afe *afe = snd_soc_component_get_drvdata(cmpnt);
252*4882a593Smuzhiyun 	struct mt8183_afe_private *afe_priv = afe->platform_priv;
253*4882a593Smuzhiyun 	struct mtk_afe_tdm_priv *tdm_priv = afe_priv->dai_priv[MT8183_DAI_TDM];
254*4882a593Smuzhiyun 
255*4882a593Smuzhiyun 	dev_info(cmpnt->dev, "%s(), name %s, event 0x%x\n",
256*4882a593Smuzhiyun 		 __func__, w->name, event);
257*4882a593Smuzhiyun 
258*4882a593Smuzhiyun 	switch (event) {
259*4882a593Smuzhiyun 	case SND_SOC_DAPM_PRE_PMU:
260*4882a593Smuzhiyun 		mt8183_mck_enable(afe, tdm_priv->bck_id, tdm_priv->bck_rate);
261*4882a593Smuzhiyun 		break;
262*4882a593Smuzhiyun 	case SND_SOC_DAPM_POST_PMD:
263*4882a593Smuzhiyun 		mt8183_mck_disable(afe, tdm_priv->bck_id);
264*4882a593Smuzhiyun 		break;
265*4882a593Smuzhiyun 	default:
266*4882a593Smuzhiyun 		break;
267*4882a593Smuzhiyun 	}
268*4882a593Smuzhiyun 
269*4882a593Smuzhiyun 	return 0;
270*4882a593Smuzhiyun }
271*4882a593Smuzhiyun 
mtk_tdm_mck_en_event(struct snd_soc_dapm_widget * w,struct snd_kcontrol * kcontrol,int event)272*4882a593Smuzhiyun static int mtk_tdm_mck_en_event(struct snd_soc_dapm_widget *w,
273*4882a593Smuzhiyun 				struct snd_kcontrol *kcontrol,
274*4882a593Smuzhiyun 				int event)
275*4882a593Smuzhiyun {
276*4882a593Smuzhiyun 	struct snd_soc_component *cmpnt = snd_soc_dapm_to_component(w->dapm);
277*4882a593Smuzhiyun 	struct mtk_base_afe *afe = snd_soc_component_get_drvdata(cmpnt);
278*4882a593Smuzhiyun 	struct mt8183_afe_private *afe_priv = afe->platform_priv;
279*4882a593Smuzhiyun 	struct mtk_afe_tdm_priv *tdm_priv = afe_priv->dai_priv[MT8183_DAI_TDM];
280*4882a593Smuzhiyun 
281*4882a593Smuzhiyun 	dev_info(cmpnt->dev, "%s(), name %s, event 0x%x\n",
282*4882a593Smuzhiyun 		 __func__, w->name, event);
283*4882a593Smuzhiyun 
284*4882a593Smuzhiyun 	switch (event) {
285*4882a593Smuzhiyun 	case SND_SOC_DAPM_PRE_PMU:
286*4882a593Smuzhiyun 		mt8183_mck_enable(afe, tdm_priv->mclk_id, tdm_priv->mclk_rate);
287*4882a593Smuzhiyun 		break;
288*4882a593Smuzhiyun 	case SND_SOC_DAPM_POST_PMD:
289*4882a593Smuzhiyun 		tdm_priv->mclk_rate = 0;
290*4882a593Smuzhiyun 		mt8183_mck_disable(afe, tdm_priv->mclk_id);
291*4882a593Smuzhiyun 		break;
292*4882a593Smuzhiyun 	default:
293*4882a593Smuzhiyun 		break;
294*4882a593Smuzhiyun 	}
295*4882a593Smuzhiyun 
296*4882a593Smuzhiyun 	return 0;
297*4882a593Smuzhiyun }
298*4882a593Smuzhiyun 
299*4882a593Smuzhiyun static const struct snd_soc_dapm_widget mtk_dai_tdm_widgets[] = {
300*4882a593Smuzhiyun 	SND_SOC_DAPM_MUX("HDMI_CH0_MUX", SND_SOC_NOPM, 0, 0,
301*4882a593Smuzhiyun 			 &hdmi_ch0_mux_control),
302*4882a593Smuzhiyun 	SND_SOC_DAPM_MUX("HDMI_CH1_MUX", SND_SOC_NOPM, 0, 0,
303*4882a593Smuzhiyun 			 &hdmi_ch1_mux_control),
304*4882a593Smuzhiyun 	SND_SOC_DAPM_MUX("HDMI_CH2_MUX", SND_SOC_NOPM, 0, 0,
305*4882a593Smuzhiyun 			 &hdmi_ch2_mux_control),
306*4882a593Smuzhiyun 	SND_SOC_DAPM_MUX("HDMI_CH3_MUX", SND_SOC_NOPM, 0, 0,
307*4882a593Smuzhiyun 			 &hdmi_ch3_mux_control),
308*4882a593Smuzhiyun 	SND_SOC_DAPM_MUX("HDMI_CH4_MUX", SND_SOC_NOPM, 0, 0,
309*4882a593Smuzhiyun 			 &hdmi_ch4_mux_control),
310*4882a593Smuzhiyun 	SND_SOC_DAPM_MUX("HDMI_CH5_MUX", SND_SOC_NOPM, 0, 0,
311*4882a593Smuzhiyun 			 &hdmi_ch5_mux_control),
312*4882a593Smuzhiyun 	SND_SOC_DAPM_MUX("HDMI_CH6_MUX", SND_SOC_NOPM, 0, 0,
313*4882a593Smuzhiyun 			 &hdmi_ch6_mux_control),
314*4882a593Smuzhiyun 	SND_SOC_DAPM_MUX("HDMI_CH7_MUX", SND_SOC_NOPM, 0, 0,
315*4882a593Smuzhiyun 			 &hdmi_ch7_mux_control),
316*4882a593Smuzhiyun 
317*4882a593Smuzhiyun 	SND_SOC_DAPM_CLOCK_SUPPLY("aud_tdm_clk"),
318*4882a593Smuzhiyun 
319*4882a593Smuzhiyun 	SND_SOC_DAPM_SUPPLY_S("TDM_BCK", SUPPLY_SEQ_TDM_BCK_EN,
320*4882a593Smuzhiyun 			      SND_SOC_NOPM, 0, 0,
321*4882a593Smuzhiyun 			      mtk_tdm_bck_en_event,
322*4882a593Smuzhiyun 			      SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
323*4882a593Smuzhiyun 
324*4882a593Smuzhiyun 	SND_SOC_DAPM_SUPPLY_S("TDM_MCK", SUPPLY_SEQ_TDM_MCK_EN,
325*4882a593Smuzhiyun 			      SND_SOC_NOPM, 0, 0,
326*4882a593Smuzhiyun 			      mtk_tdm_mck_en_event,
327*4882a593Smuzhiyun 			      SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
328*4882a593Smuzhiyun };
329*4882a593Smuzhiyun 
mtk_afe_tdm_apll_connect(struct snd_soc_dapm_widget * source,struct snd_soc_dapm_widget * sink)330*4882a593Smuzhiyun static int mtk_afe_tdm_apll_connect(struct snd_soc_dapm_widget *source,
331*4882a593Smuzhiyun 				    struct snd_soc_dapm_widget *sink)
332*4882a593Smuzhiyun {
333*4882a593Smuzhiyun 	struct snd_soc_dapm_widget *w = sink;
334*4882a593Smuzhiyun 	struct snd_soc_component *cmpnt = snd_soc_dapm_to_component(w->dapm);
335*4882a593Smuzhiyun 	struct mtk_base_afe *afe = snd_soc_component_get_drvdata(cmpnt);
336*4882a593Smuzhiyun 	struct mt8183_afe_private *afe_priv = afe->platform_priv;
337*4882a593Smuzhiyun 	struct mtk_afe_tdm_priv *tdm_priv = afe_priv->dai_priv[MT8183_DAI_TDM];
338*4882a593Smuzhiyun 	int cur_apll;
339*4882a593Smuzhiyun 
340*4882a593Smuzhiyun 	/* which apll */
341*4882a593Smuzhiyun 	cur_apll = mt8183_get_apll_by_name(afe, source->name);
342*4882a593Smuzhiyun 
343*4882a593Smuzhiyun 	return (tdm_priv->mclk_apll == cur_apll) ? 1 : 0;
344*4882a593Smuzhiyun }
345*4882a593Smuzhiyun 
346*4882a593Smuzhiyun static const struct snd_soc_dapm_route mtk_dai_tdm_routes[] = {
347*4882a593Smuzhiyun 	{"HDMI_CH0_MUX", "CH0", "HDMI"},
348*4882a593Smuzhiyun 	{"HDMI_CH0_MUX", "CH1", "HDMI"},
349*4882a593Smuzhiyun 	{"HDMI_CH0_MUX", "CH2", "HDMI"},
350*4882a593Smuzhiyun 	{"HDMI_CH0_MUX", "CH3", "HDMI"},
351*4882a593Smuzhiyun 	{"HDMI_CH0_MUX", "CH4", "HDMI"},
352*4882a593Smuzhiyun 	{"HDMI_CH0_MUX", "CH5", "HDMI"},
353*4882a593Smuzhiyun 	{"HDMI_CH0_MUX", "CH6", "HDMI"},
354*4882a593Smuzhiyun 	{"HDMI_CH0_MUX", "CH7", "HDMI"},
355*4882a593Smuzhiyun 
356*4882a593Smuzhiyun 	{"HDMI_CH1_MUX", "CH0", "HDMI"},
357*4882a593Smuzhiyun 	{"HDMI_CH1_MUX", "CH1", "HDMI"},
358*4882a593Smuzhiyun 	{"HDMI_CH1_MUX", "CH2", "HDMI"},
359*4882a593Smuzhiyun 	{"HDMI_CH1_MUX", "CH3", "HDMI"},
360*4882a593Smuzhiyun 	{"HDMI_CH1_MUX", "CH4", "HDMI"},
361*4882a593Smuzhiyun 	{"HDMI_CH1_MUX", "CH5", "HDMI"},
362*4882a593Smuzhiyun 	{"HDMI_CH1_MUX", "CH6", "HDMI"},
363*4882a593Smuzhiyun 	{"HDMI_CH1_MUX", "CH7", "HDMI"},
364*4882a593Smuzhiyun 
365*4882a593Smuzhiyun 	{"HDMI_CH2_MUX", "CH0", "HDMI"},
366*4882a593Smuzhiyun 	{"HDMI_CH2_MUX", "CH1", "HDMI"},
367*4882a593Smuzhiyun 	{"HDMI_CH2_MUX", "CH2", "HDMI"},
368*4882a593Smuzhiyun 	{"HDMI_CH2_MUX", "CH3", "HDMI"},
369*4882a593Smuzhiyun 	{"HDMI_CH2_MUX", "CH4", "HDMI"},
370*4882a593Smuzhiyun 	{"HDMI_CH2_MUX", "CH5", "HDMI"},
371*4882a593Smuzhiyun 	{"HDMI_CH2_MUX", "CH6", "HDMI"},
372*4882a593Smuzhiyun 	{"HDMI_CH2_MUX", "CH7", "HDMI"},
373*4882a593Smuzhiyun 
374*4882a593Smuzhiyun 	{"HDMI_CH3_MUX", "CH0", "HDMI"},
375*4882a593Smuzhiyun 	{"HDMI_CH3_MUX", "CH1", "HDMI"},
376*4882a593Smuzhiyun 	{"HDMI_CH3_MUX", "CH2", "HDMI"},
377*4882a593Smuzhiyun 	{"HDMI_CH3_MUX", "CH3", "HDMI"},
378*4882a593Smuzhiyun 	{"HDMI_CH3_MUX", "CH4", "HDMI"},
379*4882a593Smuzhiyun 	{"HDMI_CH3_MUX", "CH5", "HDMI"},
380*4882a593Smuzhiyun 	{"HDMI_CH3_MUX", "CH6", "HDMI"},
381*4882a593Smuzhiyun 	{"HDMI_CH3_MUX", "CH7", "HDMI"},
382*4882a593Smuzhiyun 
383*4882a593Smuzhiyun 	{"HDMI_CH4_MUX", "CH0", "HDMI"},
384*4882a593Smuzhiyun 	{"HDMI_CH4_MUX", "CH1", "HDMI"},
385*4882a593Smuzhiyun 	{"HDMI_CH4_MUX", "CH2", "HDMI"},
386*4882a593Smuzhiyun 	{"HDMI_CH4_MUX", "CH3", "HDMI"},
387*4882a593Smuzhiyun 	{"HDMI_CH4_MUX", "CH4", "HDMI"},
388*4882a593Smuzhiyun 	{"HDMI_CH4_MUX", "CH5", "HDMI"},
389*4882a593Smuzhiyun 	{"HDMI_CH4_MUX", "CH6", "HDMI"},
390*4882a593Smuzhiyun 	{"HDMI_CH4_MUX", "CH7", "HDMI"},
391*4882a593Smuzhiyun 
392*4882a593Smuzhiyun 	{"HDMI_CH5_MUX", "CH0", "HDMI"},
393*4882a593Smuzhiyun 	{"HDMI_CH5_MUX", "CH1", "HDMI"},
394*4882a593Smuzhiyun 	{"HDMI_CH5_MUX", "CH2", "HDMI"},
395*4882a593Smuzhiyun 	{"HDMI_CH5_MUX", "CH3", "HDMI"},
396*4882a593Smuzhiyun 	{"HDMI_CH5_MUX", "CH4", "HDMI"},
397*4882a593Smuzhiyun 	{"HDMI_CH5_MUX", "CH5", "HDMI"},
398*4882a593Smuzhiyun 	{"HDMI_CH5_MUX", "CH6", "HDMI"},
399*4882a593Smuzhiyun 	{"HDMI_CH5_MUX", "CH7", "HDMI"},
400*4882a593Smuzhiyun 
401*4882a593Smuzhiyun 	{"HDMI_CH6_MUX", "CH0", "HDMI"},
402*4882a593Smuzhiyun 	{"HDMI_CH6_MUX", "CH1", "HDMI"},
403*4882a593Smuzhiyun 	{"HDMI_CH6_MUX", "CH2", "HDMI"},
404*4882a593Smuzhiyun 	{"HDMI_CH6_MUX", "CH3", "HDMI"},
405*4882a593Smuzhiyun 	{"HDMI_CH6_MUX", "CH4", "HDMI"},
406*4882a593Smuzhiyun 	{"HDMI_CH6_MUX", "CH5", "HDMI"},
407*4882a593Smuzhiyun 	{"HDMI_CH6_MUX", "CH6", "HDMI"},
408*4882a593Smuzhiyun 	{"HDMI_CH6_MUX", "CH7", "HDMI"},
409*4882a593Smuzhiyun 
410*4882a593Smuzhiyun 	{"HDMI_CH7_MUX", "CH0", "HDMI"},
411*4882a593Smuzhiyun 	{"HDMI_CH7_MUX", "CH1", "HDMI"},
412*4882a593Smuzhiyun 	{"HDMI_CH7_MUX", "CH2", "HDMI"},
413*4882a593Smuzhiyun 	{"HDMI_CH7_MUX", "CH3", "HDMI"},
414*4882a593Smuzhiyun 	{"HDMI_CH7_MUX", "CH4", "HDMI"},
415*4882a593Smuzhiyun 	{"HDMI_CH7_MUX", "CH5", "HDMI"},
416*4882a593Smuzhiyun 	{"HDMI_CH7_MUX", "CH6", "HDMI"},
417*4882a593Smuzhiyun 	{"HDMI_CH7_MUX", "CH7", "HDMI"},
418*4882a593Smuzhiyun 
419*4882a593Smuzhiyun 	{"TDM", NULL, "HDMI_CH0_MUX"},
420*4882a593Smuzhiyun 	{"TDM", NULL, "HDMI_CH1_MUX"},
421*4882a593Smuzhiyun 	{"TDM", NULL, "HDMI_CH2_MUX"},
422*4882a593Smuzhiyun 	{"TDM", NULL, "HDMI_CH3_MUX"},
423*4882a593Smuzhiyun 	{"TDM", NULL, "HDMI_CH4_MUX"},
424*4882a593Smuzhiyun 	{"TDM", NULL, "HDMI_CH5_MUX"},
425*4882a593Smuzhiyun 	{"TDM", NULL, "HDMI_CH6_MUX"},
426*4882a593Smuzhiyun 	{"TDM", NULL, "HDMI_CH7_MUX"},
427*4882a593Smuzhiyun 
428*4882a593Smuzhiyun 	{"TDM", NULL, "aud_tdm_clk"},
429*4882a593Smuzhiyun 	{"TDM", NULL, "TDM_BCK"},
430*4882a593Smuzhiyun 	{"TDM_BCK", NULL, "TDM_MCK"},
431*4882a593Smuzhiyun 	{"TDM_MCK", NULL, APLL1_W_NAME, mtk_afe_tdm_apll_connect},
432*4882a593Smuzhiyun 	{"TDM_MCK", NULL, APLL2_W_NAME, mtk_afe_tdm_apll_connect},
433*4882a593Smuzhiyun };
434*4882a593Smuzhiyun 
435*4882a593Smuzhiyun /* dai ops */
mtk_dai_tdm_cal_mclk(struct mtk_base_afe * afe,struct mtk_afe_tdm_priv * tdm_priv,int freq)436*4882a593Smuzhiyun static int mtk_dai_tdm_cal_mclk(struct mtk_base_afe *afe,
437*4882a593Smuzhiyun 				struct mtk_afe_tdm_priv *tdm_priv,
438*4882a593Smuzhiyun 				int freq)
439*4882a593Smuzhiyun {
440*4882a593Smuzhiyun 	int apll;
441*4882a593Smuzhiyun 	int apll_rate;
442*4882a593Smuzhiyun 
443*4882a593Smuzhiyun 	apll = mt8183_get_apll_by_rate(afe, freq);
444*4882a593Smuzhiyun 	apll_rate = mt8183_get_apll_rate(afe, apll);
445*4882a593Smuzhiyun 
446*4882a593Smuzhiyun 	if (!freq || freq > apll_rate) {
447*4882a593Smuzhiyun 		dev_warn(afe->dev,
448*4882a593Smuzhiyun 			 "%s(), freq(%d Hz) invalid\n", __func__, freq);
449*4882a593Smuzhiyun 		return -EINVAL;
450*4882a593Smuzhiyun 	}
451*4882a593Smuzhiyun 
452*4882a593Smuzhiyun 	if (apll_rate % freq != 0) {
453*4882a593Smuzhiyun 		dev_warn(afe->dev,
454*4882a593Smuzhiyun 			 "%s(), APLL cannot generate %d Hz", __func__, freq);
455*4882a593Smuzhiyun 		return -EINVAL;
456*4882a593Smuzhiyun 	}
457*4882a593Smuzhiyun 
458*4882a593Smuzhiyun 	tdm_priv->mclk_rate = freq;
459*4882a593Smuzhiyun 	tdm_priv->mclk_apll = apll;
460*4882a593Smuzhiyun 
461*4882a593Smuzhiyun 	return 0;
462*4882a593Smuzhiyun }
463*4882a593Smuzhiyun 
mtk_dai_tdm_hw_params(struct snd_pcm_substream * substream,struct snd_pcm_hw_params * params,struct snd_soc_dai * dai)464*4882a593Smuzhiyun static int mtk_dai_tdm_hw_params(struct snd_pcm_substream *substream,
465*4882a593Smuzhiyun 				 struct snd_pcm_hw_params *params,
466*4882a593Smuzhiyun 				 struct snd_soc_dai *dai)
467*4882a593Smuzhiyun {
468*4882a593Smuzhiyun 	struct mtk_base_afe *afe = snd_soc_dai_get_drvdata(dai);
469*4882a593Smuzhiyun 	struct mt8183_afe_private *afe_priv = afe->platform_priv;
470*4882a593Smuzhiyun 	int tdm_id = dai->id;
471*4882a593Smuzhiyun 	struct mtk_afe_tdm_priv *tdm_priv = afe_priv->dai_priv[tdm_id];
472*4882a593Smuzhiyun 	unsigned int tdm_out_mode = tdm_priv->tdm_out_mode;
473*4882a593Smuzhiyun 	unsigned int rate = params_rate(params);
474*4882a593Smuzhiyun 	unsigned int channels = params_channels(params);
475*4882a593Smuzhiyun 	unsigned int out_channels_per_sdata =
476*4882a593Smuzhiyun 		get_tdm_ch_per_sdata(tdm_out_mode, channels);
477*4882a593Smuzhiyun 	snd_pcm_format_t format = params_format(params);
478*4882a593Smuzhiyun 	unsigned int tdm_con = 0;
479*4882a593Smuzhiyun 
480*4882a593Smuzhiyun 	/* calculate mclk_rate, if not set explicitly */
481*4882a593Smuzhiyun 	if (!tdm_priv->mclk_rate) {
482*4882a593Smuzhiyun 		tdm_priv->mclk_rate = rate * tdm_priv->mclk_multiple;
483*4882a593Smuzhiyun 		mtk_dai_tdm_cal_mclk(afe,
484*4882a593Smuzhiyun 				     tdm_priv,
485*4882a593Smuzhiyun 				     tdm_priv->mclk_rate);
486*4882a593Smuzhiyun 	}
487*4882a593Smuzhiyun 
488*4882a593Smuzhiyun 	/* calculate bck */
489*4882a593Smuzhiyun 	tdm_priv->bck_rate = rate *
490*4882a593Smuzhiyun 			     out_channels_per_sdata *
491*4882a593Smuzhiyun 			     snd_pcm_format_physical_width(format);
492*4882a593Smuzhiyun 
493*4882a593Smuzhiyun 	if (tdm_priv->bck_rate > tdm_priv->mclk_rate)
494*4882a593Smuzhiyun 		dev_warn(afe->dev, "%s(), bck_rate > mclk_rate rate", __func__);
495*4882a593Smuzhiyun 
496*4882a593Smuzhiyun 	if (tdm_priv->mclk_rate % tdm_priv->bck_rate != 0)
497*4882a593Smuzhiyun 		dev_warn(afe->dev, "%s(), bck cannot generate", __func__);
498*4882a593Smuzhiyun 
499*4882a593Smuzhiyun 	dev_info(afe->dev, "%s(), id %d, rate %d, channels %d, format %d, mclk_rate %d, bck_rate %d\n",
500*4882a593Smuzhiyun 		 __func__,
501*4882a593Smuzhiyun 		 tdm_id, rate, channels, format,
502*4882a593Smuzhiyun 		 tdm_priv->mclk_rate, tdm_priv->bck_rate);
503*4882a593Smuzhiyun 	dev_info(afe->dev, "%s(), out_channels_per_sdata = %d\n",
504*4882a593Smuzhiyun 		 __func__, out_channels_per_sdata);
505*4882a593Smuzhiyun 
506*4882a593Smuzhiyun 	/* set tdm */
507*4882a593Smuzhiyun 	if (tdm_priv->bck_invert)
508*4882a593Smuzhiyun 		regmap_update_bits(afe->regmap, AUDIO_TOP_CON3,
509*4882a593Smuzhiyun 				   BCK_INVERSE_MASK_SFT,
510*4882a593Smuzhiyun 				   0x1 << BCK_INVERSE_SFT);
511*4882a593Smuzhiyun 
512*4882a593Smuzhiyun 	if (tdm_priv->lck_invert)
513*4882a593Smuzhiyun 		tdm_con |= 1 << LRCK_INVERSE_SFT;
514*4882a593Smuzhiyun 
515*4882a593Smuzhiyun 	if (tdm_priv->tdm_out_mode == TDM_OUT_I2S) {
516*4882a593Smuzhiyun 		tdm_con |= 1 << DELAY_DATA_SFT;
517*4882a593Smuzhiyun 		tdm_con |= get_tdm_lrck_width(format) << LRCK_TDM_WIDTH_SFT;
518*4882a593Smuzhiyun 	} else if (tdm_priv->tdm_out_mode == TDM_OUT_TDM) {
519*4882a593Smuzhiyun 		tdm_con |= 0 << DELAY_DATA_SFT;
520*4882a593Smuzhiyun 		tdm_con |= 0 << LRCK_TDM_WIDTH_SFT;
521*4882a593Smuzhiyun 	}
522*4882a593Smuzhiyun 
523*4882a593Smuzhiyun 	tdm_con |= 1 << LEFT_ALIGN_SFT;
524*4882a593Smuzhiyun 	tdm_con |= get_tdm_wlen(format) << WLEN_SFT;
525*4882a593Smuzhiyun 	tdm_con |= get_tdm_ch(out_channels_per_sdata) << CHANNEL_NUM_SFT;
526*4882a593Smuzhiyun 	tdm_con |= get_tdm_channel_bck(format) << CHANNEL_BCK_CYCLES_SFT;
527*4882a593Smuzhiyun 	regmap_write(afe->regmap, AFE_TDM_CON1, tdm_con);
528*4882a593Smuzhiyun 
529*4882a593Smuzhiyun 	if (out_channels_per_sdata == 2) {
530*4882a593Smuzhiyun 		switch (channels) {
531*4882a593Smuzhiyun 		case 1:
532*4882a593Smuzhiyun 		case 2:
533*4882a593Smuzhiyun 			tdm_con = TDM_CH_START_O30_O31 << ST_CH_PAIR_SOUT0_SFT;
534*4882a593Smuzhiyun 			tdm_con |= TDM_CH_ZERO << ST_CH_PAIR_SOUT1_SFT;
535*4882a593Smuzhiyun 			tdm_con |= TDM_CH_ZERO << ST_CH_PAIR_SOUT2_SFT;
536*4882a593Smuzhiyun 			tdm_con |= TDM_CH_ZERO << ST_CH_PAIR_SOUT3_SFT;
537*4882a593Smuzhiyun 			break;
538*4882a593Smuzhiyun 		case 3:
539*4882a593Smuzhiyun 		case 4:
540*4882a593Smuzhiyun 			tdm_con = TDM_CH_START_O30_O31 << ST_CH_PAIR_SOUT0_SFT;
541*4882a593Smuzhiyun 			tdm_con |= TDM_CH_START_O32_O33 << ST_CH_PAIR_SOUT1_SFT;
542*4882a593Smuzhiyun 			tdm_con |= TDM_CH_ZERO << ST_CH_PAIR_SOUT2_SFT;
543*4882a593Smuzhiyun 			tdm_con |= TDM_CH_ZERO << ST_CH_PAIR_SOUT3_SFT;
544*4882a593Smuzhiyun 			break;
545*4882a593Smuzhiyun 		case 5:
546*4882a593Smuzhiyun 		case 6:
547*4882a593Smuzhiyun 			tdm_con = TDM_CH_START_O30_O31 << ST_CH_PAIR_SOUT0_SFT;
548*4882a593Smuzhiyun 			tdm_con |= TDM_CH_START_O32_O33 << ST_CH_PAIR_SOUT1_SFT;
549*4882a593Smuzhiyun 			tdm_con |= TDM_CH_START_O34_O35 << ST_CH_PAIR_SOUT2_SFT;
550*4882a593Smuzhiyun 			tdm_con |= TDM_CH_ZERO << ST_CH_PAIR_SOUT3_SFT;
551*4882a593Smuzhiyun 			break;
552*4882a593Smuzhiyun 		case 7:
553*4882a593Smuzhiyun 		case 8:
554*4882a593Smuzhiyun 			tdm_con = TDM_CH_START_O30_O31 << ST_CH_PAIR_SOUT0_SFT;
555*4882a593Smuzhiyun 			tdm_con |= TDM_CH_START_O32_O33 << ST_CH_PAIR_SOUT1_SFT;
556*4882a593Smuzhiyun 			tdm_con |= TDM_CH_START_O34_O35 << ST_CH_PAIR_SOUT2_SFT;
557*4882a593Smuzhiyun 			tdm_con |= TDM_CH_START_O36_O37 << ST_CH_PAIR_SOUT3_SFT;
558*4882a593Smuzhiyun 			break;
559*4882a593Smuzhiyun 		default:
560*4882a593Smuzhiyun 			tdm_con = 0;
561*4882a593Smuzhiyun 		}
562*4882a593Smuzhiyun 	} else {
563*4882a593Smuzhiyun 		tdm_con = TDM_CH_START_O30_O31 << ST_CH_PAIR_SOUT0_SFT;
564*4882a593Smuzhiyun 		tdm_con |= TDM_CH_ZERO << ST_CH_PAIR_SOUT1_SFT;
565*4882a593Smuzhiyun 		tdm_con |= TDM_CH_ZERO << ST_CH_PAIR_SOUT2_SFT;
566*4882a593Smuzhiyun 		tdm_con |= TDM_CH_ZERO << ST_CH_PAIR_SOUT3_SFT;
567*4882a593Smuzhiyun 	}
568*4882a593Smuzhiyun 
569*4882a593Smuzhiyun 	regmap_write(afe->regmap, AFE_TDM_CON2, tdm_con);
570*4882a593Smuzhiyun 
571*4882a593Smuzhiyun 	regmap_update_bits(afe->regmap, AFE_HDMI_OUT_CON0,
572*4882a593Smuzhiyun 			   AFE_HDMI_OUT_CH_NUM_MASK_SFT,
573*4882a593Smuzhiyun 			   channels << AFE_HDMI_OUT_CH_NUM_SFT);
574*4882a593Smuzhiyun 
575*4882a593Smuzhiyun 	regmap_update_bits(afe->regmap, AFE_HDMI_OUT_CON0,
576*4882a593Smuzhiyun 			   AFE_HDMI_OUT_BIT_WIDTH_MASK_SFT,
577*4882a593Smuzhiyun 			   get_hdmi_wlen(format) << AFE_HDMI_OUT_BIT_WIDTH_SFT);
578*4882a593Smuzhiyun 	return 0;
579*4882a593Smuzhiyun }
580*4882a593Smuzhiyun 
mtk_dai_tdm_trigger(struct snd_pcm_substream * substream,int cmd,struct snd_soc_dai * dai)581*4882a593Smuzhiyun static int mtk_dai_tdm_trigger(struct snd_pcm_substream *substream,
582*4882a593Smuzhiyun 			       int cmd,
583*4882a593Smuzhiyun 			       struct snd_soc_dai *dai)
584*4882a593Smuzhiyun {
585*4882a593Smuzhiyun 	struct mtk_base_afe *afe = snd_soc_dai_get_drvdata(dai);
586*4882a593Smuzhiyun 
587*4882a593Smuzhiyun 	switch (cmd) {
588*4882a593Smuzhiyun 	case SNDRV_PCM_TRIGGER_START:
589*4882a593Smuzhiyun 	case SNDRV_PCM_TRIGGER_RESUME:
590*4882a593Smuzhiyun 		/* enable Out control */
591*4882a593Smuzhiyun 		regmap_update_bits(afe->regmap, AFE_HDMI_OUT_CON0,
592*4882a593Smuzhiyun 				   AFE_HDMI_OUT_ON_MASK_SFT,
593*4882a593Smuzhiyun 				   0x1 << AFE_HDMI_OUT_ON_SFT);
594*4882a593Smuzhiyun 		/* enable tdm */
595*4882a593Smuzhiyun 		regmap_update_bits(afe->regmap, AFE_TDM_CON1,
596*4882a593Smuzhiyun 				   TDM_EN_MASK_SFT, 0x1 << TDM_EN_SFT);
597*4882a593Smuzhiyun 		break;
598*4882a593Smuzhiyun 	case SNDRV_PCM_TRIGGER_STOP:
599*4882a593Smuzhiyun 	case SNDRV_PCM_TRIGGER_SUSPEND:
600*4882a593Smuzhiyun 		/* disable tdm */
601*4882a593Smuzhiyun 		regmap_update_bits(afe->regmap, AFE_TDM_CON1,
602*4882a593Smuzhiyun 				   TDM_EN_MASK_SFT, 0);
603*4882a593Smuzhiyun 		/* disable Out control */
604*4882a593Smuzhiyun 		regmap_update_bits(afe->regmap, AFE_HDMI_OUT_CON0,
605*4882a593Smuzhiyun 				   AFE_HDMI_OUT_ON_MASK_SFT,
606*4882a593Smuzhiyun 				   0);
607*4882a593Smuzhiyun 		break;
608*4882a593Smuzhiyun 	default:
609*4882a593Smuzhiyun 		return -EINVAL;
610*4882a593Smuzhiyun 	}
611*4882a593Smuzhiyun 
612*4882a593Smuzhiyun 	return 0;
613*4882a593Smuzhiyun }
614*4882a593Smuzhiyun 
mtk_dai_tdm_set_sysclk(struct snd_soc_dai * dai,int clk_id,unsigned int freq,int dir)615*4882a593Smuzhiyun static int mtk_dai_tdm_set_sysclk(struct snd_soc_dai *dai,
616*4882a593Smuzhiyun 				  int clk_id, unsigned int freq, int dir)
617*4882a593Smuzhiyun {
618*4882a593Smuzhiyun 	struct mtk_base_afe *afe = dev_get_drvdata(dai->dev);
619*4882a593Smuzhiyun 	struct mt8183_afe_private *afe_priv = afe->platform_priv;
620*4882a593Smuzhiyun 	struct mtk_afe_tdm_priv *tdm_priv = afe_priv->dai_priv[dai->id];
621*4882a593Smuzhiyun 
622*4882a593Smuzhiyun 	if (!tdm_priv) {
623*4882a593Smuzhiyun 		dev_warn(afe->dev, "%s(), tdm_priv == NULL", __func__);
624*4882a593Smuzhiyun 		return -EINVAL;
625*4882a593Smuzhiyun 	}
626*4882a593Smuzhiyun 
627*4882a593Smuzhiyun 	if (dir != SND_SOC_CLOCK_OUT) {
628*4882a593Smuzhiyun 		dev_warn(afe->dev, "%s(), dir != SND_SOC_CLOCK_OUT", __func__);
629*4882a593Smuzhiyun 		return -EINVAL;
630*4882a593Smuzhiyun 	}
631*4882a593Smuzhiyun 
632*4882a593Smuzhiyun 	dev_info(afe->dev, "%s(), freq %d\n", __func__, freq);
633*4882a593Smuzhiyun 
634*4882a593Smuzhiyun 	return mtk_dai_tdm_cal_mclk(afe, tdm_priv, freq);
635*4882a593Smuzhiyun }
636*4882a593Smuzhiyun 
mtk_dai_tdm_set_fmt(struct snd_soc_dai * dai,unsigned int fmt)637*4882a593Smuzhiyun static int mtk_dai_tdm_set_fmt(struct snd_soc_dai *dai, unsigned int fmt)
638*4882a593Smuzhiyun {
639*4882a593Smuzhiyun 	struct mtk_base_afe *afe = dev_get_drvdata(dai->dev);
640*4882a593Smuzhiyun 	struct mt8183_afe_private *afe_priv = afe->platform_priv;
641*4882a593Smuzhiyun 	struct mtk_afe_tdm_priv *tdm_priv = afe_priv->dai_priv[dai->id];
642*4882a593Smuzhiyun 
643*4882a593Smuzhiyun 	if (!tdm_priv) {
644*4882a593Smuzhiyun 		dev_warn(afe->dev, "%s(), tdm_priv == NULL", __func__);
645*4882a593Smuzhiyun 		return -EINVAL;
646*4882a593Smuzhiyun 	}
647*4882a593Smuzhiyun 
648*4882a593Smuzhiyun 	/* DAI mode*/
649*4882a593Smuzhiyun 	switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
650*4882a593Smuzhiyun 	case SND_SOC_DAIFMT_I2S:
651*4882a593Smuzhiyun 		tdm_priv->tdm_out_mode = TDM_OUT_I2S;
652*4882a593Smuzhiyun 		break;
653*4882a593Smuzhiyun 	case SND_SOC_DAIFMT_DSP_A:
654*4882a593Smuzhiyun 		tdm_priv->tdm_out_mode = TDM_OUT_TDM;
655*4882a593Smuzhiyun 		break;
656*4882a593Smuzhiyun 	default:
657*4882a593Smuzhiyun 		tdm_priv->tdm_out_mode = TDM_OUT_I2S;
658*4882a593Smuzhiyun 	}
659*4882a593Smuzhiyun 
660*4882a593Smuzhiyun 	/* DAI clock inversion*/
661*4882a593Smuzhiyun 	switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
662*4882a593Smuzhiyun 	case SND_SOC_DAIFMT_NB_NF:
663*4882a593Smuzhiyun 		tdm_priv->bck_invert = TDM_BCK_NON_INV;
664*4882a593Smuzhiyun 		tdm_priv->lck_invert = TDM_LCK_NON_INV;
665*4882a593Smuzhiyun 		break;
666*4882a593Smuzhiyun 	case SND_SOC_DAIFMT_NB_IF:
667*4882a593Smuzhiyun 		tdm_priv->bck_invert = TDM_BCK_NON_INV;
668*4882a593Smuzhiyun 		tdm_priv->lck_invert = TDM_LCK_INV;
669*4882a593Smuzhiyun 		break;
670*4882a593Smuzhiyun 	case SND_SOC_DAIFMT_IB_NF:
671*4882a593Smuzhiyun 		tdm_priv->bck_invert = TDM_BCK_INV;
672*4882a593Smuzhiyun 		tdm_priv->lck_invert = TDM_LCK_NON_INV;
673*4882a593Smuzhiyun 		break;
674*4882a593Smuzhiyun 	case SND_SOC_DAIFMT_IB_IF:
675*4882a593Smuzhiyun 	default:
676*4882a593Smuzhiyun 		tdm_priv->bck_invert = TDM_BCK_INV;
677*4882a593Smuzhiyun 		tdm_priv->lck_invert = TDM_LCK_INV;
678*4882a593Smuzhiyun 		break;
679*4882a593Smuzhiyun 	}
680*4882a593Smuzhiyun 
681*4882a593Smuzhiyun 	return 0;
682*4882a593Smuzhiyun }
683*4882a593Smuzhiyun 
684*4882a593Smuzhiyun static const struct snd_soc_dai_ops mtk_dai_tdm_ops = {
685*4882a593Smuzhiyun 	.hw_params = mtk_dai_tdm_hw_params,
686*4882a593Smuzhiyun 	.trigger = mtk_dai_tdm_trigger,
687*4882a593Smuzhiyun 	.set_sysclk = mtk_dai_tdm_set_sysclk,
688*4882a593Smuzhiyun 	.set_fmt = mtk_dai_tdm_set_fmt,
689*4882a593Smuzhiyun };
690*4882a593Smuzhiyun 
691*4882a593Smuzhiyun /* dai driver */
692*4882a593Smuzhiyun #define MTK_TDM_RATES (SNDRV_PCM_RATE_8000_48000 |\
693*4882a593Smuzhiyun 		       SNDRV_PCM_RATE_88200 |\
694*4882a593Smuzhiyun 		       SNDRV_PCM_RATE_96000 |\
695*4882a593Smuzhiyun 		       SNDRV_PCM_RATE_176400 |\
696*4882a593Smuzhiyun 		       SNDRV_PCM_RATE_192000)
697*4882a593Smuzhiyun 
698*4882a593Smuzhiyun #define MTK_TDM_FORMATS (SNDRV_PCM_FMTBIT_S16_LE |\
699*4882a593Smuzhiyun 			 SNDRV_PCM_FMTBIT_S24_LE |\
700*4882a593Smuzhiyun 			 SNDRV_PCM_FMTBIT_S32_LE)
701*4882a593Smuzhiyun 
702*4882a593Smuzhiyun static struct snd_soc_dai_driver mtk_dai_tdm_driver[] = {
703*4882a593Smuzhiyun 	{
704*4882a593Smuzhiyun 		.name = "TDM",
705*4882a593Smuzhiyun 		.id = MT8183_DAI_TDM,
706*4882a593Smuzhiyun 		.playback = {
707*4882a593Smuzhiyun 			.stream_name = "TDM",
708*4882a593Smuzhiyun 			.channels_min = 2,
709*4882a593Smuzhiyun 			.channels_max = 8,
710*4882a593Smuzhiyun 			.rates = MTK_TDM_RATES,
711*4882a593Smuzhiyun 			.formats = MTK_TDM_FORMATS,
712*4882a593Smuzhiyun 		},
713*4882a593Smuzhiyun 		.ops = &mtk_dai_tdm_ops,
714*4882a593Smuzhiyun 	},
715*4882a593Smuzhiyun };
716*4882a593Smuzhiyun 
mt8183_dai_tdm_register(struct mtk_base_afe * afe)717*4882a593Smuzhiyun int mt8183_dai_tdm_register(struct mtk_base_afe *afe)
718*4882a593Smuzhiyun {
719*4882a593Smuzhiyun 	struct mt8183_afe_private *afe_priv = afe->platform_priv;
720*4882a593Smuzhiyun 	struct mtk_afe_tdm_priv *tdm_priv;
721*4882a593Smuzhiyun 	struct mtk_base_afe_dai *dai;
722*4882a593Smuzhiyun 
723*4882a593Smuzhiyun 	dai = devm_kzalloc(afe->dev, sizeof(*dai), GFP_KERNEL);
724*4882a593Smuzhiyun 	if (!dai)
725*4882a593Smuzhiyun 		return -ENOMEM;
726*4882a593Smuzhiyun 
727*4882a593Smuzhiyun 	list_add(&dai->list, &afe->sub_dais);
728*4882a593Smuzhiyun 
729*4882a593Smuzhiyun 	dai->dai_drivers = mtk_dai_tdm_driver;
730*4882a593Smuzhiyun 	dai->num_dai_drivers = ARRAY_SIZE(mtk_dai_tdm_driver);
731*4882a593Smuzhiyun 
732*4882a593Smuzhiyun 	dai->dapm_widgets = mtk_dai_tdm_widgets;
733*4882a593Smuzhiyun 	dai->num_dapm_widgets = ARRAY_SIZE(mtk_dai_tdm_widgets);
734*4882a593Smuzhiyun 	dai->dapm_routes = mtk_dai_tdm_routes;
735*4882a593Smuzhiyun 	dai->num_dapm_routes = ARRAY_SIZE(mtk_dai_tdm_routes);
736*4882a593Smuzhiyun 
737*4882a593Smuzhiyun 	tdm_priv = devm_kzalloc(afe->dev, sizeof(struct mtk_afe_tdm_priv),
738*4882a593Smuzhiyun 				GFP_KERNEL);
739*4882a593Smuzhiyun 	if (!tdm_priv)
740*4882a593Smuzhiyun 		return -ENOMEM;
741*4882a593Smuzhiyun 
742*4882a593Smuzhiyun 	tdm_priv->mclk_multiple = 128;
743*4882a593Smuzhiyun 	tdm_priv->bck_id = MT8183_I2S4_BCK;
744*4882a593Smuzhiyun 	tdm_priv->mclk_id = MT8183_I2S4_MCK;
745*4882a593Smuzhiyun 
746*4882a593Smuzhiyun 	afe_priv->dai_priv[MT8183_DAI_TDM] = tdm_priv;
747*4882a593Smuzhiyun 	return 0;
748*4882a593Smuzhiyun }
749