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

TOMOYO Linux Cross Reference
Linux/sound/soc/mediatek/mt8365/mt8365-dai-i2s.c

Version: ~ [ linux-6.12-rc7 ] ~ [ linux-6.11.7 ] ~ [ linux-6.10.14 ] ~ [ linux-6.9.12 ] ~ [ linux-6.8.12 ] ~ [ linux-6.7.12 ] ~ [ linux-6.6.60 ] ~ [ linux-6.5.13 ] ~ [ linux-6.4.16 ] ~ [ linux-6.3.13 ] ~ [ linux-6.2.16 ] ~ [ linux-6.1.116 ] ~ [ linux-6.0.19 ] ~ [ linux-5.19.17 ] ~ [ linux-5.18.19 ] ~ [ linux-5.17.15 ] ~ [ linux-5.16.20 ] ~ [ linux-5.15.171 ] ~ [ linux-5.14.21 ] ~ [ linux-5.13.19 ] ~ [ linux-5.12.19 ] ~ [ linux-5.11.22 ] ~ [ linux-5.10.229 ] ~ [ linux-5.9.16 ] ~ [ linux-5.8.18 ] ~ [ linux-5.7.19 ] ~ [ linux-5.6.19 ] ~ [ linux-5.5.19 ] ~ [ linux-5.4.285 ] ~ [ linux-5.3.18 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.323 ] ~ [ 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.12 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

  1 // SPDX-License-Identifier: GPL-2.0
  2 /*
  3  * MediaTek 8365 ALSA SoC Audio DAI I2S Control
  4  *
  5  * Copyright (c) 2024 MediaTek Inc.
  6  * Authors: Jia Zeng <jia.zeng@mediatek.com>
  7  *          Alexandre Mergnat <amergnat@baylibre.com>
  8  */
  9 
 10 #include <linux/bitops.h>
 11 #include <linux/regmap.h>
 12 #include <sound/pcm_params.h>
 13 #include "mt8365-afe-clk.h"
 14 #include "mt8365-afe-common.h"
 15 
 16 #define IIR_RATIOVER 9
 17 #define IIR_INV_COEF 10
 18 #define IIR_NO_NEED 11
 19 
 20 struct mtk_afe_i2s_priv {
 21         bool adda_link;
 22         int i2s_out_on_ref_cnt;
 23         int id;
 24         int low_jitter_en;
 25         int mclk_id;
 26         int share_i2s_id;
 27         unsigned int clk_id_in;
 28         unsigned int clk_id_in_m_sel;
 29         unsigned int clk_id_out;
 30         unsigned int clk_id_out_m_sel;
 31         unsigned int clk_in_mult;
 32         unsigned int clk_out_mult;
 33         unsigned int config_val_in;
 34         unsigned int config_val_out;
 35         unsigned int dynamic_bck;
 36         unsigned int reg_off_in;
 37         unsigned int reg_off_out;
 38 };
 39 
 40 /* This enum is merely for mtk_afe_i2s_priv declare */
 41 enum {
 42         DAI_I2S0 = 0,
 43         DAI_I2S3,
 44         DAI_I2S_NUM,
 45 };
 46 
 47 static const struct mtk_afe_i2s_priv mt8365_i2s_priv[DAI_I2S_NUM] = {
 48         [DAI_I2S0] = {
 49                 .id = MT8365_AFE_IO_I2S,
 50                 .mclk_id = MT8365_I2S0_MCK,
 51                 .share_i2s_id = -1,
 52                 .clk_id_in = MT8365_CLK_AUD_I2S2_M,
 53                 .clk_id_out = MT8365_CLK_AUD_I2S1_M,
 54                 .clk_id_in_m_sel = MT8365_CLK_I2S2_M_SEL,
 55                 .clk_id_out_m_sel = MT8365_CLK_I2S1_M_SEL,
 56                 .clk_in_mult = 256,
 57                 .clk_out_mult = 256,
 58                 .adda_link = true,
 59                 .config_val_out = AFE_I2S_CON1_I2S2_TO_PAD,
 60                 .reg_off_in = AFE_I2S_CON2,
 61                 .reg_off_out = AFE_I2S_CON1,
 62         },
 63         [DAI_I2S3] = {
 64                 .id = MT8365_AFE_IO_2ND_I2S,
 65                 .mclk_id = MT8365_I2S3_MCK,
 66                 .share_i2s_id = -1,
 67                 .clk_id_in = MT8365_CLK_AUD_I2S0_M,
 68                 .clk_id_out = MT8365_CLK_AUD_I2S3_M,
 69                 .clk_id_in_m_sel = MT8365_CLK_I2S0_M_SEL,
 70                 .clk_id_out_m_sel = MT8365_CLK_I2S3_M_SEL,
 71                 .clk_in_mult = 256,
 72                 .clk_out_mult = 256,
 73                 .adda_link = false,
 74                 .config_val_in = AFE_I2S_CON_FROM_IO_MUX,
 75                 .reg_off_in = AFE_I2S_CON,
 76                 .reg_off_out = AFE_I2S_CON3,
 77         },
 78 };
 79 
 80 static const u32 *get_iir_coef(unsigned int input_fs,
 81                                unsigned int output_fs, unsigned int *count)
 82 {
 83         static const u32 IIR_COEF_48_TO_44p1[30] = {
 84                 0x061fb0, 0x0bd256, 0x061fb0, 0xe3a3e6, 0xf0a300, 0x000003,
 85                 0x0e416d, 0x1bb577, 0x0e416d, 0xe59178, 0xf23637, 0x000003,
 86                 0x0c7d72, 0x189060, 0x0c7d72, 0xe96f09, 0xf505b2, 0x000003,
 87                 0x126054, 0x249143, 0x126054, 0xe1fc0c, 0xf4b20a, 0x000002,
 88                 0x000000, 0x323c85, 0x323c85, 0xf76d4e, 0x000000, 0x000002,
 89         };
 90 
 91         static const u32 IIR_COEF_44p1_TO_32[42] = {
 92                 0x0a6074, 0x0d237a, 0x0a6074, 0xdd8d6c, 0xe0b3f6, 0x000002,
 93                 0x0e41f8, 0x128d48, 0x0e41f8, 0xefc14e, 0xf12d7a, 0x000003,
 94                 0x0cfa60, 0x11e89c, 0x0cfa60, 0xf1b09e, 0xf27205, 0x000003,
 95                 0x15b69c, 0x20e7e4, 0x15b69c, 0xea799a, 0xe9314a, 0x000002,
 96                 0x0f79e2, 0x1a7064, 0x0f79e2, 0xf65e4a, 0xf03d8e, 0x000002,
 97                 0x10c34f, 0x1ffe4b, 0x10c34f, 0x0bbecb, 0xf2bc4b, 0x000001,
 98                 0x000000, 0x23b063, 0x23b063, 0x07335f, 0x000000, 0x000002,
 99         };
100 
101         static const u32 IIR_COEF_48_TO_32[42] = {
102                 0x0a2a9b, 0x0a2f05, 0x0a2a9b, 0xe73873, 0xe0c525, 0x000002,
103                 0x0dd4ad, 0x0e765a, 0x0dd4ad, 0xf49808, 0xf14844, 0x000003,
104                 0x18a8cd, 0x1c40d0, 0x18a8cd, 0xed2aab, 0xe542ec, 0x000002,
105                 0x13e044, 0x1a47c4, 0x13e044, 0xf44aed, 0xe9acc7, 0x000002,
106                 0x1abd9c, 0x2a5429, 0x1abd9c, 0xff3441, 0xe0fc5f, 0x000001,
107                 0x0d86db, 0x193e2e, 0x0d86db, 0x1a6f15, 0xf14507, 0x000001,
108                 0x000000, 0x1f820c, 0x1f820c, 0x0a1b1f, 0x000000, 0x000002,
109         };
110 
111         static const u32 IIR_COEF_32_TO_16[48] = {
112                 0x122893, 0xffadd4, 0x122893, 0x0bc205, 0xc0ee1c, 0x000001,
113                 0x1bab8a, 0x00750d, 0x1bab8a, 0x06a983, 0xe18a5c, 0x000002,
114                 0x18f68e, 0x02706f, 0x18f68e, 0x0886a9, 0xe31bcb, 0x000002,
115                 0x149c05, 0x054487, 0x149c05, 0x0bec31, 0xe5973e, 0x000002,
116                 0x0ea303, 0x07f24a, 0x0ea303, 0x115ff9, 0xe967b6, 0x000002,
117                 0x0823fd, 0x085531, 0x0823fd, 0x18d5b4, 0xee8d21, 0x000002,
118                 0x06888e, 0x0acbbb, 0x06888e, 0x40b55c, 0xe76dce, 0x000001,
119                 0x000000, 0x2d31a9, 0x2d31a9, 0x23ba4f, 0x000000, 0x000001,
120         };
121 
122         static const u32 IIR_COEF_96_TO_44p1[48] = {
123                 0x08b543, 0xfd80f4, 0x08b543, 0x0e2332, 0xe06ed0, 0x000002,
124                 0x1b6038, 0xf90e7e, 0x1b6038, 0x0ec1ac, 0xe16f66, 0x000002,
125                 0x188478, 0xfbb921, 0x188478, 0x105859, 0xe2e596, 0x000002,
126                 0x13eff3, 0xffa707, 0x13eff3, 0x13455c, 0xe533b7, 0x000002,
127                 0x0dc239, 0x03d458, 0x0dc239, 0x17f120, 0xe8b617, 0x000002,
128                 0x0745f1, 0x05d790, 0x0745f1, 0x1e3d75, 0xed5f18, 0x000002,
129                 0x05641f, 0x085e2b, 0x05641f, 0x48efd0, 0xe3e9c8, 0x000001,
130                 0x000000, 0x28f632, 0x28f632, 0x273905, 0x000000, 0x000001,
131         };
132 
133         static const u32 IIR_COEF_44p1_TO_16[48] = {
134                 0x0998fb, 0xf7f925, 0x0998fb, 0x1e54a0, 0xe06605, 0x000002,
135                 0x0d828e, 0xf50f97, 0x0d828e, 0x0f41b5, 0xf0a999, 0x000003,
136                 0x17ebeb, 0xee30d8, 0x17ebeb, 0x1f48ca, 0xe2ae88, 0x000002,
137                 0x12fab5, 0xf46ddc, 0x12fab5, 0x20cc51, 0xe4d068, 0x000002,
138                 0x0c7ac6, 0xfbd00e, 0x0c7ac6, 0x2337da, 0xe8028c, 0x000002,
139                 0x060ddc, 0x015b3e, 0x060ddc, 0x266754, 0xec21b6, 0x000002,
140                 0x0407b5, 0x04f827, 0x0407b5, 0x52e3d0, 0xe0149f, 0x000001,
141                 0x000000, 0x1f9521, 0x1f9521, 0x2ac116, 0x000000, 0x000001,
142         };
143 
144         static const u32 IIR_COEF_48_TO_16[48] = {
145                 0x0955ff, 0xf6544a, 0x0955ff, 0x2474e5, 0xe062e6, 0x000002,
146                 0x0d4180, 0xf297f4, 0x0d4180, 0x12415b, 0xf0a3b0, 0x000003,
147                 0x0ba079, 0xf4f0b0, 0x0ba079, 0x1285d3, 0xf1488b, 0x000003,
148                 0x12247c, 0xf1033c, 0x12247c, 0x2625be, 0xe48e0d, 0x000002,
149                 0x0b98e0, 0xf96d1a, 0x0b98e0, 0x27e79c, 0xe7798a, 0x000002,
150                 0x055e3b, 0xffed09, 0x055e3b, 0x2a2e2d, 0xeb2854, 0x000002,
151                 0x01a934, 0x01ca03, 0x01a934, 0x2c4fea, 0xee93ab, 0x000002,
152                 0x000000, 0x1c46c5, 0x1c46c5, 0x2d37dc, 0x000000, 0x000001,
153         };
154 
155         static const u32 IIR_COEF_96_TO_16[48] = {
156                 0x0805a1, 0xf21ae3, 0x0805a1, 0x3840bb, 0xe02a2e, 0x000002,
157                 0x0d5dd8, 0xe8f259, 0x0d5dd8, 0x1c0af6, 0xf04700, 0x000003,
158                 0x0bb422, 0xec08d9, 0x0bb422, 0x1bfccc, 0xf09216, 0x000003,
159                 0x08fde6, 0xf108be, 0x08fde6, 0x1bf096, 0xf10ae0, 0x000003,
160                 0x0ae311, 0xeeeda3, 0x0ae311, 0x37c646, 0xe385f5, 0x000002,
161                 0x044089, 0xfa7242, 0x044089, 0x37a785, 0xe56526, 0x000002,
162                 0x00c75c, 0xffb947, 0x00c75c, 0x378ba3, 0xe72c5f, 0x000002,
163                 0x000000, 0x0ef76e, 0x0ef76e, 0x377fda, 0x000000, 0x000001,
164         };
165 
166         static const struct {
167                 const u32 *coef;
168                 unsigned int cnt;
169         } iir_coef_tbl_list[8] = {
170                 /* 0: 0.9188 */
171                 { IIR_COEF_48_TO_44p1, ARRAY_SIZE(IIR_COEF_48_TO_44p1) },
172                 /* 1: 0.7256 */
173                 { IIR_COEF_44p1_TO_32, ARRAY_SIZE(IIR_COEF_44p1_TO_32) },
174                 /* 2: 0.6667 */
175                 { IIR_COEF_48_TO_32, ARRAY_SIZE(IIR_COEF_48_TO_32) },
176                 /* 3: 0.5 */
177                 { IIR_COEF_32_TO_16, ARRAY_SIZE(IIR_COEF_32_TO_16) },
178                 /* 4: 0.4594 */
179                 { IIR_COEF_96_TO_44p1, ARRAY_SIZE(IIR_COEF_96_TO_44p1) },
180                 /* 5: 0.3628 */
181                 { IIR_COEF_44p1_TO_16, ARRAY_SIZE(IIR_COEF_44p1_TO_16) },
182                 /* 6: 0.3333 */
183                 { IIR_COEF_48_TO_16, ARRAY_SIZE(IIR_COEF_48_TO_16) },
184                 /* 7: 0.1667 */
185                 { IIR_COEF_96_TO_16, ARRAY_SIZE(IIR_COEF_96_TO_16) },
186         };
187 
188         static const u32 freq_new_index[16] = {
189                 0, 1, 2, 99, 3, 4, 5, 99, 6, 7, 8, 9, 10, 11, 12, 99
190         };
191 
192         static const u32 iir_coef_tbl_matrix[13][13] = {
193                 {/**/
194                         IIR_NO_NEED, IIR_NO_NEED, IIR_NO_NEED, IIR_NO_NEED, IIR_NO_NEED,
195                         IIR_NO_NEED, IIR_NO_NEED, IIR_NO_NEED, IIR_NO_NEED, IIR_NO_NEED,
196                         IIR_NO_NEED, IIR_NO_NEED, IIR_NO_NEED
197                 },
198                 {/*1*/
199                         1, IIR_NO_NEED, IIR_NO_NEED, IIR_NO_NEED, IIR_NO_NEED,
200                         IIR_NO_NEED, IIR_NO_NEED, IIR_NO_NEED, IIR_NO_NEED,
201                         IIR_NO_NEED, IIR_NO_NEED, IIR_NO_NEED, IIR_NO_NEED
202                 },
203                 {/*2*/
204                         2, 0, IIR_NO_NEED, IIR_NO_NEED, IIR_NO_NEED, IIR_NO_NEED,
205                         IIR_NO_NEED, IIR_NO_NEED, IIR_NO_NEED, IIR_NO_NEED,
206                         IIR_NO_NEED, IIR_NO_NEED, IIR_NO_NEED
207                 },
208                 {/*3*/
209                         3, IIR_INV_COEF, IIR_INV_COEF, IIR_NO_NEED, IIR_NO_NEED,
210                         IIR_NO_NEED, IIR_NO_NEED, IIR_NO_NEED, IIR_NO_NEED,
211                         IIR_NO_NEED, IIR_NO_NEED, IIR_NO_NEED, IIR_NO_NEED
212                 },
213                 {/*4*/
214                         5, 3, IIR_INV_COEF, 2, IIR_NO_NEED, IIR_NO_NEED,
215                         IIR_NO_NEED, IIR_NO_NEED, IIR_NO_NEED,
216                         IIR_NO_NEED, IIR_NO_NEED, IIR_NO_NEED, IIR_NO_NEED
217                 },
218                 {/*5*/
219                         6, 4, 3, 2, 0, IIR_NO_NEED, IIR_NO_NEED, IIR_NO_NEED,
220                         IIR_NO_NEED, IIR_NO_NEED, IIR_NO_NEED,
221                         IIR_NO_NEED, IIR_NO_NEED
222                 },
223                 {/*6*/
224                         IIR_INV_COEF, IIR_INV_COEF, IIR_INV_COEF, 3, IIR_INV_COEF,
225                         IIR_INV_COEF, IIR_NO_NEED, IIR_NO_NEED, IIR_NO_NEED,
226                         IIR_NO_NEED, IIR_NO_NEED, IIR_NO_NEED
227                 },
228                 {/*7*/
229                         IIR_INV_COEF, IIR_INV_COEF, IIR_INV_COEF, 5, 3,
230                         IIR_INV_COEF, 1, IIR_NO_NEED, IIR_NO_NEED,
231                         IIR_NO_NEED, IIR_NO_NEED, IIR_NO_NEED, IIR_NO_NEED
232                 },
233                 {/*8*/
234                         7, IIR_INV_COEF, IIR_INV_COEF, 6, 4, 3, 2, 0, IIR_NO_NEED,
235                         IIR_NO_NEED, IIR_NO_NEED, IIR_NO_NEED, IIR_NO_NEED
236                 },
237                 {/*9*/
238                         IIR_INV_COEF, IIR_INV_COEF, IIR_INV_COEF, IIR_INV_COEF,
239                         IIR_INV_COEF, IIR_INV_COEF, 5, 3, IIR_INV_COEF,
240                         IIR_NO_NEED, IIR_NO_NEED, IIR_NO_NEED, IIR_NO_NEED
241                 },
242                 {/*10*/
243                         IIR_INV_COEF, IIR_INV_COEF, IIR_INV_COEF, 7, IIR_INV_COEF,
244                         IIR_INV_COEF, 6, 4, 3, 0,
245                         IIR_NO_NEED, IIR_NO_NEED, IIR_NO_NEED
246                 },
247                 { /*11*/
248                         IIR_RATIOVER, IIR_INV_COEF, IIR_INV_COEF, IIR_INV_COEF,
249                         IIR_INV_COEF, IIR_INV_COEF, IIR_INV_COEF, IIR_INV_COEF,
250                         IIR_INV_COEF, 3, IIR_INV_COEF, IIR_NO_NEED, IIR_NO_NEED
251                 },
252                 {/*12*/
253                         IIR_RATIOVER, IIR_RATIOVER, IIR_INV_COEF, IIR_INV_COEF,
254                         IIR_INV_COEF, IIR_INV_COEF, 7, IIR_INV_COEF,
255                         IIR_INV_COEF, 4, 3, 0, IIR_NO_NEED
256                 },
257         };
258 
259         const u32 *coef = NULL;
260         unsigned int cnt = 0;
261         u32 i = freq_new_index[input_fs];
262         u32 j = freq_new_index[output_fs];
263 
264         if (i < 13 && j < 13) {
265                 u32 k = iir_coef_tbl_matrix[i][j];
266 
267                 if (k >= IIR_NO_NEED) {
268                 } else if (k == IIR_RATIOVER) {
269                 } else if (k == IIR_INV_COEF) {
270                 } else {
271                         coef = iir_coef_tbl_list[k].coef;
272                         cnt = iir_coef_tbl_list[k].cnt;
273                 }
274         }
275         *count = cnt;
276         return coef;
277 }
278 
279 static int mt8365_dai_set_config(struct mtk_base_afe *afe,
280                                  struct mtk_afe_i2s_priv *i2s_data,
281                                  bool is_input, unsigned int rate,
282                                  int bit_width)
283 {
284         struct mt8365_afe_private *afe_priv = afe->platform_priv;
285         struct mt8365_be_dai_data *be =
286         &afe_priv->be_data[i2s_data->id - MT8365_AFE_BACKEND_BASE];
287         unsigned int val, reg_off;
288         int fs = mt8365_afe_fs_timing(rate);
289 
290         if (fs < 0)
291                 return -EINVAL;
292 
293         val = AFE_I2S_CON_LOW_JITTER_CLK | AFE_I2S_CON_FORMAT_I2S;
294         val |= FIELD_PREP(AFE_I2S_CON_RATE_MASK, fs);
295 
296         if (is_input) {
297                 reg_off = i2s_data->reg_off_in;
298                 if (i2s_data->adda_link)
299                         val |= i2s_data->config_val_in;
300         } else {
301                 reg_off = i2s_data->reg_off_out;
302                 val |= i2s_data->config_val_in;
303         }
304 
305         /* 1:bck=32lrck(16bit) or bck=64lrck(32bit) 0:fix bck=64lrck */
306         if (i2s_data->dynamic_bck) {
307                 if (bit_width > 16)
308                         val |= AFE_I2S_CON_WLEN_32BIT;
309                 else
310                         val &= ~(u32)AFE_I2S_CON_WLEN_32BIT;
311         } else {
312                 val |= AFE_I2S_CON_WLEN_32BIT;
313         }
314 
315         if ((be->fmt_mode & SND_SOC_DAIFMT_MASTER_MASK) ==
316             SND_SOC_DAIFMT_CBM_CFM) {
317                 val |= AFE_I2S_CON_SRC_SLAVE;
318                 val &= ~(u32)AFE_I2S_CON_FROM_IO_MUX;//from consys
319         }
320 
321         regmap_update_bits(afe->regmap, reg_off, ~(u32)AFE_I2S_CON_EN, val);
322 
323         if (i2s_data->adda_link && is_input)
324                 regmap_update_bits(afe->regmap, AFE_ADDA_TOP_CON0, 0x1, 0x1);
325 
326         return 0;
327 }
328 
329 int mt8365_afe_set_i2s_out(struct mtk_base_afe *afe,
330                            unsigned int rate, int bit_width)
331 {
332         struct mt8365_afe_private *afe_priv = afe->platform_priv;
333         struct mtk_afe_i2s_priv *i2s_data =
334                 afe_priv->dai_priv[MT8365_AFE_IO_I2S];
335 
336         return mt8365_dai_set_config(afe, i2s_data, false, rate, bit_width);
337 }
338 
339 static int mt8365_afe_set_2nd_i2s_asrc(struct mtk_base_afe *afe,
340                                        unsigned int rate_in,
341                                        unsigned int rate_out,
342                                        unsigned int width,
343                                        unsigned int mono,
344                                        int o16bit, int tracking)
345 {
346         int ifs, ofs = 0;
347         unsigned int val = 0;
348         unsigned int mask = 0;
349         const u32 *coef;
350         u32 iir_stage;
351         unsigned int coef_count = 0;
352 
353         ifs = mt8365_afe_fs_timing(rate_in);
354 
355         if (ifs < 0)
356                 return -EINVAL;
357 
358         ofs = mt8365_afe_fs_timing(rate_out);
359 
360         if (ofs < 0)
361                 return -EINVAL;
362 
363         val = FIELD_PREP(O16BIT, o16bit) | FIELD_PREP(IS_MONO, mono);
364         regmap_update_bits(afe->regmap, AFE_ASRC_2CH_CON2,
365                            O16BIT | IS_MONO, val);
366 
367         coef = get_iir_coef(ifs, ofs, &coef_count);
368         iir_stage = ((u32)coef_count / 6) - 1;
369 
370         if (coef) {
371                 unsigned int i;
372 
373                 /* CPU control IIR coeff SRAM */
374                 regmap_update_bits(afe->regmap, AFE_ASRC_2CH_CON0,
375                                    COEFF_SRAM_CTRL, COEFF_SRAM_CTRL);
376 
377                 /* set to 0, IIR coeff SRAM addr */
378                 regmap_update_bits(afe->regmap, AFE_ASRC_2CH_CON13,
379                                    0xffffffff, 0x0);
380 
381                 for (i = 0; i < coef_count; ++i)
382                         regmap_update_bits(afe->regmap, AFE_ASRC_2CH_CON12,
383                                            0xffffffff, coef[i]);
384 
385                 /* disable IIR coeff SRAM access */
386                 regmap_update_bits(afe->regmap, AFE_ASRC_2CH_CON0,
387                                    COEFF_SRAM_CTRL,
388                                    ~COEFF_SRAM_CTRL);
389                 regmap_update_bits(afe->regmap, AFE_ASRC_2CH_CON2,
390                                    CLR_IIR_HISTORY | IIR_EN | IIR_STAGE_MASK,
391                                    CLR_IIR_HISTORY | IIR_EN |
392                                    FIELD_PREP(IIR_STAGE_MASK, iir_stage));
393         } else {
394                 /* disable IIR */
395                 regmap_update_bits(afe->regmap, AFE_ASRC_2CH_CON2,
396                                    IIR_EN, ~IIR_EN);
397         }
398 
399         /* CON3 setting (RX OFS) */
400         regmap_update_bits(afe->regmap, AFE_ASRC_2CH_CON3,
401                            0x00FFFFFF, rx_frequency_palette(ofs));
402         /* CON4 setting (RX IFS) */
403         regmap_update_bits(afe->regmap, AFE_ASRC_2CH_CON4,
404                            0x00FFFFFF, rx_frequency_palette(ifs));
405 
406         /* CON5 setting */
407         if (tracking) {
408                 val = CALI_64_CYCLE |
409                       CALI_AUTORST |
410                       AUTO_TUNE_FREQ5 |
411                       COMP_FREQ_RES |
412                       CALI_BP_DGL |
413                       CALI_AUTO_RESTART |
414                       CALI_USE_FREQ_OUT |
415                       CALI_SEL_01;
416 
417                 mask = CALI_CYCLE_MASK |
418                        CALI_AUTORST |
419                        AUTO_TUNE_FREQ5 |
420                        COMP_FREQ_RES |
421                        CALI_SEL_MASK |
422                        CALI_BP_DGL |
423                        AUTO_TUNE_FREQ4 |
424                        CALI_AUTO_RESTART |
425                        CALI_USE_FREQ_OUT |
426                        CALI_ON;
427 
428                 regmap_update_bits(afe->regmap, AFE_ASRC_2CH_CON5,
429                                    mask, val);
430                 regmap_update_bits(afe->regmap, AFE_ASRC_2CH_CON5,
431                                    CALI_ON, CALI_ON);
432         } else {
433                 regmap_update_bits(afe->regmap, AFE_ASRC_2CH_CON5,
434                                    0xffffffff, 0x0);
435         }
436         /* CON6 setting fix 8125 */
437         regmap_update_bits(afe->regmap, AFE_ASRC_2CH_CON6,
438                            0x0000ffff, 0x1FBD);
439         /* CON9 setting (RX IFS) */
440         regmap_update_bits(afe->regmap, AFE_ASRC_2CH_CON9,
441                            0x000fffff, AutoRstThHi(ifs));
442         /* CON10 setting (RX IFS) */
443         regmap_update_bits(afe->regmap, AFE_ASRC_2CH_CON10,
444                            0x000fffff, AutoRstThLo(ifs));
445         regmap_update_bits(afe->regmap, AFE_ASRC_2CH_CON0,
446                            CHSET_STR_CLR, CHSET_STR_CLR);
447 
448         return 0;
449 }
450 
451 static int mt8365_afe_set_2nd_i2s_asrc_enable(struct mtk_base_afe *afe,
452                                               bool enable)
453 {
454         if (enable)
455                 regmap_update_bits(afe->regmap, AFE_ASRC_2CH_CON0,
456                                    ASM_ON, ASM_ON);
457         else
458                 regmap_update_bits(afe->regmap, AFE_ASRC_2CH_CON0,
459                                    ASM_ON, ~ASM_ON);
460         return 0;
461 }
462 
463 void mt8365_afe_set_i2s_out_enable(struct mtk_base_afe *afe, bool enable)
464 {
465         int i;
466         unsigned long flags;
467         struct mt8365_afe_private *afe_priv = afe->platform_priv;
468         struct mtk_afe_i2s_priv *i2s_data = NULL;
469 
470         for (i = 0; i < DAI_I2S_NUM; i++) {
471                 if (mt8365_i2s_priv[i].adda_link)
472                         i2s_data = afe_priv->dai_priv[mt8365_i2s_priv[i].id];
473         }
474 
475         if (!i2s_data)
476                 return;
477 
478         spin_lock_irqsave(&afe_priv->afe_ctrl_lock, flags);
479 
480         if (enable) {
481                 i2s_data->i2s_out_on_ref_cnt++;
482                 if (i2s_data->i2s_out_on_ref_cnt == 1)
483                         regmap_update_bits(afe->regmap, AFE_I2S_CON1,
484                                            0x1, enable);
485         } else {
486                 i2s_data->i2s_out_on_ref_cnt--;
487                 if (i2s_data->i2s_out_on_ref_cnt == 0)
488                         regmap_update_bits(afe->regmap, AFE_I2S_CON1,
489                                            0x1, enable);
490                 else if (i2s_data->i2s_out_on_ref_cnt < 0)
491                         i2s_data->i2s_out_on_ref_cnt = 0;
492         }
493 
494         spin_unlock_irqrestore(&afe_priv->afe_ctrl_lock, flags);
495 }
496 
497 static void mt8365_dai_set_enable(struct mtk_base_afe *afe,
498                                   struct mtk_afe_i2s_priv *i2s_data,
499                                   bool is_input, bool enable)
500 {
501         unsigned int reg_off;
502 
503         if (is_input) {
504                 reg_off = i2s_data->reg_off_in;
505         } else {
506                 if (i2s_data->adda_link) {
507                         mt8365_afe_set_i2s_out_enable(afe, enable);
508                         return;
509                 }
510                 reg_off = i2s_data->reg_off_out;
511         }
512         regmap_update_bits(afe->regmap, reg_off,
513                            0x1, enable);
514 }
515 
516 static int mt8365_dai_i2s_startup(struct snd_pcm_substream *substream,
517                                   struct snd_soc_dai *dai)
518 {
519         struct mtk_base_afe *afe = snd_soc_dai_get_drvdata(dai);
520         struct mt8365_afe_private *afe_priv = afe->platform_priv;
521         struct mtk_afe_i2s_priv *i2s_data = afe_priv->dai_priv[dai->id];
522         struct mt8365_be_dai_data *be = &afe_priv->be_data[dai->id - MT8365_AFE_BACKEND_BASE];
523         bool i2s_in_slave =
524                 (substream->stream == SNDRV_PCM_STREAM_CAPTURE) &&
525                 ((be->fmt_mode & SND_SOC_DAIFMT_MASTER_MASK) ==
526                 SND_SOC_DAIFMT_CBM_CFM);
527 
528         mt8365_afe_enable_main_clk(afe);
529 
530         if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
531                 clk_prepare_enable(afe_priv->clocks[i2s_data->clk_id_out]);
532 
533         if (substream->stream == SNDRV_PCM_STREAM_CAPTURE && !i2s_in_slave)
534                 clk_prepare_enable(afe_priv->clocks[i2s_data->clk_id_in]);
535 
536         if (i2s_in_slave)
537                 mt8365_afe_enable_top_cg(afe, MT8365_TOP_CG_I2S_IN);
538 
539         return 0;
540 }
541 
542 static void mt8365_dai_i2s_shutdown(struct snd_pcm_substream *substream,
543                                     struct snd_soc_dai *dai)
544 {
545         struct mtk_base_afe *afe = snd_soc_dai_get_drvdata(dai);
546         struct mt8365_afe_private *afe_priv = afe->platform_priv;
547         struct mtk_afe_i2s_priv *i2s_data = afe_priv->dai_priv[dai->id];
548         struct mt8365_be_dai_data *be = &afe_priv->be_data[dai->id - MT8365_AFE_BACKEND_BASE];
549         bool reset_i2s_out_change = (substream->stream == SNDRV_PCM_STREAM_PLAYBACK);
550         bool reset_i2s_in_change = (substream->stream == SNDRV_PCM_STREAM_CAPTURE);
551         bool i2s_in_slave =
552                 (substream->stream == SNDRV_PCM_STREAM_CAPTURE) &&
553                 ((be->fmt_mode & SND_SOC_DAIFMT_MASTER_MASK) ==
554                 SND_SOC_DAIFMT_CBM_CFM);
555 
556         if (be->prepared[substream->stream]) {
557                 if (reset_i2s_out_change)
558                         mt8365_dai_set_enable(afe, i2s_data, false, false);
559 
560                 if (reset_i2s_in_change)
561                         mt8365_dai_set_enable(afe, i2s_data, true, false);
562 
563                 if (substream->runtime->rate % 8000)
564                         mt8365_afe_disable_apll_associated_cfg(afe, MT8365_AFE_APLL1);
565                 else
566                         mt8365_afe_disable_apll_associated_cfg(afe, MT8365_AFE_APLL2);
567 
568                 if (reset_i2s_out_change)
569                         be->prepared[SNDRV_PCM_STREAM_PLAYBACK] = false;
570 
571                 if (reset_i2s_in_change)
572                         be->prepared[SNDRV_PCM_STREAM_CAPTURE] = false;
573         }
574 
575         if (reset_i2s_out_change)
576                 mt8365_afe_disable_clk(afe,
577                                        afe_priv->clocks[i2s_data->clk_id_out]);
578 
579         if (reset_i2s_in_change && !i2s_in_slave)
580                 mt8365_afe_disable_clk(afe,
581                                        afe_priv->clocks[i2s_data->clk_id_in]);
582 
583         if (i2s_in_slave)
584                 mt8365_afe_disable_top_cg(afe, MT8365_TOP_CG_I2S_IN);
585 
586         mt8365_afe_disable_main_clk(afe);
587 }
588 
589 static int mt8365_dai_i2s_prepare(struct snd_pcm_substream *substream,
590                                   struct snd_soc_dai *dai)
591 {
592         struct mtk_base_afe *afe = snd_soc_dai_get_drvdata(dai);
593         struct mt8365_afe_private *afe_priv = afe->platform_priv;
594         struct mtk_afe_i2s_priv *i2s_data = afe_priv->dai_priv[dai->id];
595         struct mt8365_be_dai_data *be = &afe_priv->be_data[dai->id - MT8365_AFE_BACKEND_BASE];
596         bool apply_i2s_out_change = (substream->stream == SNDRV_PCM_STREAM_PLAYBACK);
597         bool apply_i2s_in_change = (substream->stream == SNDRV_PCM_STREAM_CAPTURE);
598         unsigned int rate = substream->runtime->rate;
599         int bit_width = snd_pcm_format_width(substream->runtime->format);
600         int ret;
601 
602         if (be->prepared[substream->stream]) {
603                 dev_info(afe->dev, "%s '%s' prepared already\n",
604                          __func__, snd_pcm_stream_str(substream));
605                 return 0;
606         }
607 
608         if (apply_i2s_out_change) {
609                 ret = mt8365_dai_set_config(afe, i2s_data, false, rate, bit_width);
610                 if (ret)
611                         return ret;
612         }
613 
614         if (apply_i2s_in_change) {
615                 if ((be->fmt_mode & SND_SOC_DAIFMT_MASTER_MASK)
616                     == SND_SOC_DAIFMT_CBM_CFM) {
617                         ret = mt8365_afe_set_2nd_i2s_asrc(afe, 32000, rate,
618                                                           (unsigned int)bit_width,
619                                                           0, 0, 1);
620                         if (ret < 0)
621                                 return ret;
622                 }
623                 ret = mt8365_dai_set_config(afe, i2s_data, true, rate, bit_width);
624                 if (ret)
625                         return ret;
626         }
627 
628         if (rate % 8000)
629                 mt8365_afe_enable_apll_associated_cfg(afe, MT8365_AFE_APLL1);
630         else
631                 mt8365_afe_enable_apll_associated_cfg(afe, MT8365_AFE_APLL2);
632 
633         if (apply_i2s_out_change) {
634                 mt8365_afe_set_clk_parent(afe,
635                                           afe_priv->clocks[i2s_data->clk_id_out_m_sel],
636                                           ((rate % 8000) ?
637                                           afe_priv->clocks[MT8365_CLK_AUD1] :
638                                           afe_priv->clocks[MT8365_CLK_AUD2]));
639 
640                 mt8365_afe_set_clk_rate(afe,
641                                         afe_priv->clocks[i2s_data->clk_id_out],
642                                         rate * i2s_data->clk_out_mult);
643 
644                 mt8365_dai_set_enable(afe, i2s_data, false, true);
645                 be->prepared[SNDRV_PCM_STREAM_PLAYBACK] = true;
646         }
647 
648         if (apply_i2s_in_change) {
649                 mt8365_afe_set_clk_parent(afe,
650                                           afe_priv->clocks[i2s_data->clk_id_in_m_sel],
651                                           ((rate % 8000) ?
652                                           afe_priv->clocks[MT8365_CLK_AUD1] :
653                                           afe_priv->clocks[MT8365_CLK_AUD2]));
654 
655                 mt8365_afe_set_clk_rate(afe,
656                                         afe_priv->clocks[i2s_data->clk_id_in],
657                                         rate * i2s_data->clk_in_mult);
658 
659                 mt8365_dai_set_enable(afe, i2s_data, true, true);
660 
661                 if ((be->fmt_mode & SND_SOC_DAIFMT_MASTER_MASK)
662                     == SND_SOC_DAIFMT_CBM_CFM)
663                         mt8365_afe_set_2nd_i2s_asrc_enable(afe, true);
664 
665                 be->prepared[SNDRV_PCM_STREAM_CAPTURE] = true;
666         }
667         return 0;
668 }
669 
670 static int mt8365_afe_2nd_i2s_hw_params(struct snd_pcm_substream *substream,
671                                         struct snd_pcm_hw_params *params,
672                                         struct snd_soc_dai *dai)
673 {
674         struct mtk_base_afe *afe = snd_soc_dai_get_drvdata(dai);
675         unsigned int width_val = params_width(params) > 16 ?
676                 (AFE_CONN_24BIT_O00 | AFE_CONN_24BIT_O01) : 0;
677 
678         if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
679                 regmap_update_bits(afe->regmap, AFE_CONN_24BIT,
680                                    AFE_CONN_24BIT_O00 | AFE_CONN_24BIT_O01, width_val);
681 
682         return 0;
683 }
684 
685 static int mt8365_afe_2nd_i2s_set_fmt(struct snd_soc_dai *dai, unsigned int fmt)
686 {
687         struct mtk_base_afe *afe = snd_soc_dai_get_drvdata(dai);
688         struct mt8365_afe_private *afe_priv = afe->platform_priv;
689         struct mt8365_be_dai_data *be = &afe_priv->be_data[dai->id - MT8365_AFE_BACKEND_BASE];
690 
691         be->fmt_mode = 0;
692 
693         switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
694         case SND_SOC_DAIFMT_I2S:
695                 be->fmt_mode |= SND_SOC_DAIFMT_I2S;
696                 break;
697         case SND_SOC_DAIFMT_LEFT_J:
698                 be->fmt_mode |= SND_SOC_DAIFMT_LEFT_J;
699                 break;
700         default:
701                 dev_err(afe->dev, "invalid audio format for 2nd i2s!\n");
702                 return -EINVAL;
703         }
704 
705         if (((fmt & SND_SOC_DAIFMT_INV_MASK) != SND_SOC_DAIFMT_NB_NF) &&
706             ((fmt & SND_SOC_DAIFMT_INV_MASK) != SND_SOC_DAIFMT_NB_IF) &&
707             ((fmt & SND_SOC_DAIFMT_INV_MASK) != SND_SOC_DAIFMT_IB_NF) &&
708             ((fmt & SND_SOC_DAIFMT_INV_MASK) != SND_SOC_DAIFMT_IB_IF)) {
709                 dev_err(afe->dev, "invalid audio format for 2nd i2s!\n");
710                 return -EINVAL;
711         }
712 
713         be->fmt_mode |= (fmt & SND_SOC_DAIFMT_INV_MASK);
714 
715         if (((fmt & SND_SOC_DAIFMT_MASTER_MASK) == SND_SOC_DAIFMT_CBM_CFM))
716                 be->fmt_mode |= (fmt & SND_SOC_DAIFMT_MASTER_MASK);
717 
718         return 0;
719 }
720 
721 static const struct snd_soc_dai_ops mt8365_afe_i2s_ops = {
722         .startup        = mt8365_dai_i2s_startup,
723         .shutdown       = mt8365_dai_i2s_shutdown,
724         .prepare        = mt8365_dai_i2s_prepare,
725 };
726 
727 static const struct snd_soc_dai_ops mt8365_afe_2nd_i2s_ops = {
728         .startup        = mt8365_dai_i2s_startup,
729         .shutdown       = mt8365_dai_i2s_shutdown,
730         .hw_params      = mt8365_afe_2nd_i2s_hw_params,
731         .prepare        = mt8365_dai_i2s_prepare,
732         .set_fmt        = mt8365_afe_2nd_i2s_set_fmt,
733 };
734 
735 static struct snd_soc_dai_driver mtk_dai_i2s_driver[] = {
736         {
737                 .name = "I2S",
738                 .id = MT8365_AFE_IO_I2S,
739                 .playback = {
740                         .stream_name = "I2S Playback",
741                         .channels_min = 1,
742                         .channels_max = 2,
743                         .rates = SNDRV_PCM_RATE_8000_192000,
744                         .formats = SNDRV_PCM_FMTBIT_S16_LE |
745                                    SNDRV_PCM_FMTBIT_S24_LE |
746                                    SNDRV_PCM_FMTBIT_S32_LE,
747                 },
748                 .capture = {
749                         .stream_name = "I2S Capture",
750                         .channels_min = 1,
751                         .channels_max = 2,
752                         .rates = SNDRV_PCM_RATE_8000_192000,
753                         .formats = SNDRV_PCM_FMTBIT_S16_LE |
754                                    SNDRV_PCM_FMTBIT_S24_LE |
755                                    SNDRV_PCM_FMTBIT_S32_LE,
756                 },
757                 .ops = &mt8365_afe_i2s_ops,
758         }, {
759                 .name = "2ND I2S",
760                 .id = MT8365_AFE_IO_2ND_I2S,
761                 .playback = {
762                         .stream_name = "2ND I2S Playback",
763                         .channels_min = 1,
764                         .channels_max = 2,
765                         .rates = SNDRV_PCM_RATE_8000_192000,
766                         .formats = SNDRV_PCM_FMTBIT_S16_LE |
767                                    SNDRV_PCM_FMTBIT_S24_LE |
768                                    SNDRV_PCM_FMTBIT_S32_LE,
769                 },
770                 .capture = {
771                         .stream_name = "2ND I2S Capture",
772                         .channels_min = 1,
773                         .channels_max = 2,
774                         .rates = SNDRV_PCM_RATE_8000_192000,
775                         .formats = SNDRV_PCM_FMTBIT_S16_LE |
776                                    SNDRV_PCM_FMTBIT_S24_LE |
777                                    SNDRV_PCM_FMTBIT_S32_LE,
778                 },
779                 .ops = &mt8365_afe_2nd_i2s_ops,
780         }
781 };
782 
783 static const char * const fmi2sin_text[] = {
784         "OPEN", "FM_2ND_I2S_IN"
785 };
786 
787 static SOC_ENUM_SINGLE_VIRT_DECL(fmi2sin_enum, fmi2sin_text);
788 
789 static const struct snd_kcontrol_new fmi2sin_mux =
790         SOC_DAPM_ENUM("FM 2ND I2S Source", fmi2sin_enum);
791 
792 static const struct snd_kcontrol_new i2s_o03_o04_enable_ctl =
793         SOC_DAPM_SINGLE_VIRT("Switch", 1);
794 
795 static const struct snd_soc_dapm_widget mtk_dai_i2s_widgets[] = {
796         SND_SOC_DAPM_SWITCH("I2S O03_O04", SND_SOC_NOPM, 0, 0,
797                             &i2s_o03_o04_enable_ctl),
798         SND_SOC_DAPM_MUX("FM 2ND I2S Mux", SND_SOC_NOPM, 0, 0, &fmi2sin_mux),
799         SND_SOC_DAPM_INPUT("2ND I2S In"),
800 };
801 
802 static const struct snd_soc_dapm_route mtk_dai_i2s_routes[] = {
803         {"I2S O03_O04", "Switch", "O03"},
804         {"I2S O03_O04", "Switch", "O04"},
805         {"I2S Playback", NULL, "I2S O03_O04"},
806         {"2ND I2S Playback", NULL, "O00"},
807         {"2ND I2S Playback", NULL, "O01"},
808         {"2ND I2S Capture", NULL, "2ND I2S In"},
809         {"FM 2ND I2S Mux", "FM_2ND_I2S_IN", "2ND I2S Capture"},
810 };
811 
812 static int mt8365_dai_i2s_set_priv(struct mtk_base_afe *afe)
813 {
814         int i, ret;
815         struct mt8365_afe_private *afe_priv = afe->platform_priv;
816 
817         for (i = 0; i < DAI_I2S_NUM; i++) {
818                 ret = mt8365_dai_set_priv(afe, mt8365_i2s_priv[i].id,
819                                           sizeof(*afe_priv),
820                                           &mt8365_i2s_priv[i]);
821                 if (ret)
822                         return ret;
823         }
824         return 0;
825 }
826 
827 int mt8365_dai_i2s_register(struct mtk_base_afe *afe)
828 {
829         struct mtk_base_afe_dai *dai;
830 
831         dai = devm_kzalloc(afe->dev, sizeof(*dai), GFP_KERNEL);
832         if (!dai)
833                 return -ENOMEM;
834 
835         list_add(&dai->list, &afe->sub_dais);
836 
837         dai->dai_drivers = mtk_dai_i2s_driver;
838         dai->num_dai_drivers = ARRAY_SIZE(mtk_dai_i2s_driver);
839         dai->dapm_widgets = mtk_dai_i2s_widgets;
840         dai->num_dapm_widgets = ARRAY_SIZE(mtk_dai_i2s_widgets);
841         dai->dapm_routes = mtk_dai_i2s_routes;
842         dai->num_dapm_routes = ARRAY_SIZE(mtk_dai_i2s_routes);
843 
844         /* set all dai i2s private data */
845         return mt8365_dai_i2s_set_priv(afe);
846 }
847 

~ [ 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