Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
torvalds
GitHub Repository: torvalds/linux
Path: blob/master/sound/soc/mediatek/mt8183/mt8183-dai-i2s.c
26488 views
1
// SPDX-License-Identifier: GPL-2.0
2
//
3
// MediaTek ALSA SoC Audio DAI I2S Control
4
//
5
// Copyright (c) 2018 MediaTek Inc.
6
// Author: KaiChieh Chuang <[email protected]>
7
8
#include <linux/bitops.h>
9
#include <linux/regmap.h>
10
#include <sound/pcm_params.h>
11
#include "mt8183-afe-clk.h"
12
#include "mt8183-afe-common.h"
13
#include "mt8183-interconnection.h"
14
#include "mt8183-reg.h"
15
16
enum {
17
I2S_FMT_EIAJ = 0,
18
I2S_FMT_I2S = 1,
19
};
20
21
enum {
22
I2S_WLEN_16_BIT = 0,
23
I2S_WLEN_32_BIT = 1,
24
};
25
26
enum {
27
I2S_HD_NORMAL = 0,
28
I2S_HD_LOW_JITTER = 1,
29
};
30
31
enum {
32
I2S1_SEL_O28_O29 = 0,
33
I2S1_SEL_O03_O04 = 1,
34
};
35
36
enum {
37
I2S_IN_PAD_CONNSYS = 0,
38
I2S_IN_PAD_IO_MUX = 1,
39
};
40
41
struct mtk_afe_i2s_priv {
42
int id;
43
int rate; /* for determine which apll to use */
44
int low_jitter_en;
45
46
int share_i2s_id;
47
48
int mclk_id;
49
int mclk_rate;
50
int mclk_apll;
51
52
int use_eiaj;
53
};
54
55
static unsigned int get_i2s_wlen(snd_pcm_format_t format)
56
{
57
return snd_pcm_format_physical_width(format) <= 16 ?
58
I2S_WLEN_16_BIT : I2S_WLEN_32_BIT;
59
}
60
61
#define MTK_AFE_I2S0_KCONTROL_NAME "I2S0_HD_Mux"
62
#define MTK_AFE_I2S1_KCONTROL_NAME "I2S1_HD_Mux"
63
#define MTK_AFE_I2S2_KCONTROL_NAME "I2S2_HD_Mux"
64
#define MTK_AFE_I2S3_KCONTROL_NAME "I2S3_HD_Mux"
65
#define MTK_AFE_I2S5_KCONTROL_NAME "I2S5_HD_Mux"
66
67
#define I2S0_HD_EN_W_NAME "I2S0_HD_EN"
68
#define I2S1_HD_EN_W_NAME "I2S1_HD_EN"
69
#define I2S2_HD_EN_W_NAME "I2S2_HD_EN"
70
#define I2S3_HD_EN_W_NAME "I2S3_HD_EN"
71
#define I2S5_HD_EN_W_NAME "I2S5_HD_EN"
72
73
#define I2S0_MCLK_EN_W_NAME "I2S0_MCLK_EN"
74
#define I2S1_MCLK_EN_W_NAME "I2S1_MCLK_EN"
75
#define I2S2_MCLK_EN_W_NAME "I2S2_MCLK_EN"
76
#define I2S3_MCLK_EN_W_NAME "I2S3_MCLK_EN"
77
#define I2S5_MCLK_EN_W_NAME "I2S5_MCLK_EN"
78
79
static int get_i2s_id_by_name(struct mtk_base_afe *afe,
80
const char *name)
81
{
82
if (strncmp(name, "I2S0", 4) == 0)
83
return MT8183_DAI_I2S_0;
84
else if (strncmp(name, "I2S1", 4) == 0)
85
return MT8183_DAI_I2S_1;
86
else if (strncmp(name, "I2S2", 4) == 0)
87
return MT8183_DAI_I2S_2;
88
else if (strncmp(name, "I2S3", 4) == 0)
89
return MT8183_DAI_I2S_3;
90
else if (strncmp(name, "I2S5", 4) == 0)
91
return MT8183_DAI_I2S_5;
92
else
93
return -EINVAL;
94
}
95
96
static struct mtk_afe_i2s_priv *get_i2s_priv_by_name(struct mtk_base_afe *afe,
97
const char *name)
98
{
99
struct mt8183_afe_private *afe_priv = afe->platform_priv;
100
int dai_id = get_i2s_id_by_name(afe, name);
101
102
if (dai_id < 0)
103
return NULL;
104
105
return afe_priv->dai_priv[dai_id];
106
}
107
108
/* low jitter control */
109
static const char * const mt8183_i2s_hd_str[] = {
110
"Normal", "Low_Jitter"
111
};
112
113
static const struct soc_enum mt8183_i2s_enum[] = {
114
SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(mt8183_i2s_hd_str),
115
mt8183_i2s_hd_str),
116
};
117
118
static int mt8183_i2s_hd_get(struct snd_kcontrol *kcontrol,
119
struct snd_ctl_elem_value *ucontrol)
120
{
121
struct snd_soc_component *cmpnt = snd_soc_kcontrol_component(kcontrol);
122
struct mtk_base_afe *afe = snd_soc_component_get_drvdata(cmpnt);
123
struct mtk_afe_i2s_priv *i2s_priv;
124
125
i2s_priv = get_i2s_priv_by_name(afe, kcontrol->id.name);
126
127
if (!i2s_priv) {
128
dev_warn(afe->dev, "%s(), i2s_priv == NULL", __func__);
129
return -EINVAL;
130
}
131
132
ucontrol->value.integer.value[0] = i2s_priv->low_jitter_en;
133
134
return 0;
135
}
136
137
static int mt8183_i2s_hd_set(struct snd_kcontrol *kcontrol,
138
struct snd_ctl_elem_value *ucontrol)
139
{
140
struct snd_soc_component *cmpnt = snd_soc_kcontrol_component(kcontrol);
141
struct mtk_base_afe *afe = snd_soc_component_get_drvdata(cmpnt);
142
struct mtk_afe_i2s_priv *i2s_priv;
143
struct soc_enum *e = (struct soc_enum *)kcontrol->private_value;
144
int hd_en, change;
145
146
if (ucontrol->value.enumerated.item[0] >= e->items)
147
return -EINVAL;
148
149
hd_en = ucontrol->value.integer.value[0];
150
151
i2s_priv = get_i2s_priv_by_name(afe, kcontrol->id.name);
152
153
if (!i2s_priv) {
154
dev_warn(afe->dev, "%s(), i2s_priv == NULL", __func__);
155
return -EINVAL;
156
}
157
158
change = i2s_priv->low_jitter_en != hd_en;
159
i2s_priv->low_jitter_en = hd_en;
160
161
return change;
162
}
163
164
static const struct snd_kcontrol_new mtk_dai_i2s_controls[] = {
165
SOC_ENUM_EXT(MTK_AFE_I2S0_KCONTROL_NAME, mt8183_i2s_enum[0],
166
mt8183_i2s_hd_get, mt8183_i2s_hd_set),
167
SOC_ENUM_EXT(MTK_AFE_I2S1_KCONTROL_NAME, mt8183_i2s_enum[0],
168
mt8183_i2s_hd_get, mt8183_i2s_hd_set),
169
SOC_ENUM_EXT(MTK_AFE_I2S2_KCONTROL_NAME, mt8183_i2s_enum[0],
170
mt8183_i2s_hd_get, mt8183_i2s_hd_set),
171
SOC_ENUM_EXT(MTK_AFE_I2S3_KCONTROL_NAME, mt8183_i2s_enum[0],
172
mt8183_i2s_hd_get, mt8183_i2s_hd_set),
173
SOC_ENUM_EXT(MTK_AFE_I2S5_KCONTROL_NAME, mt8183_i2s_enum[0],
174
mt8183_i2s_hd_get, mt8183_i2s_hd_set),
175
};
176
177
/* dai component */
178
/* interconnection */
179
static const struct snd_kcontrol_new mtk_i2s3_ch1_mix[] = {
180
SOC_DAPM_SINGLE_AUTODISABLE("DL1_CH1", AFE_CONN0, I_DL1_CH1, 1, 0),
181
SOC_DAPM_SINGLE_AUTODISABLE("DL2_CH1", AFE_CONN0, I_DL2_CH1, 1, 0),
182
SOC_DAPM_SINGLE_AUTODISABLE("DL3_CH1", AFE_CONN0, I_DL3_CH1, 1, 0),
183
SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH1", AFE_CONN0,
184
I_ADDA_UL_CH1, 1, 0),
185
SOC_DAPM_SINGLE_AUTODISABLE("PCM_1_CAP_CH1", AFE_CONN0,
186
I_PCM_1_CAP_CH1, 1, 0),
187
SOC_DAPM_SINGLE_AUTODISABLE("PCM_2_CAP_CH1", AFE_CONN0,
188
I_PCM_2_CAP_CH1, 1, 0),
189
};
190
191
static const struct snd_kcontrol_new mtk_i2s3_ch2_mix[] = {
192
SOC_DAPM_SINGLE_AUTODISABLE("DL1_CH2", AFE_CONN1, I_DL1_CH2, 1, 0),
193
SOC_DAPM_SINGLE_AUTODISABLE("DL2_CH2", AFE_CONN1, I_DL2_CH2, 1, 0),
194
SOC_DAPM_SINGLE_AUTODISABLE("DL3_CH2", AFE_CONN1, I_DL3_CH2, 1, 0),
195
SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH2", AFE_CONN1,
196
I_ADDA_UL_CH2, 1, 0),
197
SOC_DAPM_SINGLE_AUTODISABLE("PCM_1_CAP_CH1", AFE_CONN1,
198
I_PCM_1_CAP_CH1, 1, 0),
199
SOC_DAPM_SINGLE_AUTODISABLE("PCM_2_CAP_CH1", AFE_CONN1,
200
I_PCM_2_CAP_CH1, 1, 0),
201
SOC_DAPM_SINGLE_AUTODISABLE("PCM_1_CAP_CH2", AFE_CONN1,
202
I_PCM_1_CAP_CH2, 1, 0),
203
SOC_DAPM_SINGLE_AUTODISABLE("PCM_2_CAP_CH2", AFE_CONN1,
204
I_PCM_2_CAP_CH2, 1, 0),
205
};
206
207
static const struct snd_kcontrol_new mtk_i2s1_ch1_mix[] = {
208
SOC_DAPM_SINGLE_AUTODISABLE("DL1_CH1", AFE_CONN28, I_DL1_CH1, 1, 0),
209
SOC_DAPM_SINGLE_AUTODISABLE("DL2_CH1", AFE_CONN28, I_DL2_CH1, 1, 0),
210
SOC_DAPM_SINGLE_AUTODISABLE("DL3_CH1", AFE_CONN28, I_DL3_CH1, 1, 0),
211
SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH1", AFE_CONN28,
212
I_ADDA_UL_CH1, 1, 0),
213
SOC_DAPM_SINGLE_AUTODISABLE("PCM_1_CAP_CH1", AFE_CONN28,
214
I_PCM_1_CAP_CH1, 1, 0),
215
SOC_DAPM_SINGLE_AUTODISABLE("PCM_2_CAP_CH1", AFE_CONN28,
216
I_PCM_2_CAP_CH1, 1, 0),
217
};
218
219
static const struct snd_kcontrol_new mtk_i2s1_ch2_mix[] = {
220
SOC_DAPM_SINGLE_AUTODISABLE("DL1_CH2", AFE_CONN29, I_DL1_CH2, 1, 0),
221
SOC_DAPM_SINGLE_AUTODISABLE("DL2_CH2", AFE_CONN29, I_DL2_CH2, 1, 0),
222
SOC_DAPM_SINGLE_AUTODISABLE("DL3_CH2", AFE_CONN29, I_DL3_CH2, 1, 0),
223
SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH2", AFE_CONN29,
224
I_ADDA_UL_CH2, 1, 0),
225
SOC_DAPM_SINGLE_AUTODISABLE("PCM_1_CAP_CH1", AFE_CONN29,
226
I_PCM_1_CAP_CH1, 1, 0),
227
SOC_DAPM_SINGLE_AUTODISABLE("PCM_2_CAP_CH1", AFE_CONN29,
228
I_PCM_2_CAP_CH1, 1, 0),
229
SOC_DAPM_SINGLE_AUTODISABLE("PCM_1_CAP_CH2", AFE_CONN29,
230
I_PCM_1_CAP_CH2, 1, 0),
231
SOC_DAPM_SINGLE_AUTODISABLE("PCM_2_CAP_CH2", AFE_CONN29,
232
I_PCM_2_CAP_CH2, 1, 0),
233
};
234
235
static const struct snd_kcontrol_new mtk_i2s5_ch1_mix[] = {
236
SOC_DAPM_SINGLE_AUTODISABLE("DL1_CH1", AFE_CONN30, I_DL1_CH1, 1, 0),
237
SOC_DAPM_SINGLE_AUTODISABLE("DL2_CH1", AFE_CONN30, I_DL2_CH1, 1, 0),
238
SOC_DAPM_SINGLE_AUTODISABLE("DL3_CH1", AFE_CONN30, I_DL3_CH1, 1, 0),
239
SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH1", AFE_CONN30,
240
I_ADDA_UL_CH1, 1, 0),
241
SOC_DAPM_SINGLE_AUTODISABLE("PCM_1_CAP_CH1", AFE_CONN30,
242
I_PCM_1_CAP_CH1, 1, 0),
243
SOC_DAPM_SINGLE_AUTODISABLE("PCM_2_CAP_CH1", AFE_CONN30,
244
I_PCM_2_CAP_CH1, 1, 0),
245
};
246
247
static const struct snd_kcontrol_new mtk_i2s5_ch2_mix[] = {
248
SOC_DAPM_SINGLE_AUTODISABLE("DL1_CH2", AFE_CONN31, I_DL1_CH2, 1, 0),
249
SOC_DAPM_SINGLE_AUTODISABLE("DL2_CH2", AFE_CONN31, I_DL2_CH2, 1, 0),
250
SOC_DAPM_SINGLE_AUTODISABLE("DL3_CH2", AFE_CONN31, I_DL3_CH2, 1, 0),
251
SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH2", AFE_CONN31,
252
I_ADDA_UL_CH2, 1, 0),
253
SOC_DAPM_SINGLE_AUTODISABLE("PCM_1_CAP_CH1", AFE_CONN31,
254
I_PCM_1_CAP_CH1, 1, 0),
255
SOC_DAPM_SINGLE_AUTODISABLE("PCM_2_CAP_CH1", AFE_CONN31,
256
I_PCM_2_CAP_CH1, 1, 0),
257
SOC_DAPM_SINGLE_AUTODISABLE("PCM_1_CAP_CH2", AFE_CONN31,
258
I_PCM_1_CAP_CH2, 1, 0),
259
SOC_DAPM_SINGLE_AUTODISABLE("PCM_2_CAP_CH2", AFE_CONN31,
260
I_PCM_2_CAP_CH2, 1, 0),
261
};
262
263
enum {
264
SUPPLY_SEQ_APLL,
265
SUPPLY_SEQ_I2S_MCLK_EN,
266
SUPPLY_SEQ_I2S_HD_EN,
267
SUPPLY_SEQ_I2S_EN,
268
};
269
270
static int mtk_apll_event(struct snd_soc_dapm_widget *w,
271
struct snd_kcontrol *kcontrol,
272
int event)
273
{
274
struct snd_soc_component *cmpnt = snd_soc_dapm_to_component(w->dapm);
275
struct mtk_base_afe *afe = snd_soc_component_get_drvdata(cmpnt);
276
277
switch (event) {
278
case SND_SOC_DAPM_PRE_PMU:
279
if (snd_soc_dapm_widget_name_cmp(w, APLL1_W_NAME) == 0)
280
mt8183_apll1_enable(afe);
281
else
282
mt8183_apll2_enable(afe);
283
break;
284
case SND_SOC_DAPM_POST_PMD:
285
if (snd_soc_dapm_widget_name_cmp(w, APLL1_W_NAME) == 0)
286
mt8183_apll1_disable(afe);
287
else
288
mt8183_apll2_disable(afe);
289
break;
290
default:
291
break;
292
}
293
294
return 0;
295
}
296
297
static int mtk_mclk_en_event(struct snd_soc_dapm_widget *w,
298
struct snd_kcontrol *kcontrol,
299
int event)
300
{
301
struct snd_soc_component *cmpnt = snd_soc_dapm_to_component(w->dapm);
302
struct mtk_base_afe *afe = snd_soc_component_get_drvdata(cmpnt);
303
struct mtk_afe_i2s_priv *i2s_priv;
304
305
i2s_priv = get_i2s_priv_by_name(afe, w->name);
306
307
if (!i2s_priv) {
308
dev_warn(afe->dev, "%s(), i2s_priv == NULL", __func__);
309
return -EINVAL;
310
}
311
312
switch (event) {
313
case SND_SOC_DAPM_PRE_PMU:
314
mt8183_mck_enable(afe, i2s_priv->mclk_id, i2s_priv->mclk_rate);
315
break;
316
case SND_SOC_DAPM_POST_PMD:
317
i2s_priv->mclk_rate = 0;
318
mt8183_mck_disable(afe, i2s_priv->mclk_id);
319
break;
320
default:
321
break;
322
}
323
324
return 0;
325
}
326
327
static const struct snd_soc_dapm_widget mtk_dai_i2s_widgets[] = {
328
SND_SOC_DAPM_MIXER("I2S1_CH1", SND_SOC_NOPM, 0, 0,
329
mtk_i2s1_ch1_mix,
330
ARRAY_SIZE(mtk_i2s1_ch1_mix)),
331
SND_SOC_DAPM_MIXER("I2S1_CH2", SND_SOC_NOPM, 0, 0,
332
mtk_i2s1_ch2_mix,
333
ARRAY_SIZE(mtk_i2s1_ch2_mix)),
334
335
SND_SOC_DAPM_MIXER("I2S3_CH1", SND_SOC_NOPM, 0, 0,
336
mtk_i2s3_ch1_mix,
337
ARRAY_SIZE(mtk_i2s3_ch1_mix)),
338
SND_SOC_DAPM_MIXER("I2S3_CH2", SND_SOC_NOPM, 0, 0,
339
mtk_i2s3_ch2_mix,
340
ARRAY_SIZE(mtk_i2s3_ch2_mix)),
341
342
SND_SOC_DAPM_MIXER("I2S5_CH1", SND_SOC_NOPM, 0, 0,
343
mtk_i2s5_ch1_mix,
344
ARRAY_SIZE(mtk_i2s5_ch1_mix)),
345
SND_SOC_DAPM_MIXER("I2S5_CH2", SND_SOC_NOPM, 0, 0,
346
mtk_i2s5_ch2_mix,
347
ARRAY_SIZE(mtk_i2s5_ch2_mix)),
348
349
/* i2s en*/
350
SND_SOC_DAPM_SUPPLY_S("I2S0_EN", SUPPLY_SEQ_I2S_EN,
351
AFE_I2S_CON, I2S_EN_SFT, 0,
352
NULL, 0),
353
SND_SOC_DAPM_SUPPLY_S("I2S1_EN", SUPPLY_SEQ_I2S_EN,
354
AFE_I2S_CON1, I2S_EN_SFT, 0,
355
NULL, 0),
356
SND_SOC_DAPM_SUPPLY_S("I2S2_EN", SUPPLY_SEQ_I2S_EN,
357
AFE_I2S_CON2, I2S_EN_SFT, 0,
358
NULL, 0),
359
SND_SOC_DAPM_SUPPLY_S("I2S3_EN", SUPPLY_SEQ_I2S_EN,
360
AFE_I2S_CON3, I2S_EN_SFT, 0,
361
NULL, 0),
362
SND_SOC_DAPM_SUPPLY_S("I2S5_EN", SUPPLY_SEQ_I2S_EN,
363
AFE_I2S_CON4, I2S5_EN_SFT, 0,
364
NULL, 0),
365
/* i2s hd en */
366
SND_SOC_DAPM_SUPPLY_S(I2S0_HD_EN_W_NAME, SUPPLY_SEQ_I2S_HD_EN,
367
AFE_I2S_CON, I2S1_HD_EN_SFT, 0,
368
NULL, 0),
369
SND_SOC_DAPM_SUPPLY_S(I2S1_HD_EN_W_NAME, SUPPLY_SEQ_I2S_HD_EN,
370
AFE_I2S_CON1, I2S2_HD_EN_SFT, 0,
371
NULL, 0),
372
SND_SOC_DAPM_SUPPLY_S(I2S2_HD_EN_W_NAME, SUPPLY_SEQ_I2S_HD_EN,
373
AFE_I2S_CON2, I2S3_HD_EN_SFT, 0,
374
NULL, 0),
375
SND_SOC_DAPM_SUPPLY_S(I2S3_HD_EN_W_NAME, SUPPLY_SEQ_I2S_HD_EN,
376
AFE_I2S_CON3, I2S4_HD_EN_SFT, 0,
377
NULL, 0),
378
SND_SOC_DAPM_SUPPLY_S(I2S5_HD_EN_W_NAME, SUPPLY_SEQ_I2S_HD_EN,
379
AFE_I2S_CON4, I2S5_HD_EN_SFT, 0,
380
NULL, 0),
381
382
/* i2s mclk en */
383
SND_SOC_DAPM_SUPPLY_S(I2S0_MCLK_EN_W_NAME, SUPPLY_SEQ_I2S_MCLK_EN,
384
SND_SOC_NOPM, 0, 0,
385
mtk_mclk_en_event,
386
SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
387
SND_SOC_DAPM_SUPPLY_S(I2S1_MCLK_EN_W_NAME, SUPPLY_SEQ_I2S_MCLK_EN,
388
SND_SOC_NOPM, 0, 0,
389
mtk_mclk_en_event,
390
SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
391
SND_SOC_DAPM_SUPPLY_S(I2S2_MCLK_EN_W_NAME, SUPPLY_SEQ_I2S_MCLK_EN,
392
SND_SOC_NOPM, 0, 0,
393
mtk_mclk_en_event,
394
SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
395
SND_SOC_DAPM_SUPPLY_S(I2S3_MCLK_EN_W_NAME, SUPPLY_SEQ_I2S_MCLK_EN,
396
SND_SOC_NOPM, 0, 0,
397
mtk_mclk_en_event,
398
SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
399
SND_SOC_DAPM_SUPPLY_S(I2S5_MCLK_EN_W_NAME, SUPPLY_SEQ_I2S_MCLK_EN,
400
SND_SOC_NOPM, 0, 0,
401
mtk_mclk_en_event,
402
SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
403
404
/* apll */
405
SND_SOC_DAPM_SUPPLY_S(APLL1_W_NAME, SUPPLY_SEQ_APLL,
406
SND_SOC_NOPM, 0, 0,
407
mtk_apll_event,
408
SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
409
SND_SOC_DAPM_SUPPLY_S(APLL2_W_NAME, SUPPLY_SEQ_APLL,
410
SND_SOC_NOPM, 0, 0,
411
mtk_apll_event,
412
SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
413
};
414
415
static int mtk_afe_i2s_share_connect(struct snd_soc_dapm_widget *source,
416
struct snd_soc_dapm_widget *sink)
417
{
418
struct snd_soc_dapm_widget *w = sink;
419
struct snd_soc_component *cmpnt = snd_soc_dapm_to_component(w->dapm);
420
struct mtk_base_afe *afe = snd_soc_component_get_drvdata(cmpnt);
421
struct mtk_afe_i2s_priv *i2s_priv;
422
423
i2s_priv = get_i2s_priv_by_name(afe, sink->name);
424
425
if (!i2s_priv) {
426
dev_warn(afe->dev, "%s(), i2s_priv == NULL", __func__);
427
return 0;
428
}
429
430
if (i2s_priv->share_i2s_id < 0)
431
return 0;
432
433
return i2s_priv->share_i2s_id == get_i2s_id_by_name(afe, source->name);
434
}
435
436
static int mtk_afe_i2s_hd_connect(struct snd_soc_dapm_widget *source,
437
struct snd_soc_dapm_widget *sink)
438
{
439
struct snd_soc_dapm_widget *w = sink;
440
struct snd_soc_component *cmpnt = snd_soc_dapm_to_component(w->dapm);
441
struct mtk_base_afe *afe = snd_soc_component_get_drvdata(cmpnt);
442
struct mtk_afe_i2s_priv *i2s_priv;
443
444
i2s_priv = get_i2s_priv_by_name(afe, sink->name);
445
446
if (!i2s_priv) {
447
dev_warn(afe->dev, "%s(), i2s_priv == NULL", __func__);
448
return 0;
449
}
450
451
if (get_i2s_id_by_name(afe, sink->name) ==
452
get_i2s_id_by_name(afe, source->name))
453
return i2s_priv->low_jitter_en;
454
455
/* check if share i2s need hd en */
456
if (i2s_priv->share_i2s_id < 0)
457
return 0;
458
459
if (i2s_priv->share_i2s_id == get_i2s_id_by_name(afe, source->name))
460
return i2s_priv->low_jitter_en;
461
462
return 0;
463
}
464
465
static int mtk_afe_i2s_apll_connect(struct snd_soc_dapm_widget *source,
466
struct snd_soc_dapm_widget *sink)
467
{
468
struct snd_soc_dapm_widget *w = sink;
469
struct snd_soc_component *cmpnt = snd_soc_dapm_to_component(w->dapm);
470
struct mtk_base_afe *afe = snd_soc_component_get_drvdata(cmpnt);
471
struct mtk_afe_i2s_priv *i2s_priv;
472
int cur_apll;
473
int i2s_need_apll;
474
475
i2s_priv = get_i2s_priv_by_name(afe, w->name);
476
477
if (!i2s_priv) {
478
dev_warn(afe->dev, "%s(), i2s_priv == NULL", __func__);
479
return 0;
480
}
481
482
/* which apll */
483
cur_apll = mt8183_get_apll_by_name(afe, source->name);
484
485
/* choose APLL from i2s rate */
486
i2s_need_apll = mt8183_get_apll_by_rate(afe, i2s_priv->rate);
487
488
return (i2s_need_apll == cur_apll) ? 1 : 0;
489
}
490
491
static int mtk_afe_i2s_mclk_connect(struct snd_soc_dapm_widget *source,
492
struct snd_soc_dapm_widget *sink)
493
{
494
struct snd_soc_dapm_widget *w = sink;
495
struct snd_soc_component *cmpnt = snd_soc_dapm_to_component(w->dapm);
496
struct mtk_base_afe *afe = snd_soc_component_get_drvdata(cmpnt);
497
struct mtk_afe_i2s_priv *i2s_priv;
498
499
i2s_priv = get_i2s_priv_by_name(afe, sink->name);
500
501
if (!i2s_priv) {
502
dev_warn(afe->dev, "%s(), i2s_priv == NULL", __func__);
503
return 0;
504
}
505
506
if (get_i2s_id_by_name(afe, sink->name) ==
507
get_i2s_id_by_name(afe, source->name))
508
return (i2s_priv->mclk_rate > 0) ? 1 : 0;
509
510
/* check if share i2s need mclk */
511
if (i2s_priv->share_i2s_id < 0)
512
return 0;
513
514
if (i2s_priv->share_i2s_id == get_i2s_id_by_name(afe, source->name))
515
return (i2s_priv->mclk_rate > 0) ? 1 : 0;
516
517
return 0;
518
}
519
520
static int mtk_afe_mclk_apll_connect(struct snd_soc_dapm_widget *source,
521
struct snd_soc_dapm_widget *sink)
522
{
523
struct snd_soc_dapm_widget *w = sink;
524
struct snd_soc_component *cmpnt = snd_soc_dapm_to_component(w->dapm);
525
struct mtk_base_afe *afe = snd_soc_component_get_drvdata(cmpnt);
526
struct mtk_afe_i2s_priv *i2s_priv;
527
int cur_apll;
528
529
i2s_priv = get_i2s_priv_by_name(afe, w->name);
530
531
if (!i2s_priv) {
532
dev_warn(afe->dev, "%s(), i2s_priv == NULL", __func__);
533
return 0;
534
}
535
536
/* which apll */
537
cur_apll = mt8183_get_apll_by_name(afe, source->name);
538
539
return (i2s_priv->mclk_apll == cur_apll) ? 1 : 0;
540
}
541
542
static const struct snd_soc_dapm_route mtk_dai_i2s_routes[] = {
543
/* i2s0 */
544
{"I2S0", NULL, "I2S0_EN"},
545
{"I2S0", NULL, "I2S1_EN", mtk_afe_i2s_share_connect},
546
{"I2S0", NULL, "I2S2_EN", mtk_afe_i2s_share_connect},
547
{"I2S0", NULL, "I2S3_EN", mtk_afe_i2s_share_connect},
548
{"I2S0", NULL, "I2S5_EN", mtk_afe_i2s_share_connect},
549
550
{"I2S0", NULL, I2S0_HD_EN_W_NAME, mtk_afe_i2s_hd_connect},
551
{"I2S0", NULL, I2S1_HD_EN_W_NAME, mtk_afe_i2s_hd_connect},
552
{"I2S0", NULL, I2S2_HD_EN_W_NAME, mtk_afe_i2s_hd_connect},
553
{"I2S0", NULL, I2S3_HD_EN_W_NAME, mtk_afe_i2s_hd_connect},
554
{"I2S0", NULL, I2S5_HD_EN_W_NAME, mtk_afe_i2s_hd_connect},
555
{I2S0_HD_EN_W_NAME, NULL, APLL1_W_NAME, mtk_afe_i2s_apll_connect},
556
{I2S0_HD_EN_W_NAME, NULL, APLL2_W_NAME, mtk_afe_i2s_apll_connect},
557
558
{"I2S0", NULL, I2S0_MCLK_EN_W_NAME, mtk_afe_i2s_mclk_connect},
559
{"I2S0", NULL, I2S1_MCLK_EN_W_NAME, mtk_afe_i2s_mclk_connect},
560
{"I2S0", NULL, I2S2_MCLK_EN_W_NAME, mtk_afe_i2s_mclk_connect},
561
{"I2S0", NULL, I2S3_MCLK_EN_W_NAME, mtk_afe_i2s_mclk_connect},
562
{"I2S0", NULL, I2S5_MCLK_EN_W_NAME, mtk_afe_i2s_mclk_connect},
563
{I2S0_MCLK_EN_W_NAME, NULL, APLL1_W_NAME, mtk_afe_mclk_apll_connect},
564
{I2S0_MCLK_EN_W_NAME, NULL, APLL2_W_NAME, mtk_afe_mclk_apll_connect},
565
566
/* i2s1 */
567
{"I2S1_CH1", "DL1_CH1", "DL1"},
568
{"I2S1_CH2", "DL1_CH2", "DL1"},
569
570
{"I2S1_CH1", "DL2_CH1", "DL2"},
571
{"I2S1_CH2", "DL2_CH2", "DL2"},
572
573
{"I2S1_CH1", "DL3_CH1", "DL3"},
574
{"I2S1_CH2", "DL3_CH2", "DL3"},
575
576
{"I2S1", NULL, "I2S1_CH1"},
577
{"I2S1", NULL, "I2S1_CH2"},
578
579
{"I2S1", NULL, "I2S0_EN", mtk_afe_i2s_share_connect},
580
{"I2S1", NULL, "I2S1_EN"},
581
{"I2S1", NULL, "I2S2_EN", mtk_afe_i2s_share_connect},
582
{"I2S1", NULL, "I2S3_EN", mtk_afe_i2s_share_connect},
583
{"I2S1", NULL, "I2S5_EN", mtk_afe_i2s_share_connect},
584
585
{"I2S1", NULL, I2S0_HD_EN_W_NAME, mtk_afe_i2s_hd_connect},
586
{"I2S1", NULL, I2S1_HD_EN_W_NAME, mtk_afe_i2s_hd_connect},
587
{"I2S1", NULL, I2S2_HD_EN_W_NAME, mtk_afe_i2s_hd_connect},
588
{"I2S1", NULL, I2S3_HD_EN_W_NAME, mtk_afe_i2s_hd_connect},
589
{"I2S1", NULL, I2S5_HD_EN_W_NAME, mtk_afe_i2s_hd_connect},
590
{I2S1_HD_EN_W_NAME, NULL, APLL1_W_NAME, mtk_afe_i2s_apll_connect},
591
{I2S1_HD_EN_W_NAME, NULL, APLL2_W_NAME, mtk_afe_i2s_apll_connect},
592
593
{"I2S1", NULL, I2S0_MCLK_EN_W_NAME, mtk_afe_i2s_mclk_connect},
594
{"I2S1", NULL, I2S1_MCLK_EN_W_NAME, mtk_afe_i2s_mclk_connect},
595
{"I2S1", NULL, I2S2_MCLK_EN_W_NAME, mtk_afe_i2s_mclk_connect},
596
{"I2S1", NULL, I2S3_MCLK_EN_W_NAME, mtk_afe_i2s_mclk_connect},
597
{"I2S1", NULL, I2S5_MCLK_EN_W_NAME, mtk_afe_i2s_mclk_connect},
598
{I2S1_MCLK_EN_W_NAME, NULL, APLL1_W_NAME, mtk_afe_mclk_apll_connect},
599
{I2S1_MCLK_EN_W_NAME, NULL, APLL2_W_NAME, mtk_afe_mclk_apll_connect},
600
601
/* i2s2 */
602
{"I2S2", NULL, "I2S0_EN", mtk_afe_i2s_share_connect},
603
{"I2S2", NULL, "I2S1_EN", mtk_afe_i2s_share_connect},
604
{"I2S2", NULL, "I2S2_EN"},
605
{"I2S2", NULL, "I2S3_EN", mtk_afe_i2s_share_connect},
606
{"I2S2", NULL, "I2S5_EN", mtk_afe_i2s_share_connect},
607
608
{"I2S2", NULL, I2S0_HD_EN_W_NAME, mtk_afe_i2s_hd_connect},
609
{"I2S2", NULL, I2S1_HD_EN_W_NAME, mtk_afe_i2s_hd_connect},
610
{"I2S2", NULL, I2S2_HD_EN_W_NAME, mtk_afe_i2s_hd_connect},
611
{"I2S2", NULL, I2S3_HD_EN_W_NAME, mtk_afe_i2s_hd_connect},
612
{"I2S2", NULL, I2S5_HD_EN_W_NAME, mtk_afe_i2s_hd_connect},
613
{I2S2_HD_EN_W_NAME, NULL, APLL1_W_NAME, mtk_afe_i2s_apll_connect},
614
{I2S2_HD_EN_W_NAME, NULL, APLL2_W_NAME, mtk_afe_i2s_apll_connect},
615
616
{"I2S2", NULL, I2S0_MCLK_EN_W_NAME, mtk_afe_i2s_mclk_connect},
617
{"I2S2", NULL, I2S1_MCLK_EN_W_NAME, mtk_afe_i2s_mclk_connect},
618
{"I2S2", NULL, I2S2_MCLK_EN_W_NAME, mtk_afe_i2s_mclk_connect},
619
{"I2S2", NULL, I2S3_MCLK_EN_W_NAME, mtk_afe_i2s_mclk_connect},
620
{"I2S2", NULL, I2S5_MCLK_EN_W_NAME, mtk_afe_i2s_mclk_connect},
621
{I2S2_MCLK_EN_W_NAME, NULL, APLL1_W_NAME, mtk_afe_mclk_apll_connect},
622
{I2S2_MCLK_EN_W_NAME, NULL, APLL2_W_NAME, mtk_afe_mclk_apll_connect},
623
624
/* i2s3 */
625
{"I2S3_CH1", "DL1_CH1", "DL1"},
626
{"I2S3_CH2", "DL1_CH2", "DL1"},
627
628
{"I2S3_CH1", "DL2_CH1", "DL2"},
629
{"I2S3_CH2", "DL2_CH2", "DL2"},
630
631
{"I2S3_CH1", "DL3_CH1", "DL3"},
632
{"I2S3_CH2", "DL3_CH2", "DL3"},
633
634
{"I2S3", NULL, "I2S3_CH1"},
635
{"I2S3", NULL, "I2S3_CH2"},
636
637
{"I2S3", NULL, "I2S0_EN", mtk_afe_i2s_share_connect},
638
{"I2S3", NULL, "I2S1_EN", mtk_afe_i2s_share_connect},
639
{"I2S3", NULL, "I2S2_EN", mtk_afe_i2s_share_connect},
640
{"I2S3", NULL, "I2S3_EN"},
641
{"I2S3", NULL, "I2S5_EN", mtk_afe_i2s_share_connect},
642
643
{"I2S3", NULL, I2S0_HD_EN_W_NAME, mtk_afe_i2s_hd_connect},
644
{"I2S3", NULL, I2S1_HD_EN_W_NAME, mtk_afe_i2s_hd_connect},
645
{"I2S3", NULL, I2S2_HD_EN_W_NAME, mtk_afe_i2s_hd_connect},
646
{"I2S3", NULL, I2S3_HD_EN_W_NAME, mtk_afe_i2s_hd_connect},
647
{"I2S3", NULL, I2S5_HD_EN_W_NAME, mtk_afe_i2s_hd_connect},
648
{I2S3_HD_EN_W_NAME, NULL, APLL1_W_NAME, mtk_afe_i2s_apll_connect},
649
{I2S3_HD_EN_W_NAME, NULL, APLL2_W_NAME, mtk_afe_i2s_apll_connect},
650
651
{"I2S3", NULL, I2S0_MCLK_EN_W_NAME, mtk_afe_i2s_mclk_connect},
652
{"I2S3", NULL, I2S1_MCLK_EN_W_NAME, mtk_afe_i2s_mclk_connect},
653
{"I2S3", NULL, I2S2_MCLK_EN_W_NAME, mtk_afe_i2s_mclk_connect},
654
{"I2S3", NULL, I2S3_MCLK_EN_W_NAME, mtk_afe_i2s_mclk_connect},
655
{"I2S3", NULL, I2S5_MCLK_EN_W_NAME, mtk_afe_i2s_mclk_connect},
656
{I2S3_MCLK_EN_W_NAME, NULL, APLL1_W_NAME, mtk_afe_mclk_apll_connect},
657
{I2S3_MCLK_EN_W_NAME, NULL, APLL2_W_NAME, mtk_afe_mclk_apll_connect},
658
659
/* i2s5 */
660
{"I2S5_CH1", "DL1_CH1", "DL1"},
661
{"I2S5_CH2", "DL1_CH2", "DL1"},
662
663
{"I2S5_CH1", "DL2_CH1", "DL2"},
664
{"I2S5_CH2", "DL2_CH2", "DL2"},
665
666
{"I2S5_CH1", "DL3_CH1", "DL3"},
667
{"I2S5_CH2", "DL3_CH2", "DL3"},
668
669
{"I2S5", NULL, "I2S5_CH1"},
670
{"I2S5", NULL, "I2S5_CH2"},
671
672
{"I2S5", NULL, "I2S0_EN", mtk_afe_i2s_share_connect},
673
{"I2S5", NULL, "I2S1_EN", mtk_afe_i2s_share_connect},
674
{"I2S5", NULL, "I2S2_EN", mtk_afe_i2s_share_connect},
675
{"I2S5", NULL, "I2S3_EN", mtk_afe_i2s_share_connect},
676
{"I2S5", NULL, "I2S5_EN"},
677
678
{"I2S5", NULL, I2S0_HD_EN_W_NAME, mtk_afe_i2s_hd_connect},
679
{"I2S5", NULL, I2S1_HD_EN_W_NAME, mtk_afe_i2s_hd_connect},
680
{"I2S5", NULL, I2S2_HD_EN_W_NAME, mtk_afe_i2s_hd_connect},
681
{"I2S5", NULL, I2S3_HD_EN_W_NAME, mtk_afe_i2s_hd_connect},
682
{"I2S5", NULL, I2S5_HD_EN_W_NAME, mtk_afe_i2s_hd_connect},
683
{I2S5_HD_EN_W_NAME, NULL, APLL1_W_NAME, mtk_afe_i2s_apll_connect},
684
{I2S5_HD_EN_W_NAME, NULL, APLL2_W_NAME, mtk_afe_i2s_apll_connect},
685
686
{"I2S5", NULL, I2S0_MCLK_EN_W_NAME, mtk_afe_i2s_mclk_connect},
687
{"I2S5", NULL, I2S1_MCLK_EN_W_NAME, mtk_afe_i2s_mclk_connect},
688
{"I2S5", NULL, I2S2_MCLK_EN_W_NAME, mtk_afe_i2s_mclk_connect},
689
{"I2S5", NULL, I2S3_MCLK_EN_W_NAME, mtk_afe_i2s_mclk_connect},
690
{"I2S5", NULL, I2S5_MCLK_EN_W_NAME, mtk_afe_i2s_mclk_connect},
691
{I2S5_MCLK_EN_W_NAME, NULL, APLL1_W_NAME, mtk_afe_mclk_apll_connect},
692
{I2S5_MCLK_EN_W_NAME, NULL, APLL2_W_NAME, mtk_afe_mclk_apll_connect},
693
};
694
695
/* dai ops */
696
static int mtk_dai_i2s_config(struct mtk_base_afe *afe,
697
struct snd_pcm_hw_params *params,
698
int i2s_id)
699
{
700
struct mt8183_afe_private *afe_priv = afe->platform_priv;
701
struct mtk_afe_i2s_priv *i2s_priv = afe_priv->dai_priv[i2s_id];
702
703
unsigned int rate = params_rate(params);
704
unsigned int rate_reg = mt8183_rate_transform(afe->dev,
705
rate, i2s_id);
706
snd_pcm_format_t format = params_format(params);
707
unsigned int i2s_con = 0, fmt_con = I2S_FMT_I2S << I2S_FMT_SFT;
708
int ret = 0;
709
710
if (i2s_priv) {
711
i2s_priv->rate = rate;
712
713
if (i2s_priv->use_eiaj)
714
fmt_con = I2S_FMT_EIAJ << I2S_FMT_SFT;
715
} else {
716
dev_warn(afe->dev, "%s(), i2s_priv == NULL", __func__);
717
}
718
719
switch (i2s_id) {
720
case MT8183_DAI_I2S_0:
721
regmap_update_bits(afe->regmap, AFE_DAC_CON1,
722
I2S_MODE_MASK_SFT, rate_reg << I2S_MODE_SFT);
723
i2s_con = I2S_IN_PAD_IO_MUX << I2SIN_PAD_SEL_SFT;
724
i2s_con |= fmt_con;
725
i2s_con |= get_i2s_wlen(format) << I2S_WLEN_SFT;
726
regmap_update_bits(afe->regmap, AFE_I2S_CON,
727
0xffffeffe, i2s_con);
728
break;
729
case MT8183_DAI_I2S_1:
730
i2s_con = I2S1_SEL_O28_O29 << I2S2_SEL_O03_O04_SFT;
731
i2s_con |= rate_reg << I2S2_OUT_MODE_SFT;
732
i2s_con |= fmt_con;
733
i2s_con |= get_i2s_wlen(format) << I2S2_WLEN_SFT;
734
regmap_update_bits(afe->regmap, AFE_I2S_CON1,
735
0xffffeffe, i2s_con);
736
break;
737
case MT8183_DAI_I2S_2:
738
i2s_con = 8 << I2S3_UPDATE_WORD_SFT;
739
i2s_con |= rate_reg << I2S3_OUT_MODE_SFT;
740
i2s_con |= fmt_con;
741
i2s_con |= get_i2s_wlen(format) << I2S3_WLEN_SFT;
742
regmap_update_bits(afe->regmap, AFE_I2S_CON2,
743
0xffffeffe, i2s_con);
744
break;
745
case MT8183_DAI_I2S_3:
746
i2s_con = rate_reg << I2S4_OUT_MODE_SFT;
747
i2s_con |= fmt_con;
748
i2s_con |= get_i2s_wlen(format) << I2S4_WLEN_SFT;
749
regmap_update_bits(afe->regmap, AFE_I2S_CON3,
750
0xffffeffe, i2s_con);
751
break;
752
case MT8183_DAI_I2S_5:
753
i2s_con = rate_reg << I2S5_OUT_MODE_SFT;
754
i2s_con |= fmt_con;
755
i2s_con |= get_i2s_wlen(format) << I2S5_WLEN_SFT;
756
regmap_update_bits(afe->regmap, AFE_I2S_CON4,
757
0xffffeffe, i2s_con);
758
break;
759
default:
760
dev_warn(afe->dev, "%s(), id %d not support\n",
761
__func__, i2s_id);
762
return -EINVAL;
763
}
764
765
/* set share i2s */
766
if (i2s_priv && i2s_priv->share_i2s_id >= 0)
767
ret = mtk_dai_i2s_config(afe, params, i2s_priv->share_i2s_id);
768
769
return ret;
770
}
771
772
static int mtk_dai_i2s_hw_params(struct snd_pcm_substream *substream,
773
struct snd_pcm_hw_params *params,
774
struct snd_soc_dai *dai)
775
{
776
struct mtk_base_afe *afe = snd_soc_dai_get_drvdata(dai);
777
778
return mtk_dai_i2s_config(afe, params, dai->id);
779
}
780
781
static int mtk_dai_i2s_set_sysclk(struct snd_soc_dai *dai,
782
int clk_id, unsigned int freq, int dir)
783
{
784
struct mtk_base_afe *afe = dev_get_drvdata(dai->dev);
785
struct mt8183_afe_private *afe_priv = afe->platform_priv;
786
struct mtk_afe_i2s_priv *i2s_priv = afe_priv->dai_priv[dai->id];
787
int apll;
788
int apll_rate;
789
790
if (!i2s_priv) {
791
dev_warn(afe->dev, "%s(), i2s_priv == NULL", __func__);
792
return -EINVAL;
793
}
794
795
if (dir != SND_SOC_CLOCK_OUT) {
796
dev_warn(afe->dev, "%s(), dir != SND_SOC_CLOCK_OUT", __func__);
797
return -EINVAL;
798
}
799
800
apll = mt8183_get_apll_by_rate(afe, freq);
801
apll_rate = mt8183_get_apll_rate(afe, apll);
802
803
if (freq > apll_rate) {
804
dev_warn(afe->dev, "%s(), freq > apll rate", __func__);
805
return -EINVAL;
806
}
807
808
if (apll_rate % freq != 0) {
809
dev_warn(afe->dev, "%s(), APLL cannot generate freq Hz",
810
__func__);
811
return -EINVAL;
812
}
813
814
i2s_priv->mclk_rate = freq;
815
i2s_priv->mclk_apll = apll;
816
817
if (i2s_priv->share_i2s_id > 0) {
818
struct mtk_afe_i2s_priv *share_i2s_priv;
819
820
share_i2s_priv = afe_priv->dai_priv[i2s_priv->share_i2s_id];
821
if (!share_i2s_priv) {
822
dev_warn(afe->dev, "%s(), share_i2s_priv == NULL",
823
__func__);
824
return -EINVAL;
825
}
826
827
share_i2s_priv->mclk_rate = i2s_priv->mclk_rate;
828
share_i2s_priv->mclk_apll = i2s_priv->mclk_apll;
829
}
830
831
return 0;
832
}
833
834
static int mtk_dai_i2s_set_fmt(struct snd_soc_dai *dai, unsigned int fmt)
835
{
836
struct mtk_base_afe *afe = snd_soc_dai_get_drvdata(dai);
837
struct mt8183_afe_private *afe_priv = afe->platform_priv;
838
struct mtk_afe_i2s_priv *i2s_priv;
839
840
switch (dai->id) {
841
case MT8183_DAI_I2S_0:
842
case MT8183_DAI_I2S_1:
843
case MT8183_DAI_I2S_2:
844
case MT8183_DAI_I2S_3:
845
case MT8183_DAI_I2S_5:
846
break;
847
default:
848
dev_warn(afe->dev, "%s(), id %d not support\n",
849
__func__, dai->id);
850
return -EINVAL;
851
}
852
i2s_priv = afe_priv->dai_priv[dai->id];
853
854
switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
855
case SND_SOC_DAIFMT_LEFT_J:
856
i2s_priv->use_eiaj = 1;
857
break;
858
case SND_SOC_DAIFMT_I2S:
859
i2s_priv->use_eiaj = 0;
860
break;
861
default:
862
dev_warn(afe->dev, "%s(), DAI format %d not support\n",
863
__func__, fmt & SND_SOC_DAIFMT_FORMAT_MASK);
864
return -EINVAL;
865
}
866
867
return 0;
868
}
869
870
static const struct snd_soc_dai_ops mtk_dai_i2s_ops = {
871
.hw_params = mtk_dai_i2s_hw_params,
872
.set_sysclk = mtk_dai_i2s_set_sysclk,
873
.set_fmt = mtk_dai_i2s_set_fmt,
874
};
875
876
/* dai driver */
877
#define MTK_I2S_RATES (SNDRV_PCM_RATE_8000_48000 |\
878
SNDRV_PCM_RATE_88200 |\
879
SNDRV_PCM_RATE_96000 |\
880
SNDRV_PCM_RATE_176400 |\
881
SNDRV_PCM_RATE_192000)
882
883
#define MTK_I2S_FORMATS (SNDRV_PCM_FMTBIT_S16_LE |\
884
SNDRV_PCM_FMTBIT_S24_LE |\
885
SNDRV_PCM_FMTBIT_S32_LE)
886
887
static struct snd_soc_dai_driver mtk_dai_i2s_driver[] = {
888
{
889
.name = "I2S0",
890
.id = MT8183_DAI_I2S_0,
891
.capture = {
892
.stream_name = "I2S0",
893
.channels_min = 1,
894
.channels_max = 2,
895
.rates = MTK_I2S_RATES,
896
.formats = MTK_I2S_FORMATS,
897
},
898
.ops = &mtk_dai_i2s_ops,
899
},
900
{
901
.name = "I2S1",
902
.id = MT8183_DAI_I2S_1,
903
.playback = {
904
.stream_name = "I2S1",
905
.channels_min = 1,
906
.channels_max = 2,
907
.rates = MTK_I2S_RATES,
908
.formats = MTK_I2S_FORMATS,
909
},
910
.ops = &mtk_dai_i2s_ops,
911
},
912
{
913
.name = "I2S2",
914
.id = MT8183_DAI_I2S_2,
915
.capture = {
916
.stream_name = "I2S2",
917
.channels_min = 1,
918
.channels_max = 2,
919
.rates = MTK_I2S_RATES,
920
.formats = MTK_I2S_FORMATS,
921
},
922
.ops = &mtk_dai_i2s_ops,
923
},
924
{
925
.name = "I2S3",
926
.id = MT8183_DAI_I2S_3,
927
.playback = {
928
.stream_name = "I2S3",
929
.channels_min = 1,
930
.channels_max = 2,
931
.rates = MTK_I2S_RATES,
932
.formats = MTK_I2S_FORMATS,
933
},
934
.ops = &mtk_dai_i2s_ops,
935
},
936
{
937
.name = "I2S5",
938
.id = MT8183_DAI_I2S_5,
939
.playback = {
940
.stream_name = "I2S5",
941
.channels_min = 1,
942
.channels_max = 2,
943
.rates = MTK_I2S_RATES,
944
.formats = MTK_I2S_FORMATS,
945
},
946
.ops = &mtk_dai_i2s_ops,
947
},
948
};
949
950
/* this enum is merely for mtk_afe_i2s_priv declare */
951
enum {
952
DAI_I2S0 = 0,
953
DAI_I2S1,
954
DAI_I2S2,
955
DAI_I2S3,
956
DAI_I2S5,
957
DAI_I2S_NUM,
958
};
959
960
static const struct mtk_afe_i2s_priv mt8183_i2s_priv[DAI_I2S_NUM] = {
961
[DAI_I2S0] = {
962
.id = MT8183_DAI_I2S_0,
963
.mclk_id = MT8183_I2S0_MCK,
964
.share_i2s_id = -1,
965
},
966
[DAI_I2S1] = {
967
.id = MT8183_DAI_I2S_1,
968
.mclk_id = MT8183_I2S1_MCK,
969
.share_i2s_id = -1,
970
},
971
[DAI_I2S2] = {
972
.id = MT8183_DAI_I2S_2,
973
.mclk_id = MT8183_I2S2_MCK,
974
.share_i2s_id = -1,
975
},
976
[DAI_I2S3] = {
977
.id = MT8183_DAI_I2S_3,
978
.mclk_id = MT8183_I2S3_MCK,
979
.share_i2s_id = -1,
980
},
981
[DAI_I2S5] = {
982
.id = MT8183_DAI_I2S_5,
983
.mclk_id = MT8183_I2S5_MCK,
984
.share_i2s_id = -1,
985
},
986
};
987
988
/**
989
* mt8183_dai_i2s_set_share() - Set up I2S ports to share a single clock.
990
* @afe: Pointer to &struct mtk_base_afe
991
* @main_i2s_name: The name of the I2S port that will provide the clock
992
* @secondary_i2s_name: The name of the I2S port that will use this clock
993
*/
994
int mt8183_dai_i2s_set_share(struct mtk_base_afe *afe, const char *main_i2s_name,
995
const char *secondary_i2s_name)
996
{
997
struct mtk_afe_i2s_priv *secondary_i2s_priv;
998
int main_i2s_id;
999
1000
secondary_i2s_priv = get_i2s_priv_by_name(afe, secondary_i2s_name);
1001
if (!secondary_i2s_priv)
1002
return -EINVAL;
1003
1004
main_i2s_id = get_i2s_id_by_name(afe, main_i2s_name);
1005
if (main_i2s_id < 0)
1006
return main_i2s_id;
1007
1008
secondary_i2s_priv->share_i2s_id = main_i2s_id;
1009
1010
return 0;
1011
}
1012
EXPORT_SYMBOL_GPL(mt8183_dai_i2s_set_share);
1013
1014
static int mt8183_dai_i2s_set_priv(struct mtk_base_afe *afe)
1015
{
1016
struct mt8183_afe_private *afe_priv = afe->platform_priv;
1017
struct mtk_afe_i2s_priv *i2s_priv;
1018
int i;
1019
1020
for (i = 0; i < DAI_I2S_NUM; i++) {
1021
i2s_priv = devm_kzalloc(afe->dev,
1022
sizeof(struct mtk_afe_i2s_priv),
1023
GFP_KERNEL);
1024
if (!i2s_priv)
1025
return -ENOMEM;
1026
1027
memcpy(i2s_priv, &mt8183_i2s_priv[i],
1028
sizeof(struct mtk_afe_i2s_priv));
1029
1030
afe_priv->dai_priv[mt8183_i2s_priv[i].id] = i2s_priv;
1031
}
1032
1033
return 0;
1034
}
1035
1036
int mt8183_dai_i2s_register(struct mtk_base_afe *afe)
1037
{
1038
struct mtk_base_afe_dai *dai;
1039
1040
dai = devm_kzalloc(afe->dev, sizeof(*dai), GFP_KERNEL);
1041
if (!dai)
1042
return -ENOMEM;
1043
1044
list_add(&dai->list, &afe->sub_dais);
1045
1046
dai->dai_drivers = mtk_dai_i2s_driver;
1047
dai->num_dai_drivers = ARRAY_SIZE(mtk_dai_i2s_driver);
1048
1049
dai->controls = mtk_dai_i2s_controls;
1050
dai->num_controls = ARRAY_SIZE(mtk_dai_i2s_controls);
1051
dai->dapm_widgets = mtk_dai_i2s_widgets;
1052
dai->num_dapm_widgets = ARRAY_SIZE(mtk_dai_i2s_widgets);
1053
dai->dapm_routes = mtk_dai_i2s_routes;
1054
dai->num_dapm_routes = ARRAY_SIZE(mtk_dai_i2s_routes);
1055
1056
/* set all dai i2s private data */
1057
return mt8183_dai_i2s_set_priv(afe);
1058
}
1059
1060