1*9f8df795SMaso Huang // SPDX-License-Identifier: GPL-2.0
2*9f8df795SMaso Huang /*
3*9f8df795SMaso Huang  * MediaTek ALSA SoC Audio DAI eTDM Control
4*9f8df795SMaso Huang  *
5*9f8df795SMaso Huang  * Copyright (c) 2023 MediaTek Inc.
6*9f8df795SMaso Huang  * Authors: Vic Wu <vic.wu@mediatek.com>
7*9f8df795SMaso Huang  *          Maso Huang <maso.huang@mediatek.com>
8*9f8df795SMaso Huang  */
9*9f8df795SMaso Huang 
10*9f8df795SMaso Huang #include <linux/bitfield.h>
11*9f8df795SMaso Huang #include <linux/bitops.h>
12*9f8df795SMaso Huang #include <linux/regmap.h>
13*9f8df795SMaso Huang #include <sound/pcm_params.h>
14*9f8df795SMaso Huang #include "mt7986-afe-common.h"
15*9f8df795SMaso Huang #include "mt7986-reg.h"
16*9f8df795SMaso Huang 
17*9f8df795SMaso Huang #define HOPPING_CLK  0
18*9f8df795SMaso Huang #define APLL_CLK     1
19*9f8df795SMaso Huang #define MTK_DAI_ETDM_FORMAT_I2S   0
20*9f8df795SMaso Huang #define MTK_DAI_ETDM_FORMAT_DSPA  4
21*9f8df795SMaso Huang #define MTK_DAI_ETDM_FORMAT_DSPB  5
22*9f8df795SMaso Huang 
23*9f8df795SMaso Huang enum {
24*9f8df795SMaso Huang 	MTK_ETDM_RATE_8K = 0,
25*9f8df795SMaso Huang 	MTK_ETDM_RATE_12K = 1,
26*9f8df795SMaso Huang 	MTK_ETDM_RATE_16K = 2,
27*9f8df795SMaso Huang 	MTK_ETDM_RATE_24K = 3,
28*9f8df795SMaso Huang 	MTK_ETDM_RATE_32K = 4,
29*9f8df795SMaso Huang 	MTK_ETDM_RATE_48K = 5,
30*9f8df795SMaso Huang 	MTK_ETDM_RATE_96K = 7,
31*9f8df795SMaso Huang 	MTK_ETDM_RATE_192K = 9,
32*9f8df795SMaso Huang 	MTK_ETDM_RATE_11K = 16,
33*9f8df795SMaso Huang 	MTK_ETDM_RATE_22K = 17,
34*9f8df795SMaso Huang 	MTK_ETDM_RATE_44K = 18,
35*9f8df795SMaso Huang 	MTK_ETDM_RATE_88K = 19,
36*9f8df795SMaso Huang 	MTK_ETDM_RATE_176K = 20,
37*9f8df795SMaso Huang };
38*9f8df795SMaso Huang 
39*9f8df795SMaso Huang struct mtk_dai_etdm_priv {
40*9f8df795SMaso Huang 	bool bck_inv;
41*9f8df795SMaso Huang 	bool lrck_inv;
42*9f8df795SMaso Huang 	bool slave_mode;
43*9f8df795SMaso Huang 	unsigned int format;
44*9f8df795SMaso Huang };
45*9f8df795SMaso Huang 
mt7986_etdm_rate_transform(struct device * dev,unsigned int rate)46*9f8df795SMaso Huang static unsigned int mt7986_etdm_rate_transform(struct device *dev, unsigned int rate)
47*9f8df795SMaso Huang {
48*9f8df795SMaso Huang 	switch (rate) {
49*9f8df795SMaso Huang 	case 8000:
50*9f8df795SMaso Huang 		return MTK_ETDM_RATE_8K;
51*9f8df795SMaso Huang 	case 11025:
52*9f8df795SMaso Huang 		return MTK_ETDM_RATE_11K;
53*9f8df795SMaso Huang 	case 12000:
54*9f8df795SMaso Huang 		return MTK_ETDM_RATE_12K;
55*9f8df795SMaso Huang 	case 16000:
56*9f8df795SMaso Huang 		return MTK_ETDM_RATE_16K;
57*9f8df795SMaso Huang 	case 22050:
58*9f8df795SMaso Huang 		return MTK_ETDM_RATE_22K;
59*9f8df795SMaso Huang 	case 24000:
60*9f8df795SMaso Huang 		return MTK_ETDM_RATE_24K;
61*9f8df795SMaso Huang 	case 32000:
62*9f8df795SMaso Huang 		return MTK_ETDM_RATE_32K;
63*9f8df795SMaso Huang 	case 44100:
64*9f8df795SMaso Huang 		return MTK_ETDM_RATE_44K;
65*9f8df795SMaso Huang 	case 48000:
66*9f8df795SMaso Huang 		return MTK_ETDM_RATE_48K;
67*9f8df795SMaso Huang 	case 88200:
68*9f8df795SMaso Huang 		return MTK_ETDM_RATE_88K;
69*9f8df795SMaso Huang 	case 96000:
70*9f8df795SMaso Huang 		return MTK_ETDM_RATE_96K;
71*9f8df795SMaso Huang 	case 176400:
72*9f8df795SMaso Huang 		return MTK_ETDM_RATE_176K;
73*9f8df795SMaso Huang 	case 192000:
74*9f8df795SMaso Huang 		return MTK_ETDM_RATE_192K;
75*9f8df795SMaso Huang 	default:
76*9f8df795SMaso Huang 		dev_warn(dev, "%s(), rate %u invalid, using %d!!!\n",
77*9f8df795SMaso Huang 			 __func__, rate, MTK_ETDM_RATE_48K);
78*9f8df795SMaso Huang 		return MTK_ETDM_RATE_48K;
79*9f8df795SMaso Huang 	}
80*9f8df795SMaso Huang }
81*9f8df795SMaso Huang 
get_etdm_wlen(unsigned int bitwidth)82*9f8df795SMaso Huang static int get_etdm_wlen(unsigned int bitwidth)
83*9f8df795SMaso Huang {
84*9f8df795SMaso Huang 	return bitwidth <= 16 ? 16 : 32;
85*9f8df795SMaso Huang }
86*9f8df795SMaso Huang 
87*9f8df795SMaso Huang /* dai component */
88*9f8df795SMaso Huang /* interconnection */
89*9f8df795SMaso Huang 
90*9f8df795SMaso Huang static const struct snd_kcontrol_new o124_mix[] = {
91*9f8df795SMaso Huang 	SOC_DAPM_SINGLE_AUTODISABLE("I032_Switch", AFE_CONN124_1, 0, 1, 0),
92*9f8df795SMaso Huang };
93*9f8df795SMaso Huang 
94*9f8df795SMaso Huang static const struct snd_kcontrol_new o125_mix[] = {
95*9f8df795SMaso Huang 	SOC_DAPM_SINGLE_AUTODISABLE("I033_Switch", AFE_CONN125_1, 1, 1, 0),
96*9f8df795SMaso Huang };
97*9f8df795SMaso Huang 
98*9f8df795SMaso Huang static const struct snd_soc_dapm_widget mtk_dai_etdm_widgets[] = {
99*9f8df795SMaso Huang 
100*9f8df795SMaso Huang 	/* DL */
101*9f8df795SMaso Huang 	SND_SOC_DAPM_MIXER("I150", SND_SOC_NOPM, 0, 0, NULL, 0),
102*9f8df795SMaso Huang 	SND_SOC_DAPM_MIXER("I151", SND_SOC_NOPM, 0, 0, NULL, 0),
103*9f8df795SMaso Huang 	/* UL */
104*9f8df795SMaso Huang 	SND_SOC_DAPM_MIXER("O124", SND_SOC_NOPM, 0, 0, o124_mix, ARRAY_SIZE(o124_mix)),
105*9f8df795SMaso Huang 	SND_SOC_DAPM_MIXER("O125", SND_SOC_NOPM, 0, 0, o125_mix, ARRAY_SIZE(o125_mix)),
106*9f8df795SMaso Huang };
107*9f8df795SMaso Huang 
108*9f8df795SMaso Huang static const struct snd_soc_dapm_route mtk_dai_etdm_routes[] = {
109*9f8df795SMaso Huang 	{"I150", NULL, "ETDM Capture"},
110*9f8df795SMaso Huang 	{"I151", NULL, "ETDM Capture"},
111*9f8df795SMaso Huang 	{"ETDM Playback", NULL, "O124"},
112*9f8df795SMaso Huang 	{"ETDM Playback", NULL, "O125"},
113*9f8df795SMaso Huang 	{"O124", "I032_Switch", "I032"},
114*9f8df795SMaso Huang 	{"O125", "I033_Switch", "I033"},
115*9f8df795SMaso Huang };
116*9f8df795SMaso Huang 
117*9f8df795SMaso Huang /* dai ops */
mtk_dai_etdm_startup(struct snd_pcm_substream * substream,struct snd_soc_dai * dai)118*9f8df795SMaso Huang static int mtk_dai_etdm_startup(struct snd_pcm_substream *substream,
119*9f8df795SMaso Huang 				struct snd_soc_dai *dai)
120*9f8df795SMaso Huang {
121*9f8df795SMaso Huang 	struct mtk_base_afe *afe = snd_soc_dai_get_drvdata(dai);
122*9f8df795SMaso Huang 	struct mt7986_afe_private *afe_priv = afe->platform_priv;
123*9f8df795SMaso Huang 	int ret;
124*9f8df795SMaso Huang 
125*9f8df795SMaso Huang 	ret = clk_bulk_prepare_enable(afe_priv->num_clks, afe_priv->clks);
126*9f8df795SMaso Huang 	if (ret)
127*9f8df795SMaso Huang 		return dev_err_probe(afe->dev, ret, "Failed to enable clocks\n");
128*9f8df795SMaso Huang 
129*9f8df795SMaso Huang 	regmap_update_bits(afe->regmap, AUDIO_TOP_CON2, CLK_OUT5_PDN_MASK, 0);
130*9f8df795SMaso Huang 	regmap_update_bits(afe->regmap, AUDIO_TOP_CON2, CLK_IN5_PDN_MASK, 0);
131*9f8df795SMaso Huang 
132*9f8df795SMaso Huang 	return 0;
133*9f8df795SMaso Huang }
134*9f8df795SMaso Huang 
mtk_dai_etdm_shutdown(struct snd_pcm_substream * substream,struct snd_soc_dai * dai)135*9f8df795SMaso Huang static void mtk_dai_etdm_shutdown(struct snd_pcm_substream *substream,
136*9f8df795SMaso Huang 				  struct snd_soc_dai *dai)
137*9f8df795SMaso Huang {
138*9f8df795SMaso Huang 	struct mtk_base_afe *afe = snd_soc_dai_get_drvdata(dai);
139*9f8df795SMaso Huang 	struct mt7986_afe_private *afe_priv = afe->platform_priv;
140*9f8df795SMaso Huang 
141*9f8df795SMaso Huang 	regmap_update_bits(afe->regmap, AUDIO_TOP_CON2, CLK_OUT5_PDN_MASK,
142*9f8df795SMaso Huang 			   CLK_OUT5_PDN);
143*9f8df795SMaso Huang 	regmap_update_bits(afe->regmap, AUDIO_TOP_CON2, CLK_IN5_PDN_MASK,
144*9f8df795SMaso Huang 			   CLK_IN5_PDN);
145*9f8df795SMaso Huang 
146*9f8df795SMaso Huang 	clk_bulk_disable_unprepare(afe_priv->num_clks, afe_priv->clks);
147*9f8df795SMaso Huang }
148*9f8df795SMaso Huang 
get_etdm_ch_fixup(unsigned int channels)149*9f8df795SMaso Huang static unsigned int get_etdm_ch_fixup(unsigned int channels)
150*9f8df795SMaso Huang {
151*9f8df795SMaso Huang 	if (channels > 16)
152*9f8df795SMaso Huang 		return 24;
153*9f8df795SMaso Huang 	else if (channels > 8)
154*9f8df795SMaso Huang 		return 16;
155*9f8df795SMaso Huang 	else if (channels > 4)
156*9f8df795SMaso Huang 		return 8;
157*9f8df795SMaso Huang 	else if (channels > 2)
158*9f8df795SMaso Huang 		return 4;
159*9f8df795SMaso Huang 	else
160*9f8df795SMaso Huang 		return 2;
161*9f8df795SMaso Huang }
162*9f8df795SMaso Huang 
mtk_dai_etdm_config(struct mtk_base_afe * afe,struct snd_pcm_hw_params * params,struct snd_soc_dai * dai,int stream)163*9f8df795SMaso Huang static int mtk_dai_etdm_config(struct mtk_base_afe *afe,
164*9f8df795SMaso Huang 			       struct snd_pcm_hw_params *params,
165*9f8df795SMaso Huang 			       struct snd_soc_dai *dai,
166*9f8df795SMaso Huang 			       int stream)
167*9f8df795SMaso Huang {
168*9f8df795SMaso Huang 	struct mt7986_afe_private *afe_priv = afe->platform_priv;
169*9f8df795SMaso Huang 	struct mtk_dai_etdm_priv *etdm_data = afe_priv->dai_priv[dai->id];
170*9f8df795SMaso Huang 	unsigned int rate = params_rate(params);
171*9f8df795SMaso Huang 	unsigned int etdm_rate = mt7986_etdm_rate_transform(afe->dev, rate);
172*9f8df795SMaso Huang 	unsigned int afe_rate = mt7986_afe_rate_transform(afe->dev, rate);
173*9f8df795SMaso Huang 	unsigned int channels = params_channels(params);
174*9f8df795SMaso Huang 	unsigned int bit_width = params_width(params);
175*9f8df795SMaso Huang 	unsigned int wlen = get_etdm_wlen(bit_width);
176*9f8df795SMaso Huang 	unsigned int val = 0;
177*9f8df795SMaso Huang 	unsigned int mask = 0;
178*9f8df795SMaso Huang 
179*9f8df795SMaso Huang 	dev_dbg(afe->dev, "%s(), stream %d, rate %u, bitwidth %u\n",
180*9f8df795SMaso Huang 		 __func__, stream, rate, bit_width);
181*9f8df795SMaso Huang 
182*9f8df795SMaso Huang 	/* CON0 */
183*9f8df795SMaso Huang 	mask |= ETDM_BIT_LEN_MASK;
184*9f8df795SMaso Huang 	val |= FIELD_PREP(ETDM_BIT_LEN_MASK, bit_width - 1);
185*9f8df795SMaso Huang 	mask |= ETDM_WRD_LEN_MASK;
186*9f8df795SMaso Huang 	val |= FIELD_PREP(ETDM_WRD_LEN_MASK, wlen - 1);
187*9f8df795SMaso Huang 	mask |= ETDM_FMT_MASK;
188*9f8df795SMaso Huang 	val |= FIELD_PREP(ETDM_FMT_MASK, etdm_data->format);
189*9f8df795SMaso Huang 	mask |= ETDM_CH_NUM_MASK;
190*9f8df795SMaso Huang 	val |= FIELD_PREP(ETDM_CH_NUM_MASK, get_etdm_ch_fixup(channels) - 1);
191*9f8df795SMaso Huang 	mask |= RELATCH_SRC_MASK;
192*9f8df795SMaso Huang 	val |= FIELD_PREP(RELATCH_SRC_MASK, APLL_CLK);
193*9f8df795SMaso Huang 
194*9f8df795SMaso Huang 	switch (stream) {
195*9f8df795SMaso Huang 	case SNDRV_PCM_STREAM_PLAYBACK:
196*9f8df795SMaso Huang 		/* set ETDM_OUT5_CON0 */
197*9f8df795SMaso Huang 		regmap_update_bits(afe->regmap, ETDM_OUT5_CON0, mask, val);
198*9f8df795SMaso Huang 
199*9f8df795SMaso Huang 		/* set ETDM_OUT5_CON4 */
200*9f8df795SMaso Huang 		regmap_update_bits(afe->regmap, ETDM_OUT5_CON4,
201*9f8df795SMaso Huang 				   OUT_RELATCH_MASK, OUT_RELATCH(afe_rate));
202*9f8df795SMaso Huang 		regmap_update_bits(afe->regmap, ETDM_OUT5_CON4,
203*9f8df795SMaso Huang 				   OUT_CLK_SRC_MASK, OUT_CLK_SRC(APLL_CLK));
204*9f8df795SMaso Huang 		regmap_update_bits(afe->regmap, ETDM_OUT5_CON4,
205*9f8df795SMaso Huang 				   OUT_SEL_FS_MASK, OUT_SEL_FS(etdm_rate));
206*9f8df795SMaso Huang 
207*9f8df795SMaso Huang 		/* set ETDM_OUT5_CON5 */
208*9f8df795SMaso Huang 		regmap_update_bits(afe->regmap, ETDM_OUT5_CON5,
209*9f8df795SMaso Huang 				   ETDM_CLK_DIV_MASK, ETDM_CLK_DIV);
210*9f8df795SMaso Huang 		break;
211*9f8df795SMaso Huang 	case SNDRV_PCM_STREAM_CAPTURE:
212*9f8df795SMaso Huang 		/* set ETDM_IN5_CON0 */
213*9f8df795SMaso Huang 		regmap_update_bits(afe->regmap, ETDM_IN5_CON0, mask, val);
214*9f8df795SMaso Huang 		regmap_update_bits(afe->regmap, ETDM_IN5_CON0,
215*9f8df795SMaso Huang 				   ETDM_SYNC_MASK, ETDM_SYNC);
216*9f8df795SMaso Huang 
217*9f8df795SMaso Huang 		/* set ETDM_IN5_CON2 */
218*9f8df795SMaso Huang 		regmap_update_bits(afe->regmap, ETDM_IN5_CON2,
219*9f8df795SMaso Huang 				   IN_CLK_SRC_MASK, IN_CLK_SRC(APLL_CLK));
220*9f8df795SMaso Huang 
221*9f8df795SMaso Huang 		/* set ETDM_IN5_CON3 */
222*9f8df795SMaso Huang 		regmap_update_bits(afe->regmap, ETDM_IN5_CON3,
223*9f8df795SMaso Huang 				   IN_SEL_FS_MASK, IN_SEL_FS(etdm_rate));
224*9f8df795SMaso Huang 
225*9f8df795SMaso Huang 		/* set ETDM_IN5_CON4 */
226*9f8df795SMaso Huang 		regmap_update_bits(afe->regmap, ETDM_IN5_CON4,
227*9f8df795SMaso Huang 				   IN_RELATCH_MASK, IN_RELATCH(afe_rate));
228*9f8df795SMaso Huang 		break;
229*9f8df795SMaso Huang 	default:
230*9f8df795SMaso Huang 		break;
231*9f8df795SMaso Huang 	}
232*9f8df795SMaso Huang 
233*9f8df795SMaso Huang 	return 0;
234*9f8df795SMaso Huang }
235*9f8df795SMaso Huang 
mtk_dai_etdm_hw_params(struct snd_pcm_substream * substream,struct snd_pcm_hw_params * params,struct snd_soc_dai * dai)236*9f8df795SMaso Huang static int mtk_dai_etdm_hw_params(struct snd_pcm_substream *substream,
237*9f8df795SMaso Huang 				  struct snd_pcm_hw_params *params,
238*9f8df795SMaso Huang 				  struct snd_soc_dai *dai)
239*9f8df795SMaso Huang {
240*9f8df795SMaso Huang 	struct mtk_base_afe *afe = snd_soc_dai_get_drvdata(dai);
241*9f8df795SMaso Huang 
242*9f8df795SMaso Huang 	mtk_dai_etdm_config(afe, params, dai, SNDRV_PCM_STREAM_PLAYBACK);
243*9f8df795SMaso Huang 	mtk_dai_etdm_config(afe, params, dai, SNDRV_PCM_STREAM_CAPTURE);
244*9f8df795SMaso Huang 
245*9f8df795SMaso Huang 	return 0;
246*9f8df795SMaso Huang }
247*9f8df795SMaso Huang 
mtk_dai_etdm_trigger(struct snd_pcm_substream * substream,int cmd,struct snd_soc_dai * dai)248*9f8df795SMaso Huang static int mtk_dai_etdm_trigger(struct snd_pcm_substream *substream, int cmd,
249*9f8df795SMaso Huang 				struct snd_soc_dai *dai)
250*9f8df795SMaso Huang {
251*9f8df795SMaso Huang 	struct mtk_base_afe *afe = snd_soc_dai_get_drvdata(dai);
252*9f8df795SMaso Huang 
253*9f8df795SMaso Huang 	dev_dbg(afe->dev, "%s(), cmd %d, dai id %d\n", __func__, cmd, dai->id);
254*9f8df795SMaso Huang 	switch (cmd) {
255*9f8df795SMaso Huang 	case SNDRV_PCM_TRIGGER_START:
256*9f8df795SMaso Huang 	case SNDRV_PCM_TRIGGER_RESUME:
257*9f8df795SMaso Huang 		regmap_update_bits(afe->regmap, ETDM_IN5_CON0, ETDM_EN_MASK,
258*9f8df795SMaso Huang 				   ETDM_EN);
259*9f8df795SMaso Huang 		regmap_update_bits(afe->regmap, ETDM_OUT5_CON0, ETDM_EN_MASK,
260*9f8df795SMaso Huang 				   ETDM_EN);
261*9f8df795SMaso Huang 		break;
262*9f8df795SMaso Huang 	case SNDRV_PCM_TRIGGER_STOP:
263*9f8df795SMaso Huang 	case SNDRV_PCM_TRIGGER_SUSPEND:
264*9f8df795SMaso Huang 		regmap_update_bits(afe->regmap, ETDM_IN5_CON0, ETDM_EN_MASK,
265*9f8df795SMaso Huang 				   0);
266*9f8df795SMaso Huang 		regmap_update_bits(afe->regmap, ETDM_OUT5_CON0, ETDM_EN_MASK,
267*9f8df795SMaso Huang 				   0);
268*9f8df795SMaso Huang 		break;
269*9f8df795SMaso Huang 	default:
270*9f8df795SMaso Huang 		break;
271*9f8df795SMaso Huang 	}
272*9f8df795SMaso Huang 
273*9f8df795SMaso Huang 	return 0;
274*9f8df795SMaso Huang }
275*9f8df795SMaso Huang 
mtk_dai_etdm_set_fmt(struct snd_soc_dai * dai,unsigned int fmt)276*9f8df795SMaso Huang static int mtk_dai_etdm_set_fmt(struct snd_soc_dai *dai, unsigned int fmt)
277*9f8df795SMaso Huang {
278*9f8df795SMaso Huang 	struct mtk_base_afe *afe = snd_soc_dai_get_drvdata(dai);
279*9f8df795SMaso Huang 	struct mt7986_afe_private *afe_priv = afe->platform_priv;
280*9f8df795SMaso Huang 	struct mtk_dai_etdm_priv *etdm_data;
281*9f8df795SMaso Huang 	void *priv_data;
282*9f8df795SMaso Huang 
283*9f8df795SMaso Huang 	switch (dai->id) {
284*9f8df795SMaso Huang 	case MT7986_DAI_ETDM:
285*9f8df795SMaso Huang 		break;
286*9f8df795SMaso Huang 	default:
287*9f8df795SMaso Huang 		dev_warn(afe->dev, "%s(), id %d not support\n",
288*9f8df795SMaso Huang 			 __func__, dai->id);
289*9f8df795SMaso Huang 		return -EINVAL;
290*9f8df795SMaso Huang 	}
291*9f8df795SMaso Huang 
292*9f8df795SMaso Huang 	priv_data = devm_kzalloc(afe->dev, sizeof(struct mtk_dai_etdm_priv),
293*9f8df795SMaso Huang 				 GFP_KERNEL);
294*9f8df795SMaso Huang 	if (!priv_data)
295*9f8df795SMaso Huang 		return -ENOMEM;
296*9f8df795SMaso Huang 
297*9f8df795SMaso Huang 	afe_priv->dai_priv[dai->id] = priv_data;
298*9f8df795SMaso Huang 	etdm_data = afe_priv->dai_priv[dai->id];
299*9f8df795SMaso Huang 
300*9f8df795SMaso Huang 	switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
301*9f8df795SMaso Huang 	case SND_SOC_DAIFMT_I2S:
302*9f8df795SMaso Huang 		etdm_data->format = MTK_DAI_ETDM_FORMAT_I2S;
303*9f8df795SMaso Huang 		break;
304*9f8df795SMaso Huang 	case SND_SOC_DAIFMT_DSP_A:
305*9f8df795SMaso Huang 		etdm_data->format = MTK_DAI_ETDM_FORMAT_DSPA;
306*9f8df795SMaso Huang 		break;
307*9f8df795SMaso Huang 	case SND_SOC_DAIFMT_DSP_B:
308*9f8df795SMaso Huang 		etdm_data->format = MTK_DAI_ETDM_FORMAT_DSPB;
309*9f8df795SMaso Huang 		break;
310*9f8df795SMaso Huang 	default:
311*9f8df795SMaso Huang 		return -EINVAL;
312*9f8df795SMaso Huang 	}
313*9f8df795SMaso Huang 
314*9f8df795SMaso Huang 	switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
315*9f8df795SMaso Huang 	case SND_SOC_DAIFMT_NB_NF:
316*9f8df795SMaso Huang 		etdm_data->bck_inv = false;
317*9f8df795SMaso Huang 		etdm_data->lrck_inv = false;
318*9f8df795SMaso Huang 		break;
319*9f8df795SMaso Huang 	case SND_SOC_DAIFMT_NB_IF:
320*9f8df795SMaso Huang 		etdm_data->bck_inv = false;
321*9f8df795SMaso Huang 		etdm_data->lrck_inv = true;
322*9f8df795SMaso Huang 		break;
323*9f8df795SMaso Huang 	case SND_SOC_DAIFMT_IB_NF:
324*9f8df795SMaso Huang 		etdm_data->bck_inv = true;
325*9f8df795SMaso Huang 		etdm_data->lrck_inv = false;
326*9f8df795SMaso Huang 		break;
327*9f8df795SMaso Huang 	case SND_SOC_DAIFMT_IB_IF:
328*9f8df795SMaso Huang 		etdm_data->bck_inv = true;
329*9f8df795SMaso Huang 		etdm_data->lrck_inv = true;
330*9f8df795SMaso Huang 		break;
331*9f8df795SMaso Huang 	default:
332*9f8df795SMaso Huang 		return -EINVAL;
333*9f8df795SMaso Huang 	}
334*9f8df795SMaso Huang 
335*9f8df795SMaso Huang 	switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
336*9f8df795SMaso Huang 	case SND_SOC_DAIFMT_CBM_CFM:
337*9f8df795SMaso Huang 		etdm_data->slave_mode = true;
338*9f8df795SMaso Huang 		break;
339*9f8df795SMaso Huang 	case SND_SOC_DAIFMT_CBS_CFS:
340*9f8df795SMaso Huang 		etdm_data->slave_mode = false;
341*9f8df795SMaso Huang 		break;
342*9f8df795SMaso Huang 	default:
343*9f8df795SMaso Huang 		return -EINVAL;
344*9f8df795SMaso Huang 	}
345*9f8df795SMaso Huang 
346*9f8df795SMaso Huang 	return 0;
347*9f8df795SMaso Huang }
348*9f8df795SMaso Huang 
349*9f8df795SMaso Huang static const struct snd_soc_dai_ops mtk_dai_etdm_ops = {
350*9f8df795SMaso Huang 	.startup = mtk_dai_etdm_startup,
351*9f8df795SMaso Huang 	.shutdown = mtk_dai_etdm_shutdown,
352*9f8df795SMaso Huang 	.hw_params = mtk_dai_etdm_hw_params,
353*9f8df795SMaso Huang 	.trigger = mtk_dai_etdm_trigger,
354*9f8df795SMaso Huang 	.set_fmt = mtk_dai_etdm_set_fmt,
355*9f8df795SMaso Huang };
356*9f8df795SMaso Huang 
357*9f8df795SMaso Huang /* dai driver */
358*9f8df795SMaso Huang #define MTK_ETDM_RATES (SNDRV_PCM_RATE_8000_48000 |\
359*9f8df795SMaso Huang 			SNDRV_PCM_RATE_88200 |\
360*9f8df795SMaso Huang 			SNDRV_PCM_RATE_96000 |\
361*9f8df795SMaso Huang 			SNDRV_PCM_RATE_176400 |\
362*9f8df795SMaso Huang 			SNDRV_PCM_RATE_192000)
363*9f8df795SMaso Huang 
364*9f8df795SMaso Huang #define MTK_ETDM_FORMATS (SNDRV_PCM_FMTBIT_S16_LE |\
365*9f8df795SMaso Huang 			  SNDRV_PCM_FMTBIT_S24_LE |\
366*9f8df795SMaso Huang 			  SNDRV_PCM_FMTBIT_S32_LE)
367*9f8df795SMaso Huang 
368*9f8df795SMaso Huang static struct snd_soc_dai_driver mtk_dai_etdm_driver[] = {
369*9f8df795SMaso Huang 	{
370*9f8df795SMaso Huang 		.name = "ETDM",
371*9f8df795SMaso Huang 		.id = MT7986_DAI_ETDM,
372*9f8df795SMaso Huang 		.capture = {
373*9f8df795SMaso Huang 			.stream_name = "ETDM Capture",
374*9f8df795SMaso Huang 			.channels_min = 1,
375*9f8df795SMaso Huang 			.channels_max = 2,
376*9f8df795SMaso Huang 			.rates = MTK_ETDM_RATES,
377*9f8df795SMaso Huang 			.formats = MTK_ETDM_FORMATS,
378*9f8df795SMaso Huang 		},
379*9f8df795SMaso Huang 		.playback = {
380*9f8df795SMaso Huang 			.stream_name = "ETDM Playback",
381*9f8df795SMaso Huang 			.channels_min = 1,
382*9f8df795SMaso Huang 			.channels_max = 2,
383*9f8df795SMaso Huang 			.rates = MTK_ETDM_RATES,
384*9f8df795SMaso Huang 			.formats = MTK_ETDM_FORMATS,
385*9f8df795SMaso Huang 		},
386*9f8df795SMaso Huang 		.ops = &mtk_dai_etdm_ops,
387*9f8df795SMaso Huang 		.symmetric_rate = 1,
388*9f8df795SMaso Huang 		.symmetric_sample_bits = 1,
389*9f8df795SMaso Huang 	},
390*9f8df795SMaso Huang };
391*9f8df795SMaso Huang 
mt7986_dai_etdm_register(struct mtk_base_afe * afe)392*9f8df795SMaso Huang int mt7986_dai_etdm_register(struct mtk_base_afe *afe)
393*9f8df795SMaso Huang {
394*9f8df795SMaso Huang 	struct mtk_base_afe_dai *dai;
395*9f8df795SMaso Huang 
396*9f8df795SMaso Huang 	dai = devm_kzalloc(afe->dev, sizeof(*dai), GFP_KERNEL);
397*9f8df795SMaso Huang 	if (!dai)
398*9f8df795SMaso Huang 		return -ENOMEM;
399*9f8df795SMaso Huang 
400*9f8df795SMaso Huang 	list_add(&dai->list, &afe->sub_dais);
401*9f8df795SMaso Huang 
402*9f8df795SMaso Huang 	dai->dai_drivers = mtk_dai_etdm_driver;
403*9f8df795SMaso Huang 	dai->num_dai_drivers = ARRAY_SIZE(mtk_dai_etdm_driver);
404*9f8df795SMaso Huang 
405*9f8df795SMaso Huang 	dai->dapm_widgets = mtk_dai_etdm_widgets;
406*9f8df795SMaso Huang 	dai->num_dapm_widgets = ARRAY_SIZE(mtk_dai_etdm_widgets);
407*9f8df795SMaso Huang 	dai->dapm_routes = mtk_dai_etdm_routes;
408*9f8df795SMaso Huang 	dai->num_dapm_routes = ARRAY_SIZE(mtk_dai_etdm_routes);
409*9f8df795SMaso Huang 
410*9f8df795SMaso Huang 	return 0;
411*9f8df795SMaso Huang }
412