Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
torvalds
GitHub Repository: torvalds/linux
Path: blob/master/sound/soc/mediatek/mt8365/mt8365-dai-i2s.c
26488 views
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 <[email protected]>
7
* Alexandre Mergnat <[email protected]>
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
{/*0*/
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_CBP_CFP) {
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_CBP_CFP);
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_CBP_CFP);
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_CBP_CFP) {
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_CBP_CFP)
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_CBP_CFP))
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
816
for (i = 0; i < DAI_I2S_NUM; i++) {
817
ret = mt8365_dai_set_priv(afe, mt8365_i2s_priv[i].id,
818
sizeof(mt8365_i2s_priv[i]),
819
&mt8365_i2s_priv[i]);
820
if (ret)
821
return ret;
822
}
823
return 0;
824
}
825
826
int mt8365_dai_i2s_register(struct mtk_base_afe *afe)
827
{
828
struct mtk_base_afe_dai *dai;
829
830
dai = devm_kzalloc(afe->dev, sizeof(*dai), GFP_KERNEL);
831
if (!dai)
832
return -ENOMEM;
833
834
list_add(&dai->list, &afe->sub_dais);
835
836
dai->dai_drivers = mtk_dai_i2s_driver;
837
dai->num_dai_drivers = ARRAY_SIZE(mtk_dai_i2s_driver);
838
dai->dapm_widgets = mtk_dai_i2s_widgets;
839
dai->num_dapm_widgets = ARRAY_SIZE(mtk_dai_i2s_widgets);
840
dai->dapm_routes = mtk_dai_i2s_routes;
841
dai->num_dapm_routes = ARRAY_SIZE(mtk_dai_i2s_routes);
842
843
/* set all dai i2s private data */
844
return mt8365_dai_i2s_set_priv(afe);
845
}
846
847