~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

TOMOYO Linux Cross Reference
Linux/sound/soc/mediatek/mt8186/mt8186-dai-src.c

Version: ~ [ linux-6.11.5 ] ~ [ linux-6.10.14 ] ~ [ linux-6.9.12 ] ~ [ linux-6.8.12 ] ~ [ linux-6.7.12 ] ~ [ linux-6.6.58 ] ~ [ linux-6.5.13 ] ~ [ linux-6.4.16 ] ~ [ linux-6.3.13 ] ~ [ linux-6.2.16 ] ~ [ linux-6.1.114 ] ~ [ linux-6.0.19 ] ~ [ linux-5.19.17 ] ~ [ linux-5.18.19 ] ~ [ linux-5.17.15 ] ~ [ linux-5.16.20 ] ~ [ linux-5.15.169 ] ~ [ linux-5.14.21 ] ~ [ linux-5.13.19 ] ~ [ linux-5.12.19 ] ~ [ linux-5.11.22 ] ~ [ linux-5.10.228 ] ~ [ linux-5.9.16 ] ~ [ linux-5.8.18 ] ~ [ linux-5.7.19 ] ~ [ linux-5.6.19 ] ~ [ linux-5.5.19 ] ~ [ linux-5.4.284 ] ~ [ linux-5.3.18 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.322 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.336 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.337 ] ~ [ linux-4.4.302 ] ~ [ linux-3.10.108 ] ~ [ linux-2.6.32.71 ] ~ [ linux-2.6.0 ] ~ [ linux-2.4.37.11 ] ~ [ unix-v6-master ] ~ [ ccs-tools-1.8.9 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

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

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

kernel.org | git.kernel.org | LWN.net | Project Home | SVN repository | Mail admin

Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.

sflogo.php