xref: /openbmc/linux/sound/soc/mediatek/mt8186/mt8186-dai-src.c (revision 4f2c0a4acffbec01079c28f839422e64ddeff004)
1*e118015dSJiaxin Yu // SPDX-License-Identifier: GPL-2.0
2*e118015dSJiaxin Yu //
3*e118015dSJiaxin Yu //  MediaTek ALSA SoC Audio DAI SRC Control
4*e118015dSJiaxin Yu //
5*e118015dSJiaxin Yu // Copyright (c) 2022 MediaTek Inc.
6*e118015dSJiaxin Yu // Author: Jiaxin Yu <jiaxin.yu@mediatek.com>
7*e118015dSJiaxin Yu 
8*e118015dSJiaxin Yu #include <linux/regmap.h>
9*e118015dSJiaxin Yu #include "mt8186-afe-common.h"
10*e118015dSJiaxin Yu #include "mt8186-interconnection.h"
11*e118015dSJiaxin Yu 
12*e118015dSJiaxin Yu struct mtk_afe_src_priv {
13*e118015dSJiaxin Yu 	int dl_rate;
14*e118015dSJiaxin Yu 	int ul_rate;
15*e118015dSJiaxin Yu };
16*e118015dSJiaxin Yu 
17*e118015dSJiaxin Yu static const unsigned int src_iir_coeff_32_to_16[] = {
18*e118015dSJiaxin Yu 	0x0dbae6, 0xff9b0a, 0x0dbae6, 0x05e488, 0xe072b9, 0x000002,
19*e118015dSJiaxin Yu 	0x0dbae6, 0x000f3b, 0x0dbae6, 0x06a537, 0xe17d79, 0x000002,
20*e118015dSJiaxin Yu 	0x0dbae6, 0x01246a, 0x0dbae6, 0x087261, 0xe306be, 0x000002,
21*e118015dSJiaxin Yu 	0x0dbae6, 0x03437d, 0x0dbae6, 0x0bc16f, 0xe57c87, 0x000002,
22*e118015dSJiaxin Yu 	0x0dbae6, 0x072981, 0x0dbae6, 0x111dd3, 0xe94f2a, 0x000002,
23*e118015dSJiaxin Yu 	0x0dbae6, 0x0dc4a6, 0x0dbae6, 0x188611, 0xee85a0, 0x000002,
24*e118015dSJiaxin Yu 	0x0dbae6, 0x168b9a, 0x0dbae6, 0x200e8f, 0xf3ccf1, 0x000002,
25*e118015dSJiaxin Yu 	0x000000, 0x1b75cb, 0x1b75cb, 0x2374a2, 0x000000, 0x000001
26*e118015dSJiaxin Yu };
27*e118015dSJiaxin Yu 
28*e118015dSJiaxin Yu static const unsigned int src_iir_coeff_44_to_16[] = {
29*e118015dSJiaxin Yu 	0x09ae28, 0xf7d97d, 0x09ae28, 0x212a3d, 0xe0ac3a, 0x000002,
30*e118015dSJiaxin Yu 	0x09ae28, 0xf8525a, 0x09ae28, 0x216d72, 0xe234be, 0x000002,
31*e118015dSJiaxin Yu 	0x09ae28, 0xf980f5, 0x09ae28, 0x22a057, 0xe45a81, 0x000002,
32*e118015dSJiaxin Yu 	0x09ae28, 0xfc0a08, 0x09ae28, 0x24d3bd, 0xe7752d, 0x000002,
33*e118015dSJiaxin Yu 	0x09ae28, 0x016162, 0x09ae28, 0x27da01, 0xeb6ea8, 0x000002,
34*e118015dSJiaxin Yu 	0x09ae28, 0x0b67df, 0x09ae28, 0x2aca4a, 0xef34c4, 0x000002,
35*e118015dSJiaxin Yu 	0x000000, 0x135c50, 0x135c50, 0x2c1079, 0x000000, 0x000001
36*e118015dSJiaxin Yu };
37*e118015dSJiaxin Yu 
38*e118015dSJiaxin Yu static const unsigned int src_iir_coeff_44_to_32[] = {
39*e118015dSJiaxin Yu 	0x096966, 0x0c4d35, 0x096966, 0xedee81, 0xf05070, 0x000003,
40*e118015dSJiaxin Yu 	0x12d2cc, 0x193910, 0x12d2cc, 0xddbf4f, 0xe21e1d, 0x000002,
41*e118015dSJiaxin Yu 	0x12d2cc, 0x1a9e60, 0x12d2cc, 0xe18916, 0xe470fd, 0x000002,
42*e118015dSJiaxin Yu 	0x12d2cc, 0x1d06e0, 0x12d2cc, 0xe8a4a6, 0xe87b24, 0x000002,
43*e118015dSJiaxin Yu 	0x12d2cc, 0x207578, 0x12d2cc, 0xf4fe62, 0xef5917, 0x000002,
44*e118015dSJiaxin Yu 	0x12d2cc, 0x24055f, 0x12d2cc, 0x05ee2b, 0xf8b502, 0x000002,
45*e118015dSJiaxin Yu 	0x000000, 0x25a599, 0x25a599, 0x0fabe2, 0x000000, 0x000001
46*e118015dSJiaxin Yu };
47*e118015dSJiaxin Yu 
48*e118015dSJiaxin Yu static const unsigned int src_iir_coeff_48_to_16[] = {
49*e118015dSJiaxin Yu 	0x0296a4, 0xfd69dd, 0x0296a4, 0x209439, 0xe01ff9, 0x000002,
50*e118015dSJiaxin Yu 	0x0f4ff3, 0xf0d6d4, 0x0f4ff3, 0x209bc9, 0xe076c3, 0x000002,
51*e118015dSJiaxin Yu 	0x0e8490, 0xf1fe63, 0x0e8490, 0x20cfd6, 0xe12124, 0x000002,
52*e118015dSJiaxin Yu 	0x14852f, 0xed794a, 0x14852f, 0x21503d, 0xe28b32, 0x000002,
53*e118015dSJiaxin Yu 	0x136222, 0xf17677, 0x136222, 0x225be1, 0xe56964, 0x000002,
54*e118015dSJiaxin Yu 	0x0a8d85, 0xfc4a97, 0x0a8d85, 0x24310c, 0xea6952, 0x000002,
55*e118015dSJiaxin Yu 	0x05eff5, 0x043455, 0x05eff5, 0x4ced8f, 0xe134d6, 0x000001,
56*e118015dSJiaxin Yu 	0x000000, 0x3aebe6, 0x3aebe6, 0x04f3b0, 0x000000, 0x000004
57*e118015dSJiaxin Yu };
58*e118015dSJiaxin Yu 
59*e118015dSJiaxin Yu static const unsigned int src_iir_coeff_48_to_32[] = {
60*e118015dSJiaxin Yu 	0x10c1b8, 0x10a7df, 0x10c1b8, 0xe7514e, 0xe0b41f, 0x000002,
61*e118015dSJiaxin Yu 	0x10c1b8, 0x116257, 0x10c1b8, 0xe9402f, 0xe25aaa, 0x000002,
62*e118015dSJiaxin Yu 	0x10c1b8, 0x130c89, 0x10c1b8, 0xed3cc3, 0xe4dddb, 0x000002,
63*e118015dSJiaxin Yu 	0x10c1b8, 0x1600dd, 0x10c1b8, 0xf48000, 0xe90c55, 0x000002,
64*e118015dSJiaxin Yu 	0x10c1b8, 0x1a672e, 0x10c1b8, 0x00494c, 0xefa807, 0x000002,
65*e118015dSJiaxin Yu 	0x10c1b8, 0x1f38e6, 0x10c1b8, 0x0ee076, 0xf7c5f3, 0x000002,
66*e118015dSJiaxin Yu 	0x000000, 0x218370, 0x218370, 0x168b40, 0x000000, 0x000001
67*e118015dSJiaxin Yu };
68*e118015dSJiaxin Yu 
69*e118015dSJiaxin Yu static const unsigned int src_iir_coeff_48_to_44[] = {
70*e118015dSJiaxin Yu 	0x0bf71c, 0x170f3f, 0x0bf71c, 0xe3a4c8, 0xf096cb, 0x000003,
71*e118015dSJiaxin Yu 	0x0bf71c, 0x17395e, 0x0bf71c, 0xe58085, 0xf210c8, 0x000003,
72*e118015dSJiaxin Yu 	0x0bf71c, 0x1782bd, 0x0bf71c, 0xe95ef6, 0xf4c899, 0x000003,
73*e118015dSJiaxin Yu 	0x0bf71c, 0x17cd97, 0x0bf71c, 0xf1608a, 0xfa3b18, 0x000003,
74*e118015dSJiaxin Yu 	0x000000, 0x2fdc6f, 0x2fdc6f, 0xf15663, 0x000000, 0x000001
75*e118015dSJiaxin Yu };
76*e118015dSJiaxin Yu 
77*e118015dSJiaxin Yu static const unsigned int src_iir_coeff_96_to_16[] = {
78*e118015dSJiaxin Yu 	0x0805a1, 0xf21ae3, 0x0805a1, 0x3840bb, 0xe02a2e, 0x000002,
79*e118015dSJiaxin Yu 	0x0d5dd8, 0xe8f259, 0x0d5dd8, 0x1c0af6, 0xf04700, 0x000003,
80*e118015dSJiaxin Yu 	0x0bb422, 0xec08d9, 0x0bb422, 0x1bfccc, 0xf09216, 0x000003,
81*e118015dSJiaxin Yu 	0x08fde6, 0xf108be, 0x08fde6, 0x1bf096, 0xf10ae0, 0x000003,
82*e118015dSJiaxin Yu 	0x0ae311, 0xeeeda3, 0x0ae311, 0x37c646, 0xe385f5, 0x000002,
83*e118015dSJiaxin Yu 	0x044089, 0xfa7242, 0x044089, 0x37a785, 0xe56526, 0x000002,
84*e118015dSJiaxin Yu 	0x00c75c, 0xffb947, 0x00c75c, 0x378ba3, 0xe72c5f, 0x000002,
85*e118015dSJiaxin Yu 	0x000000, 0x0ef76e, 0x0ef76e, 0x377fda, 0x000000, 0x000001,
86*e118015dSJiaxin Yu };
87*e118015dSJiaxin Yu 
88*e118015dSJiaxin Yu static const unsigned int src_iir_coeff_96_to_44[] = {
89*e118015dSJiaxin Yu 	0x08b543, 0xfd80f4, 0x08b543, 0x0e2332, 0xe06ed0, 0x000002,
90*e118015dSJiaxin Yu 	0x1b6038, 0xf90e7e, 0x1b6038, 0x0ec1ac, 0xe16f66, 0x000002,
91*e118015dSJiaxin Yu 	0x188478, 0xfbb921, 0x188478, 0x105859, 0xe2e596, 0x000002,
92*e118015dSJiaxin Yu 	0x13eff3, 0xffa707, 0x13eff3, 0x13455c, 0xe533b7, 0x000002,
93*e118015dSJiaxin Yu 	0x0dc239, 0x03d458, 0x0dc239, 0x17f120, 0xe8b617, 0x000002,
94*e118015dSJiaxin Yu 	0x0745f1, 0x05d790, 0x0745f1, 0x1e3d75, 0xed5f18, 0x000002,
95*e118015dSJiaxin Yu 	0x05641f, 0x085e2b, 0x05641f, 0x48efd0, 0xe3e9c8, 0x000001,
96*e118015dSJiaxin Yu 	0x000000, 0x28f632, 0x28f632, 0x273905, 0x000000, 0x000001,
97*e118015dSJiaxin Yu };
98*e118015dSJiaxin Yu 
mtk_get_src_freq_mode(struct mtk_base_afe * afe,int rate)99*e118015dSJiaxin Yu static unsigned int mtk_get_src_freq_mode(struct mtk_base_afe *afe, int rate)
100*e118015dSJiaxin Yu {
101*e118015dSJiaxin Yu 	switch (rate) {
102*e118015dSJiaxin Yu 	case 8000:
103*e118015dSJiaxin Yu 		return 0x50000;
104*e118015dSJiaxin Yu 	case 11025:
105*e118015dSJiaxin Yu 		return 0x6e400;
106*e118015dSJiaxin Yu 	case 12000:
107*e118015dSJiaxin Yu 		return 0x78000;
108*e118015dSJiaxin Yu 	case 16000:
109*e118015dSJiaxin Yu 		return 0xa0000;
110*e118015dSJiaxin Yu 	case 22050:
111*e118015dSJiaxin Yu 		return 0xdc800;
112*e118015dSJiaxin Yu 	case 24000:
113*e118015dSJiaxin Yu 		return 0xf0000;
114*e118015dSJiaxin Yu 	case 32000:
115*e118015dSJiaxin Yu 		return 0x140000;
116*e118015dSJiaxin Yu 	case 44100:
117*e118015dSJiaxin Yu 		return 0x1b9000;
118*e118015dSJiaxin Yu 	case 48000:
119*e118015dSJiaxin Yu 		return 0x1e0000;
120*e118015dSJiaxin Yu 	case 88200:
121*e118015dSJiaxin Yu 		return 0x372000;
122*e118015dSJiaxin Yu 	case 96000:
123*e118015dSJiaxin Yu 		return 0x3c0000;
124*e118015dSJiaxin Yu 	case 176400:
125*e118015dSJiaxin Yu 		return 0x6e4000;
126*e118015dSJiaxin Yu 	case 192000:
127*e118015dSJiaxin Yu 		return 0x780000;
128*e118015dSJiaxin Yu 	default:
129*e118015dSJiaxin Yu 		dev_err(afe->dev, "%s(), rate %d invalid!!!\n",
130*e118015dSJiaxin Yu 			__func__, rate);
131*e118015dSJiaxin Yu 		return 0;
132*e118015dSJiaxin Yu 	}
133*e118015dSJiaxin Yu }
134*e118015dSJiaxin Yu 
get_iir_coeff(unsigned int rate_in,unsigned int rate_out,unsigned int * param_num)135*e118015dSJiaxin Yu static const unsigned int *get_iir_coeff(unsigned int rate_in,
136*e118015dSJiaxin Yu 					 unsigned int rate_out,
137*e118015dSJiaxin Yu 					 unsigned int *param_num)
138*e118015dSJiaxin Yu {
139*e118015dSJiaxin Yu 	if (rate_in == 32000 && rate_out == 16000) {
140*e118015dSJiaxin Yu 		*param_num = ARRAY_SIZE(src_iir_coeff_32_to_16);
141*e118015dSJiaxin Yu 		return src_iir_coeff_32_to_16;
142*e118015dSJiaxin Yu 	} else if (rate_in == 44100 && rate_out == 16000) {
143*e118015dSJiaxin Yu 		*param_num = ARRAY_SIZE(src_iir_coeff_44_to_16);
144*e118015dSJiaxin Yu 		return src_iir_coeff_44_to_16;
145*e118015dSJiaxin Yu 	} else if (rate_in == 44100 && rate_out == 32000) {
146*e118015dSJiaxin Yu 		*param_num = ARRAY_SIZE(src_iir_coeff_44_to_32);
147*e118015dSJiaxin Yu 		return src_iir_coeff_44_to_32;
148*e118015dSJiaxin Yu 	} else if ((rate_in == 48000 && rate_out == 16000) ||
149*e118015dSJiaxin Yu 		   (rate_in == 96000 && rate_out == 32000)) {
150*e118015dSJiaxin Yu 		*param_num = ARRAY_SIZE(src_iir_coeff_48_to_16);
151*e118015dSJiaxin Yu 		return src_iir_coeff_48_to_16;
152*e118015dSJiaxin Yu 	} else if (rate_in == 48000 && rate_out == 32000) {
153*e118015dSJiaxin Yu 		*param_num = ARRAY_SIZE(src_iir_coeff_48_to_32);
154*e118015dSJiaxin Yu 		return src_iir_coeff_48_to_32;
155*e118015dSJiaxin Yu 	} else if (rate_in == 48000 && rate_out == 44100) {
156*e118015dSJiaxin Yu 		*param_num = ARRAY_SIZE(src_iir_coeff_48_to_44);
157*e118015dSJiaxin Yu 		return src_iir_coeff_48_to_44;
158*e118015dSJiaxin Yu 	} else if (rate_in == 96000 && rate_out == 16000) {
159*e118015dSJiaxin Yu 		*param_num = ARRAY_SIZE(src_iir_coeff_96_to_16);
160*e118015dSJiaxin Yu 		return src_iir_coeff_96_to_16;
161*e118015dSJiaxin Yu 	} else if ((rate_in == 96000 && rate_out == 44100) ||
162*e118015dSJiaxin Yu 		   (rate_in == 48000 && rate_out == 22050)) {
163*e118015dSJiaxin Yu 		*param_num = ARRAY_SIZE(src_iir_coeff_96_to_44);
164*e118015dSJiaxin Yu 		return src_iir_coeff_96_to_44;
165*e118015dSJiaxin Yu 	}
166*e118015dSJiaxin Yu 
167*e118015dSJiaxin Yu 	*param_num = 0;
168*e118015dSJiaxin Yu 	return NULL;
169*e118015dSJiaxin Yu }
170*e118015dSJiaxin Yu 
mtk_set_src_1_param(struct mtk_base_afe * afe,int id)171*e118015dSJiaxin Yu static int mtk_set_src_1_param(struct mtk_base_afe *afe, int id)
172*e118015dSJiaxin Yu {
173*e118015dSJiaxin Yu 	struct mt8186_afe_private *afe_priv = afe->platform_priv;
174*e118015dSJiaxin Yu 	struct mtk_afe_src_priv *src_priv = afe_priv->dai_priv[id];
175*e118015dSJiaxin Yu 	unsigned int iir_coeff_num;
176*e118015dSJiaxin Yu 	unsigned int iir_stage;
177*e118015dSJiaxin Yu 	int rate_in = src_priv->dl_rate;
178*e118015dSJiaxin Yu 	int rate_out = src_priv->ul_rate;
179*e118015dSJiaxin Yu 	unsigned int out_freq_mode = mtk_get_src_freq_mode(afe, rate_out);
180*e118015dSJiaxin Yu 	unsigned int in_freq_mode = mtk_get_src_freq_mode(afe, rate_in);
181*e118015dSJiaxin Yu 
182*e118015dSJiaxin Yu 	/* set out freq mode */
183*e118015dSJiaxin Yu 	regmap_update_bits(afe->regmap, AFE_GENERAL1_ASRC_2CH_CON3,
184*e118015dSJiaxin Yu 			   G_SRC_ASM_FREQ_4_MASK_SFT,
185*e118015dSJiaxin Yu 			   out_freq_mode << G_SRC_ASM_FREQ_4_SFT);
186*e118015dSJiaxin Yu 
187*e118015dSJiaxin Yu 	/* set in freq mode */
188*e118015dSJiaxin Yu 	regmap_update_bits(afe->regmap, AFE_GENERAL1_ASRC_2CH_CON4,
189*e118015dSJiaxin Yu 			   G_SRC_ASM_FREQ_5_MASK_SFT,
190*e118015dSJiaxin Yu 			   in_freq_mode << G_SRC_ASM_FREQ_5_SFT);
191*e118015dSJiaxin Yu 
192*e118015dSJiaxin Yu 	regmap_write(afe->regmap, AFE_GENERAL1_ASRC_2CH_CON5, 0x3f5986);
193*e118015dSJiaxin Yu 	regmap_write(afe->regmap, AFE_GENERAL1_ASRC_2CH_CON5, 0x3f5987);
194*e118015dSJiaxin Yu 	regmap_write(afe->regmap, AFE_GENERAL1_ASRC_2CH_CON6, 0x1fbd);
195*e118015dSJiaxin Yu 	regmap_write(afe->regmap, AFE_GENERAL1_ASRC_2CH_CON2, 0);
196*e118015dSJiaxin Yu 
197*e118015dSJiaxin Yu 	/* set iir if in_rate > out_rate */
198*e118015dSJiaxin Yu 	if (rate_in > rate_out) {
199*e118015dSJiaxin Yu 		int i;
200*e118015dSJiaxin Yu 		const unsigned int *iir_coeff = get_iir_coeff(rate_in, rate_out,
201*e118015dSJiaxin Yu 							      &iir_coeff_num);
202*e118015dSJiaxin Yu 
203*e118015dSJiaxin Yu 		if (iir_coeff_num == 0 || !iir_coeff) {
204*e118015dSJiaxin Yu 			dev_err(afe->dev, "%s(), iir coeff error, num %d, coeff %p\n",
205*e118015dSJiaxin Yu 				__func__, iir_coeff_num, iir_coeff);
206*e118015dSJiaxin Yu 			return -EINVAL;
207*e118015dSJiaxin Yu 		}
208*e118015dSJiaxin Yu 
209*e118015dSJiaxin Yu 		/* COEFF_SRAM_CTRL */
210*e118015dSJiaxin Yu 		regmap_update_bits(afe->regmap, AFE_GENERAL1_ASRC_2CH_CON0,
211*e118015dSJiaxin Yu 				   G_SRC_COEFF_SRAM_CTRL_MASK_SFT,
212*e118015dSJiaxin Yu 				   BIT(G_SRC_COEFF_SRAM_CTRL_SFT));
213*e118015dSJiaxin Yu 		/* Clear coeff history to r/w coeff from the first position */
214*e118015dSJiaxin Yu 		regmap_update_bits(afe->regmap, AFE_GENERAL1_ASRC_2CH_CON13,
215*e118015dSJiaxin Yu 				   G_SRC_COEFF_SRAM_ADR_MASK_SFT, 0);
216*e118015dSJiaxin Yu 		/* Write SRC coeff, should not read the reg during write */
217*e118015dSJiaxin Yu 		for (i = 0; i < iir_coeff_num; i++)
218*e118015dSJiaxin Yu 			regmap_write(afe->regmap, AFE_GENERAL1_ASRC_2CH_CON12,
219*e118015dSJiaxin Yu 				     iir_coeff[i]);
220*e118015dSJiaxin Yu 		/* disable sram access */
221*e118015dSJiaxin Yu 		regmap_update_bits(afe->regmap, AFE_GENERAL1_ASRC_2CH_CON0,
222*e118015dSJiaxin Yu 				   G_SRC_COEFF_SRAM_CTRL_MASK_SFT, 0);
223*e118015dSJiaxin Yu 		/* CHSET_IIR_STAGE */
224*e118015dSJiaxin Yu 		iir_stage = (iir_coeff_num / 6) - 1;
225*e118015dSJiaxin Yu 		regmap_update_bits(afe->regmap, AFE_GENERAL1_ASRC_2CH_CON2,
226*e118015dSJiaxin Yu 				   G_SRC_CHSET_IIR_STAGE_MASK_SFT,
227*e118015dSJiaxin Yu 				   iir_stage << G_SRC_CHSET_IIR_STAGE_SFT);
228*e118015dSJiaxin Yu 		/* CHSET_IIR_EN */
229*e118015dSJiaxin Yu 		regmap_update_bits(afe->regmap, AFE_GENERAL1_ASRC_2CH_CON2,
230*e118015dSJiaxin Yu 				   G_SRC_CHSET_IIR_EN_MASK_SFT,
231*e118015dSJiaxin Yu 				   BIT(G_SRC_CHSET_IIR_EN_SFT));
232*e118015dSJiaxin Yu 	} else {
233*e118015dSJiaxin Yu 		/* CHSET_IIR_EN off */
234*e118015dSJiaxin Yu 		regmap_update_bits(afe->regmap, AFE_GENERAL1_ASRC_2CH_CON2,
235*e118015dSJiaxin Yu 				   G_SRC_CHSET_IIR_EN_MASK_SFT, 0);
236*e118015dSJiaxin Yu 	}
237*e118015dSJiaxin Yu 
238*e118015dSJiaxin Yu 	return 0;
239*e118015dSJiaxin Yu }
240*e118015dSJiaxin Yu 
mtk_set_src_2_param(struct mtk_base_afe * afe,int id)241*e118015dSJiaxin Yu static int mtk_set_src_2_param(struct mtk_base_afe *afe, int id)
242*e118015dSJiaxin Yu {
243*e118015dSJiaxin Yu 	struct mt8186_afe_private *afe_priv = afe->platform_priv;
244*e118015dSJiaxin Yu 	struct mtk_afe_src_priv *src_priv = afe_priv->dai_priv[id];
245*e118015dSJiaxin Yu 	unsigned int iir_coeff_num;
246*e118015dSJiaxin Yu 	unsigned int iir_stage;
247*e118015dSJiaxin Yu 	int rate_in = src_priv->dl_rate;
248*e118015dSJiaxin Yu 	int rate_out = src_priv->ul_rate;
249*e118015dSJiaxin Yu 	unsigned int out_freq_mode = mtk_get_src_freq_mode(afe, rate_out);
250*e118015dSJiaxin Yu 	unsigned int in_freq_mode = mtk_get_src_freq_mode(afe, rate_in);
251*e118015dSJiaxin Yu 
252*e118015dSJiaxin Yu 	/* set out freq mode */
253*e118015dSJiaxin Yu 	regmap_update_bits(afe->regmap, AFE_GENERAL2_ASRC_2CH_CON3,
254*e118015dSJiaxin Yu 			   G_SRC_ASM_FREQ_4_MASK_SFT,
255*e118015dSJiaxin Yu 			   out_freq_mode << G_SRC_ASM_FREQ_4_SFT);
256*e118015dSJiaxin Yu 
257*e118015dSJiaxin Yu 	/* set in freq mode */
258*e118015dSJiaxin Yu 	regmap_update_bits(afe->regmap, AFE_GENERAL2_ASRC_2CH_CON4,
259*e118015dSJiaxin Yu 			   G_SRC_ASM_FREQ_5_MASK_SFT,
260*e118015dSJiaxin Yu 			   in_freq_mode << G_SRC_ASM_FREQ_5_SFT);
261*e118015dSJiaxin Yu 
262*e118015dSJiaxin Yu 	regmap_write(afe->regmap, AFE_GENERAL2_ASRC_2CH_CON5, 0x3f5986);
263*e118015dSJiaxin Yu 	regmap_write(afe->regmap, AFE_GENERAL2_ASRC_2CH_CON5, 0x3f5987);
264*e118015dSJiaxin Yu 	regmap_write(afe->regmap, AFE_GENERAL2_ASRC_2CH_CON6, 0x1fbd);
265*e118015dSJiaxin Yu 	regmap_write(afe->regmap, AFE_GENERAL2_ASRC_2CH_CON2, 0);
266*e118015dSJiaxin Yu 
267*e118015dSJiaxin Yu 	/* set iir if in_rate > out_rate */
268*e118015dSJiaxin Yu 	if (rate_in > rate_out) {
269*e118015dSJiaxin Yu 		int i;
270*e118015dSJiaxin Yu 		const unsigned int *iir_coeff = get_iir_coeff(rate_in, rate_out,
271*e118015dSJiaxin Yu 							      &iir_coeff_num);
272*e118015dSJiaxin Yu 
273*e118015dSJiaxin Yu 		if (iir_coeff_num == 0 || !iir_coeff) {
274*e118015dSJiaxin Yu 			dev_err(afe->dev, "%s(), iir coeff error, num %d, coeff %p\n",
275*e118015dSJiaxin Yu 				 __func__, iir_coeff_num, iir_coeff);
276*e118015dSJiaxin Yu 			return -EINVAL;
277*e118015dSJiaxin Yu 		}
278*e118015dSJiaxin Yu 
279*e118015dSJiaxin Yu 		/* COEFF_SRAM_CTRL */
280*e118015dSJiaxin Yu 		regmap_update_bits(afe->regmap, AFE_GENERAL2_ASRC_2CH_CON0,
281*e118015dSJiaxin Yu 				   G_SRC_COEFF_SRAM_CTRL_MASK_SFT,
282*e118015dSJiaxin Yu 				   BIT(G_SRC_COEFF_SRAM_CTRL_SFT));
283*e118015dSJiaxin Yu 		/* Clear coeff history to r/w coeff from the first position */
284*e118015dSJiaxin Yu 		regmap_update_bits(afe->regmap, AFE_GENERAL2_ASRC_2CH_CON13,
285*e118015dSJiaxin Yu 				   G_SRC_COEFF_SRAM_ADR_MASK_SFT, 0);
286*e118015dSJiaxin Yu 		/* Write SRC coeff, should not read the reg during write */
287*e118015dSJiaxin Yu 		for (i = 0; i < iir_coeff_num; i++)
288*e118015dSJiaxin Yu 			regmap_write(afe->regmap, AFE_GENERAL2_ASRC_2CH_CON12,
289*e118015dSJiaxin Yu 				     iir_coeff[i]);
290*e118015dSJiaxin Yu 		/* disable sram access */
291*e118015dSJiaxin Yu 		regmap_update_bits(afe->regmap, AFE_GENERAL2_ASRC_2CH_CON0,
292*e118015dSJiaxin Yu 				   G_SRC_COEFF_SRAM_CTRL_MASK_SFT, 0);
293*e118015dSJiaxin Yu 		/* CHSET_IIR_STAGE */
294*e118015dSJiaxin Yu 		iir_stage = (iir_coeff_num / 6) - 1;
295*e118015dSJiaxin Yu 		regmap_update_bits(afe->regmap, AFE_GENERAL2_ASRC_2CH_CON2,
296*e118015dSJiaxin Yu 				   G_SRC_CHSET_IIR_STAGE_MASK_SFT,
297*e118015dSJiaxin Yu 				   iir_stage << G_SRC_CHSET_IIR_STAGE_SFT);
298*e118015dSJiaxin Yu 		/* CHSET_IIR_EN */
299*e118015dSJiaxin Yu 		regmap_update_bits(afe->regmap, AFE_GENERAL2_ASRC_2CH_CON2,
300*e118015dSJiaxin Yu 				   G_SRC_CHSET_IIR_EN_MASK_SFT,
301*e118015dSJiaxin Yu 				   BIT(G_SRC_CHSET_IIR_EN_SFT));
302*e118015dSJiaxin Yu 	} else {
303*e118015dSJiaxin Yu 		/* CHSET_IIR_EN off */
304*e118015dSJiaxin Yu 		regmap_update_bits(afe->regmap, AFE_GENERAL2_ASRC_2CH_CON2,
305*e118015dSJiaxin Yu 				   G_SRC_CHSET_IIR_EN_MASK_SFT, 0);
306*e118015dSJiaxin Yu 	}
307*e118015dSJiaxin Yu 
308*e118015dSJiaxin Yu 	return 0;
309*e118015dSJiaxin Yu }
310*e118015dSJiaxin Yu 
311*e118015dSJiaxin Yu #define HW_SRC_1_EN_W_NAME "HW_SRC_1_Enable"
312*e118015dSJiaxin Yu #define HW_SRC_2_EN_W_NAME "HW_SRC_2_Enable"
313*e118015dSJiaxin Yu 
mtk_hw_src_event(struct snd_soc_dapm_widget * w,struct snd_kcontrol * kcontrol,int event)314*e118015dSJiaxin Yu static int mtk_hw_src_event(struct snd_soc_dapm_widget *w,
315*e118015dSJiaxin Yu 			    struct snd_kcontrol *kcontrol,
316*e118015dSJiaxin Yu 			    int event)
317*e118015dSJiaxin Yu {
318*e118015dSJiaxin Yu 	struct snd_soc_component *cmpnt = snd_soc_dapm_to_component(w->dapm);
319*e118015dSJiaxin Yu 	struct mtk_base_afe *afe = snd_soc_component_get_drvdata(cmpnt);
320*e118015dSJiaxin Yu 	struct mt8186_afe_private *afe_priv = afe->platform_priv;
321*e118015dSJiaxin Yu 	int id;
322*e118015dSJiaxin Yu 	struct mtk_afe_src_priv *src_priv;
323*e118015dSJiaxin Yu 	unsigned int reg;
324*e118015dSJiaxin Yu 
325*e118015dSJiaxin Yu 	if (strcmp(w->name, HW_SRC_1_EN_W_NAME) == 0)
326*e118015dSJiaxin Yu 		id = MT8186_DAI_SRC_1;
327*e118015dSJiaxin Yu 	else
328*e118015dSJiaxin Yu 		id = MT8186_DAI_SRC_2;
329*e118015dSJiaxin Yu 
330*e118015dSJiaxin Yu 	src_priv = afe_priv->dai_priv[id];
331*e118015dSJiaxin Yu 
332*e118015dSJiaxin Yu 	dev_dbg(afe->dev,
333*e118015dSJiaxin Yu 		"%s(), name %s, event 0x%x, id %d, src_priv %p, dl_rate %d, ul_rate %d\n",
334*e118015dSJiaxin Yu 		__func__, w->name, event, id, src_priv,
335*e118015dSJiaxin Yu 		src_priv->dl_rate, src_priv->ul_rate);
336*e118015dSJiaxin Yu 
337*e118015dSJiaxin Yu 	switch (event) {
338*e118015dSJiaxin Yu 	case SND_SOC_DAPM_PRE_PMU:
339*e118015dSJiaxin Yu 		if (id == MT8186_DAI_SRC_1)
340*e118015dSJiaxin Yu 			mtk_set_src_1_param(afe, id);
341*e118015dSJiaxin Yu 		else
342*e118015dSJiaxin Yu 			mtk_set_src_2_param(afe, id);
343*e118015dSJiaxin Yu 		break;
344*e118015dSJiaxin Yu 	case SND_SOC_DAPM_POST_PMU:
345*e118015dSJiaxin Yu 		reg = (id == MT8186_DAI_SRC_1) ?
346*e118015dSJiaxin Yu 		      AFE_GENERAL1_ASRC_2CH_CON0 : AFE_GENERAL2_ASRC_2CH_CON0;
347*e118015dSJiaxin Yu 		/* ASM_ON */
348*e118015dSJiaxin Yu 		regmap_update_bits(afe->regmap, reg,
349*e118015dSJiaxin Yu 				   G_SRC_ASM_ON_MASK_SFT,
350*e118015dSJiaxin Yu 				   BIT(G_SRC_ASM_ON_SFT));
351*e118015dSJiaxin Yu 		/* CHSET_ON */
352*e118015dSJiaxin Yu 		regmap_update_bits(afe->regmap, reg,
353*e118015dSJiaxin Yu 				   G_SRC_CHSET_ON_MASK_SFT,
354*e118015dSJiaxin Yu 				   BIT(G_SRC_CHSET_ON_SFT));
355*e118015dSJiaxin Yu 		/* CHSET_STR_CLR */
356*e118015dSJiaxin Yu 		regmap_update_bits(afe->regmap, reg,
357*e118015dSJiaxin Yu 				   G_SRC_CHSET_STR_CLR_MASK_SFT,
358*e118015dSJiaxin Yu 				   BIT(G_SRC_CHSET_STR_CLR_SFT));
359*e118015dSJiaxin Yu 		break;
360*e118015dSJiaxin Yu 	case SND_SOC_DAPM_PRE_PMD:
361*e118015dSJiaxin Yu 		reg = (id == MT8186_DAI_SRC_1) ?
362*e118015dSJiaxin Yu 		      AFE_GENERAL1_ASRC_2CH_CON0 : AFE_GENERAL2_ASRC_2CH_CON0;
363*e118015dSJiaxin Yu 		/* ASM_OFF */
364*e118015dSJiaxin Yu 		regmap_update_bits(afe->regmap, reg, G_SRC_ASM_ON_MASK_SFT, 0);
365*e118015dSJiaxin Yu 		/* CHSET_OFF */
366*e118015dSJiaxin Yu 		regmap_update_bits(afe->regmap, reg, G_SRC_CHSET_ON_MASK_SFT, 0);
367*e118015dSJiaxin Yu 		/* CHSET_STR_CLR */
368*e118015dSJiaxin Yu 		regmap_update_bits(afe->regmap, reg, G_SRC_CHSET_STR_CLR_MASK_SFT, 0);
369*e118015dSJiaxin Yu 		break;
370*e118015dSJiaxin Yu 	default:
371*e118015dSJiaxin Yu 		break;
372*e118015dSJiaxin Yu 	}
373*e118015dSJiaxin Yu 
374*e118015dSJiaxin Yu 	return 0;
375*e118015dSJiaxin Yu }
376*e118015dSJiaxin Yu 
377*e118015dSJiaxin Yu /* dai component */
378*e118015dSJiaxin Yu static const struct snd_kcontrol_new mtk_hw_src_1_in_ch1_mix[] = {
379*e118015dSJiaxin Yu 	SOC_DAPM_SINGLE_AUTODISABLE("DL1_CH1 Switch", AFE_CONN40,
380*e118015dSJiaxin Yu 				    I_DL1_CH1, 1, 0),
381*e118015dSJiaxin Yu 	SOC_DAPM_SINGLE_AUTODISABLE("DL2_CH1 Switch", AFE_CONN40,
382*e118015dSJiaxin Yu 				    I_DL2_CH1, 1, 0),
383*e118015dSJiaxin Yu 	SOC_DAPM_SINGLE_AUTODISABLE("DL3_CH1 Switch", AFE_CONN40,
384*e118015dSJiaxin Yu 				    I_DL3_CH1, 1, 0),
385*e118015dSJiaxin Yu 	SOC_DAPM_SINGLE_AUTODISABLE("DL4_CH1 Switch", AFE_CONN40_1,
386*e118015dSJiaxin Yu 				    I_DL4_CH1, 1, 0),
387*e118015dSJiaxin Yu 	SOC_DAPM_SINGLE_AUTODISABLE("DL6_CH1 Switch", AFE_CONN40_1,
388*e118015dSJiaxin Yu 				    I_DL6_CH1, 1, 0),
389*e118015dSJiaxin Yu 	SOC_DAPM_SINGLE_AUTODISABLE("I2S0_CH1 Switch", AFE_CONN40,
390*e118015dSJiaxin Yu 				    I_I2S0_CH1, 1, 0),
391*e118015dSJiaxin Yu 	SOC_DAPM_SINGLE_AUTODISABLE("DL5_CH1 Switch", AFE_CONN40_1,
392*e118015dSJiaxin Yu 				    I_DL5_CH1, 1, 0),
393*e118015dSJiaxin Yu };
394*e118015dSJiaxin Yu 
395*e118015dSJiaxin Yu static const struct snd_kcontrol_new mtk_hw_src_1_in_ch2_mix[] = {
396*e118015dSJiaxin Yu 	SOC_DAPM_SINGLE_AUTODISABLE("DL1_CH2 Switch", AFE_CONN41,
397*e118015dSJiaxin Yu 				    I_DL1_CH2, 1, 0),
398*e118015dSJiaxin Yu 	SOC_DAPM_SINGLE_AUTODISABLE("DL2_CH2 Switch", AFE_CONN41,
399*e118015dSJiaxin Yu 				    I_DL2_CH2, 1, 0),
400*e118015dSJiaxin Yu 	SOC_DAPM_SINGLE_AUTODISABLE("DL3_CH2 Switch", AFE_CONN41,
401*e118015dSJiaxin Yu 				    I_DL3_CH2, 1, 0),
402*e118015dSJiaxin Yu 	SOC_DAPM_SINGLE_AUTODISABLE("DL4_CH2 Switch", AFE_CONN41_1,
403*e118015dSJiaxin Yu 				    I_DL4_CH2, 1, 0),
404*e118015dSJiaxin Yu 	SOC_DAPM_SINGLE_AUTODISABLE("DL6_CH2 Switch", AFE_CONN41_1,
405*e118015dSJiaxin Yu 				    I_DL6_CH2, 1, 0),
406*e118015dSJiaxin Yu 	SOC_DAPM_SINGLE_AUTODISABLE("I2S0_CH2 Switch", AFE_CONN41,
407*e118015dSJiaxin Yu 				    I_I2S0_CH2, 1, 0),
408*e118015dSJiaxin Yu 	SOC_DAPM_SINGLE_AUTODISABLE("DL5_CH2 Switch", AFE_CONN41_1,
409*e118015dSJiaxin Yu 				    I_DL5_CH2, 1, 0),
410*e118015dSJiaxin Yu };
411*e118015dSJiaxin Yu 
412*e118015dSJiaxin Yu static const struct snd_kcontrol_new mtk_hw_src_2_in_ch1_mix[] = {
413*e118015dSJiaxin Yu 	SOC_DAPM_SINGLE_AUTODISABLE("DL1_CH1 Switch", AFE_CONN42,
414*e118015dSJiaxin Yu 				    I_DL1_CH1, 1, 0),
415*e118015dSJiaxin Yu 	SOC_DAPM_SINGLE_AUTODISABLE("DL2_CH1 Switch", AFE_CONN42,
416*e118015dSJiaxin Yu 				    I_DL2_CH1, 1, 0),
417*e118015dSJiaxin Yu 	SOC_DAPM_SINGLE_AUTODISABLE("DL3_CH1 Switch", AFE_CONN42,
418*e118015dSJiaxin Yu 				    I_DL3_CH1, 1, 0),
419*e118015dSJiaxin Yu 	SOC_DAPM_SINGLE_AUTODISABLE("DL4_CH1 Switch", AFE_CONN42,
420*e118015dSJiaxin Yu 				    I_DL4_CH1, 1, 0),
421*e118015dSJiaxin Yu 	SOC_DAPM_SINGLE_AUTODISABLE("DL5_CH1 Switch", AFE_CONN42_1,
422*e118015dSJiaxin Yu 				    I_DL5_CH1, 1, 0),
423*e118015dSJiaxin Yu 	SOC_DAPM_SINGLE_AUTODISABLE("DL6_CH1 Switch", AFE_CONN42_1,
424*e118015dSJiaxin Yu 				    I_DL6_CH1, 1, 0),
425*e118015dSJiaxin Yu 	SOC_DAPM_SINGLE_AUTODISABLE("HW_GAIN2_OUT_CH1 Switch", AFE_CONN42,
426*e118015dSJiaxin Yu 				    I_GAIN2_OUT_CH1, 1, 0),
427*e118015dSJiaxin Yu };
428*e118015dSJiaxin Yu 
429*e118015dSJiaxin Yu static const struct snd_kcontrol_new mtk_hw_src_2_in_ch2_mix[] = {
430*e118015dSJiaxin Yu 	SOC_DAPM_SINGLE_AUTODISABLE("DL1_CH2 Switch", AFE_CONN43,
431*e118015dSJiaxin Yu 				    I_DL1_CH2, 1, 0),
432*e118015dSJiaxin Yu 	SOC_DAPM_SINGLE_AUTODISABLE("DL2_CH2 Switch", AFE_CONN43,
433*e118015dSJiaxin Yu 				    I_DL2_CH2, 1, 0),
434*e118015dSJiaxin Yu 	SOC_DAPM_SINGLE_AUTODISABLE("DL3_CH2 Switch", AFE_CONN43,
435*e118015dSJiaxin Yu 				    I_DL3_CH2, 1, 0),
436*e118015dSJiaxin Yu 	SOC_DAPM_SINGLE_AUTODISABLE("DL4_CH2 Switch", AFE_CONN43,
437*e118015dSJiaxin Yu 				    I_DL4_CH2, 1, 0),
438*e118015dSJiaxin Yu 	SOC_DAPM_SINGLE_AUTODISABLE("DL5_CH2 Switch", AFE_CONN43_1,
439*e118015dSJiaxin Yu 				    I_DL5_CH2, 1, 0),
440*e118015dSJiaxin Yu 	SOC_DAPM_SINGLE_AUTODISABLE("DL6_CH2 Switch", AFE_CONN43_1,
441*e118015dSJiaxin Yu 				    I_DL6_CH2, 1, 0),
442*e118015dSJiaxin Yu 	SOC_DAPM_SINGLE_AUTODISABLE("HW_GAIN2_OUT_CH2 Switch", AFE_CONN43,
443*e118015dSJiaxin Yu 				    I_GAIN2_OUT_CH2, 1, 0),
444*e118015dSJiaxin Yu };
445*e118015dSJiaxin Yu 
446*e118015dSJiaxin Yu static const struct snd_soc_dapm_widget mtk_dai_src_widgets[] = {
447*e118015dSJiaxin Yu 	/* inter-connections */
448*e118015dSJiaxin Yu 	SND_SOC_DAPM_MIXER("HW_SRC_1_IN_CH1", SND_SOC_NOPM, 0, 0,
449*e118015dSJiaxin Yu 			   mtk_hw_src_1_in_ch1_mix,
450*e118015dSJiaxin Yu 			   ARRAY_SIZE(mtk_hw_src_1_in_ch1_mix)),
451*e118015dSJiaxin Yu 	SND_SOC_DAPM_MIXER("HW_SRC_1_IN_CH2", SND_SOC_NOPM, 0, 0,
452*e118015dSJiaxin Yu 			   mtk_hw_src_1_in_ch2_mix,
453*e118015dSJiaxin Yu 			   ARRAY_SIZE(mtk_hw_src_1_in_ch2_mix)),
454*e118015dSJiaxin Yu 	SND_SOC_DAPM_MIXER("HW_SRC_2_IN_CH1", SND_SOC_NOPM, 0, 0,
455*e118015dSJiaxin Yu 			   mtk_hw_src_2_in_ch1_mix,
456*e118015dSJiaxin Yu 			   ARRAY_SIZE(mtk_hw_src_2_in_ch1_mix)),
457*e118015dSJiaxin Yu 	SND_SOC_DAPM_MIXER("HW_SRC_2_IN_CH2", SND_SOC_NOPM, 0, 0,
458*e118015dSJiaxin Yu 			   mtk_hw_src_2_in_ch2_mix,
459*e118015dSJiaxin Yu 			   ARRAY_SIZE(mtk_hw_src_2_in_ch2_mix)),
460*e118015dSJiaxin Yu 
461*e118015dSJiaxin Yu 	SND_SOC_DAPM_SUPPLY(HW_SRC_1_EN_W_NAME,
462*e118015dSJiaxin Yu 			    GENERAL_ASRC_EN_ON, GENERAL1_ASRC_EN_ON_SFT, 0,
463*e118015dSJiaxin Yu 			    mtk_hw_src_event,
464*e118015dSJiaxin Yu 			    SND_SOC_DAPM_PRE_PMU |
465*e118015dSJiaxin Yu 			    SND_SOC_DAPM_POST_PMU |
466*e118015dSJiaxin Yu 			    SND_SOC_DAPM_PRE_PMD),
467*e118015dSJiaxin Yu 
468*e118015dSJiaxin Yu 	SND_SOC_DAPM_SUPPLY(HW_SRC_2_EN_W_NAME,
469*e118015dSJiaxin Yu 			    GENERAL_ASRC_EN_ON, GENERAL2_ASRC_EN_ON_SFT, 0,
470*e118015dSJiaxin Yu 			    mtk_hw_src_event,
471*e118015dSJiaxin Yu 			    SND_SOC_DAPM_PRE_PMU |
472*e118015dSJiaxin Yu 			    SND_SOC_DAPM_POST_PMU |
473*e118015dSJiaxin Yu 			    SND_SOC_DAPM_PRE_PMD),
474*e118015dSJiaxin Yu 
475*e118015dSJiaxin Yu 	SND_SOC_DAPM_INPUT("HW SRC 1 Out Endpoint"),
476*e118015dSJiaxin Yu 	SND_SOC_DAPM_INPUT("HW SRC 2 Out Endpoint"),
477*e118015dSJiaxin Yu 	SND_SOC_DAPM_OUTPUT("HW SRC 1 In Endpoint"),
478*e118015dSJiaxin Yu 	SND_SOC_DAPM_OUTPUT("HW SRC 2 In Endpoint"),
479*e118015dSJiaxin Yu };
480*e118015dSJiaxin Yu 
mtk_afe_src_en_connect(struct snd_soc_dapm_widget * source,struct snd_soc_dapm_widget * sink)481*e118015dSJiaxin Yu static int mtk_afe_src_en_connect(struct snd_soc_dapm_widget *source,
482*e118015dSJiaxin Yu 				  struct snd_soc_dapm_widget *sink)
483*e118015dSJiaxin Yu {
484*e118015dSJiaxin Yu 	struct snd_soc_dapm_widget *w = source;
485*e118015dSJiaxin Yu 	struct snd_soc_component *cmpnt = snd_soc_dapm_to_component(w->dapm);
486*e118015dSJiaxin Yu 	struct mtk_base_afe *afe = snd_soc_component_get_drvdata(cmpnt);
487*e118015dSJiaxin Yu 	struct mt8186_afe_private *afe_priv = afe->platform_priv;
488*e118015dSJiaxin Yu 	struct mtk_afe_src_priv *src_priv;
489*e118015dSJiaxin Yu 
490*e118015dSJiaxin Yu 	if (strcmp(w->name, HW_SRC_1_EN_W_NAME) == 0)
491*e118015dSJiaxin Yu 		src_priv = afe_priv->dai_priv[MT8186_DAI_SRC_1];
492*e118015dSJiaxin Yu 	else
493*e118015dSJiaxin Yu 		src_priv = afe_priv->dai_priv[MT8186_DAI_SRC_2];
494*e118015dSJiaxin Yu 
495*e118015dSJiaxin Yu 	dev_dbg(afe->dev,
496*e118015dSJiaxin Yu 		"%s(), source %s, sink %s, dl_rate %d, ul_rate %d\n",
497*e118015dSJiaxin Yu 		__func__, source->name, sink->name,
498*e118015dSJiaxin Yu 		src_priv->dl_rate, src_priv->ul_rate);
499*e118015dSJiaxin Yu 
500*e118015dSJiaxin Yu 	return (src_priv->dl_rate > 0 && src_priv->ul_rate > 0) ? 1 : 0;
501*e118015dSJiaxin Yu }
502*e118015dSJiaxin Yu 
503*e118015dSJiaxin Yu static const struct snd_soc_dapm_route mtk_dai_src_routes[] = {
504*e118015dSJiaxin Yu 	{"HW_SRC_1_IN_CH1", "DL1_CH1 Switch", "DL1"},
505*e118015dSJiaxin Yu 	{"HW_SRC_1_IN_CH2", "DL1_CH2 Switch", "DL1"},
506*e118015dSJiaxin Yu 	{"HW_SRC_2_IN_CH1", "DL1_CH1 Switch", "DL1"},
507*e118015dSJiaxin Yu 	{"HW_SRC_2_IN_CH2", "DL1_CH2 Switch", "DL1"},
508*e118015dSJiaxin Yu 	{"HW_SRC_1_IN_CH1", "DL2_CH1 Switch", "DL2"},
509*e118015dSJiaxin Yu 	{"HW_SRC_1_IN_CH2", "DL2_CH2 Switch", "DL2"},
510*e118015dSJiaxin Yu 	{"HW_SRC_2_IN_CH1", "DL2_CH1 Switch", "DL2"},
511*e118015dSJiaxin Yu 	{"HW_SRC_2_IN_CH2", "DL2_CH2 Switch", "DL2"},
512*e118015dSJiaxin Yu 	{"HW_SRC_1_IN_CH1", "DL3_CH1 Switch", "DL3"},
513*e118015dSJiaxin Yu 	{"HW_SRC_1_IN_CH2", "DL3_CH2 Switch", "DL3"},
514*e118015dSJiaxin Yu 	{"HW_SRC_2_IN_CH1", "DL3_CH1 Switch", "DL3"},
515*e118015dSJiaxin Yu 	{"HW_SRC_2_IN_CH2", "DL3_CH2 Switch", "DL3"},
516*e118015dSJiaxin Yu 	{"HW_SRC_1_IN_CH1", "DL6_CH1 Switch", "DL6"},
517*e118015dSJiaxin Yu 	{"HW_SRC_1_IN_CH2", "DL6_CH2 Switch", "DL6"},
518*e118015dSJiaxin Yu 	{"HW_SRC_2_IN_CH1", "DL6_CH1 Switch", "DL6"},
519*e118015dSJiaxin Yu 	{"HW_SRC_2_IN_CH2", "DL6_CH2 Switch", "DL6"},
520*e118015dSJiaxin Yu 	{"HW_SRC_1_IN_CH1", "DL5_CH1 Switch", "DL5"},
521*e118015dSJiaxin Yu 	{"HW_SRC_1_IN_CH2", "DL5_CH2 Switch", "DL5"},
522*e118015dSJiaxin Yu 	{"HW_SRC_2_IN_CH1", "DL5_CH1 Switch", "DL5"},
523*e118015dSJiaxin Yu 	{"HW_SRC_2_IN_CH2", "DL5_CH2 Switch", "DL5"},
524*e118015dSJiaxin Yu 	{"HW_SRC_1_IN_CH1", "DL4_CH1 Switch", "DL4"},
525*e118015dSJiaxin Yu 	{"HW_SRC_1_IN_CH2", "DL4_CH2 Switch", "DL4"},
526*e118015dSJiaxin Yu 	{"HW_SRC_2_IN_CH1", "DL4_CH1 Switch", "DL4"},
527*e118015dSJiaxin Yu 	{"HW_SRC_2_IN_CH2", "DL4_CH2 Switch", "DL4"},
528*e118015dSJiaxin Yu 
529*e118015dSJiaxin Yu 	{"HW_SRC_1_In", NULL, "HW_SRC_1_IN_CH1"},
530*e118015dSJiaxin Yu 	{"HW_SRC_1_In", NULL, "HW_SRC_1_IN_CH2"},
531*e118015dSJiaxin Yu 
532*e118015dSJiaxin Yu 	{"HW_SRC_2_In", NULL, "HW_SRC_2_IN_CH1"},
533*e118015dSJiaxin Yu 	{"HW_SRC_2_In", NULL, "HW_SRC_2_IN_CH2"},
534*e118015dSJiaxin Yu 
535*e118015dSJiaxin Yu 	{"HW_SRC_1_In", NULL, HW_SRC_1_EN_W_NAME, mtk_afe_src_en_connect},
536*e118015dSJiaxin Yu 	{"HW_SRC_1_Out", NULL, HW_SRC_1_EN_W_NAME, mtk_afe_src_en_connect},
537*e118015dSJiaxin Yu 	{"HW_SRC_2_In", NULL, HW_SRC_2_EN_W_NAME, mtk_afe_src_en_connect},
538*e118015dSJiaxin Yu 	{"HW_SRC_2_Out", NULL, HW_SRC_2_EN_W_NAME, mtk_afe_src_en_connect},
539*e118015dSJiaxin Yu 
540*e118015dSJiaxin Yu 	{"HW SRC 1 In Endpoint", NULL, "HW_SRC_1_In"},
541*e118015dSJiaxin Yu 	{"HW SRC 2 In Endpoint", NULL, "HW_SRC_2_In"},
542*e118015dSJiaxin Yu 	{"HW_SRC_1_Out", NULL, "HW SRC 1 Out Endpoint"},
543*e118015dSJiaxin Yu 	{"HW_SRC_2_Out", NULL, "HW SRC 2 Out Endpoint"},
544*e118015dSJiaxin Yu };
545*e118015dSJiaxin Yu 
546*e118015dSJiaxin Yu /* dai ops */
mtk_dai_src_hw_params(struct snd_pcm_substream * substream,struct snd_pcm_hw_params * params,struct snd_soc_dai * dai)547*e118015dSJiaxin Yu static int mtk_dai_src_hw_params(struct snd_pcm_substream *substream,
548*e118015dSJiaxin Yu 				 struct snd_pcm_hw_params *params,
549*e118015dSJiaxin Yu 				 struct snd_soc_dai *dai)
550*e118015dSJiaxin Yu {
551*e118015dSJiaxin Yu 	struct mtk_base_afe *afe = snd_soc_dai_get_drvdata(dai);
552*e118015dSJiaxin Yu 	struct mt8186_afe_private *afe_priv = afe->platform_priv;
553*e118015dSJiaxin Yu 	int id = dai->id;
554*e118015dSJiaxin Yu 	struct mtk_afe_src_priv *src_priv = afe_priv->dai_priv[id];
555*e118015dSJiaxin Yu 	unsigned int sft, mask;
556*e118015dSJiaxin Yu 	unsigned int rate = params_rate(params);
557*e118015dSJiaxin Yu 	unsigned int rate_reg = mt8186_rate_transform(afe->dev, rate, id);
558*e118015dSJiaxin Yu 
559*e118015dSJiaxin Yu 	dev_dbg(afe->dev, "%s(), id %d, stream %d, rate %d\n",
560*e118015dSJiaxin Yu 		__func__, id, substream->stream, rate);
561*e118015dSJiaxin Yu 
562*e118015dSJiaxin Yu 	/* rate */
563*e118015dSJiaxin Yu 	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
564*e118015dSJiaxin Yu 		src_priv->dl_rate = rate;
565*e118015dSJiaxin Yu 		if (id == MT8186_DAI_SRC_1) {
566*e118015dSJiaxin Yu 			sft = GENERAL1_ASRCIN_MODE_SFT;
567*e118015dSJiaxin Yu 			mask = GENERAL1_ASRCIN_MODE_MASK;
568*e118015dSJiaxin Yu 		} else {
569*e118015dSJiaxin Yu 			sft = GENERAL2_ASRCIN_MODE_SFT;
570*e118015dSJiaxin Yu 			mask = GENERAL2_ASRCIN_MODE_MASK;
571*e118015dSJiaxin Yu 		}
572*e118015dSJiaxin Yu 	} else {
573*e118015dSJiaxin Yu 		src_priv->ul_rate = rate;
574*e118015dSJiaxin Yu 		if (id == MT8186_DAI_SRC_1) {
575*e118015dSJiaxin Yu 			sft = GENERAL1_ASRCOUT_MODE_SFT;
576*e118015dSJiaxin Yu 			mask = GENERAL1_ASRCOUT_MODE_MASK;
577*e118015dSJiaxin Yu 		} else {
578*e118015dSJiaxin Yu 			sft = GENERAL2_ASRCOUT_MODE_SFT;
579*e118015dSJiaxin Yu 			mask = GENERAL2_ASRCOUT_MODE_MASK;
580*e118015dSJiaxin Yu 		}
581*e118015dSJiaxin Yu 	}
582*e118015dSJiaxin Yu 
583*e118015dSJiaxin Yu 	regmap_update_bits(afe->regmap, GENERAL_ASRC_MODE, mask << sft, rate_reg << sft);
584*e118015dSJiaxin Yu 
585*e118015dSJiaxin Yu 	return 0;
586*e118015dSJiaxin Yu }
587*e118015dSJiaxin Yu 
mtk_dai_src_hw_free(struct snd_pcm_substream * substream,struct snd_soc_dai * dai)588*e118015dSJiaxin Yu static int mtk_dai_src_hw_free(struct snd_pcm_substream *substream,
589*e118015dSJiaxin Yu 			       struct snd_soc_dai *dai)
590*e118015dSJiaxin Yu {
591*e118015dSJiaxin Yu 	struct mtk_base_afe *afe = snd_soc_dai_get_drvdata(dai);
592*e118015dSJiaxin Yu 	struct mt8186_afe_private *afe_priv = afe->platform_priv;
593*e118015dSJiaxin Yu 	int id = dai->id;
594*e118015dSJiaxin Yu 	struct mtk_afe_src_priv *src_priv = afe_priv->dai_priv[id];
595*e118015dSJiaxin Yu 
596*e118015dSJiaxin Yu 	dev_dbg(afe->dev, "%s(), id %d, stream %d\n",
597*e118015dSJiaxin Yu 		__func__, id, substream->stream);
598*e118015dSJiaxin Yu 
599*e118015dSJiaxin Yu 	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
600*e118015dSJiaxin Yu 		src_priv->dl_rate = 0;
601*e118015dSJiaxin Yu 	else
602*e118015dSJiaxin Yu 		src_priv->ul_rate = 0;
603*e118015dSJiaxin Yu 
604*e118015dSJiaxin Yu 	return 0;
605*e118015dSJiaxin Yu }
606*e118015dSJiaxin Yu 
607*e118015dSJiaxin Yu static const struct snd_soc_dai_ops mtk_dai_src_ops = {
608*e118015dSJiaxin Yu 	.hw_params = mtk_dai_src_hw_params,
609*e118015dSJiaxin Yu 	.hw_free = mtk_dai_src_hw_free,
610*e118015dSJiaxin Yu };
611*e118015dSJiaxin Yu 
612*e118015dSJiaxin Yu /* dai driver */
613*e118015dSJiaxin Yu #define MTK_SRC_RATES (SNDRV_PCM_RATE_8000_48000 |\
614*e118015dSJiaxin Yu 		       SNDRV_PCM_RATE_88200 |\
615*e118015dSJiaxin Yu 		       SNDRV_PCM_RATE_96000 |\
616*e118015dSJiaxin Yu 		       SNDRV_PCM_RATE_176400 |\
617*e118015dSJiaxin Yu 		       SNDRV_PCM_RATE_192000)
618*e118015dSJiaxin Yu 
619*e118015dSJiaxin Yu #define MTK_SRC_FORMATS (SNDRV_PCM_FMTBIT_S16_LE |\
620*e118015dSJiaxin Yu 			 SNDRV_PCM_FMTBIT_S24_LE |\
621*e118015dSJiaxin Yu 			 SNDRV_PCM_FMTBIT_S32_LE)
622*e118015dSJiaxin Yu 
623*e118015dSJiaxin Yu static struct snd_soc_dai_driver mtk_dai_src_driver[] = {
624*e118015dSJiaxin Yu 	{
625*e118015dSJiaxin Yu 		.name = "HW_SRC_1",
626*e118015dSJiaxin Yu 		.id = MT8186_DAI_SRC_1,
627*e118015dSJiaxin Yu 		.playback = {
628*e118015dSJiaxin Yu 			.stream_name = "HW_SRC_1_In",
629*e118015dSJiaxin Yu 			.channels_min = 1,
630*e118015dSJiaxin Yu 			.channels_max = 2,
631*e118015dSJiaxin Yu 			.rates = MTK_SRC_RATES,
632*e118015dSJiaxin Yu 			.formats = MTK_SRC_FORMATS,
633*e118015dSJiaxin Yu 		},
634*e118015dSJiaxin Yu 		.capture = {
635*e118015dSJiaxin Yu 			.stream_name = "HW_SRC_1_Out",
636*e118015dSJiaxin Yu 			.channels_min = 1,
637*e118015dSJiaxin Yu 			.channels_max = 2,
638*e118015dSJiaxin Yu 			.rates = MTK_SRC_RATES,
639*e118015dSJiaxin Yu 			.formats = MTK_SRC_FORMATS,
640*e118015dSJiaxin Yu 		},
641*e118015dSJiaxin Yu 		.ops = &mtk_dai_src_ops,
642*e118015dSJiaxin Yu 	},
643*e118015dSJiaxin Yu 	{
644*e118015dSJiaxin Yu 		.name = "HW_SRC_2",
645*e118015dSJiaxin Yu 		.id = MT8186_DAI_SRC_2,
646*e118015dSJiaxin Yu 		.playback = {
647*e118015dSJiaxin Yu 			.stream_name = "HW_SRC_2_In",
648*e118015dSJiaxin Yu 			.channels_min = 1,
649*e118015dSJiaxin Yu 			.channels_max = 2,
650*e118015dSJiaxin Yu 			.rates = MTK_SRC_RATES,
651*e118015dSJiaxin Yu 			.formats = MTK_SRC_FORMATS,
652*e118015dSJiaxin Yu 		},
653*e118015dSJiaxin Yu 		.capture = {
654*e118015dSJiaxin Yu 			.stream_name = "HW_SRC_2_Out",
655*e118015dSJiaxin Yu 			.channels_min = 1,
656*e118015dSJiaxin Yu 			.channels_max = 2,
657*e118015dSJiaxin Yu 			.rates = MTK_SRC_RATES,
658*e118015dSJiaxin Yu 			.formats = MTK_SRC_FORMATS,
659*e118015dSJiaxin Yu 		},
660*e118015dSJiaxin Yu 		.ops = &mtk_dai_src_ops,
661*e118015dSJiaxin Yu 	},
662*e118015dSJiaxin Yu };
663*e118015dSJiaxin Yu 
mt8186_dai_src_register(struct mtk_base_afe * afe)664*e118015dSJiaxin Yu int mt8186_dai_src_register(struct mtk_base_afe *afe)
665*e118015dSJiaxin Yu {
666*e118015dSJiaxin Yu 	struct mtk_base_afe_dai *dai;
667*e118015dSJiaxin Yu 	int ret;
668*e118015dSJiaxin Yu 
669*e118015dSJiaxin Yu 	dai = devm_kzalloc(afe->dev, sizeof(*dai), GFP_KERNEL);
670*e118015dSJiaxin Yu 	if (!dai)
671*e118015dSJiaxin Yu 		return -ENOMEM;
672*e118015dSJiaxin Yu 
673*e118015dSJiaxin Yu 	list_add(&dai->list, &afe->sub_dais);
674*e118015dSJiaxin Yu 
675*e118015dSJiaxin Yu 	dai->dai_drivers = mtk_dai_src_driver;
676*e118015dSJiaxin Yu 	dai->num_dai_drivers = ARRAY_SIZE(mtk_dai_src_driver);
677*e118015dSJiaxin Yu 
678*e118015dSJiaxin Yu 	dai->dapm_widgets = mtk_dai_src_widgets;
679*e118015dSJiaxin Yu 	dai->num_dapm_widgets = ARRAY_SIZE(mtk_dai_src_widgets);
680*e118015dSJiaxin Yu 	dai->dapm_routes = mtk_dai_src_routes;
681*e118015dSJiaxin Yu 	dai->num_dapm_routes = ARRAY_SIZE(mtk_dai_src_routes);
682*e118015dSJiaxin Yu 
683*e118015dSJiaxin Yu 	/* set dai priv */
684*e118015dSJiaxin Yu 	ret = mt8186_dai_set_priv(afe, MT8186_DAI_SRC_1,
685*e118015dSJiaxin Yu 				  sizeof(struct mtk_afe_src_priv), NULL);
686*e118015dSJiaxin Yu 	if (ret)
687*e118015dSJiaxin Yu 		return ret;
688*e118015dSJiaxin Yu 
689*e118015dSJiaxin Yu 	ret = mt8186_dai_set_priv(afe, MT8186_DAI_SRC_2,
690*e118015dSJiaxin Yu 				  sizeof(struct mtk_afe_src_priv), NULL);
691*e118015dSJiaxin Yu 	if (ret)
692*e118015dSJiaxin Yu 		return ret;
693*e118015dSJiaxin Yu 
694*e118015dSJiaxin Yu 	return 0;
695*e118015dSJiaxin Yu }
696