Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
torvalds
GitHub Repository: torvalds/linux
Path: blob/master/sound/soc/mediatek/mt8365/mt8365-dai-dmic.c
26488 views
1
// SPDX-License-Identifier: GPL-2.0
2
/*
3
* MediaTek 8365 ALSA SoC Audio DAI DMIC 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
struct mt8365_dmic_data {
17
bool two_wire_mode;
18
unsigned int clk_phase_sel_ch1;
19
unsigned int clk_phase_sel_ch2;
20
bool iir_on;
21
unsigned int irr_mode;
22
unsigned int dmic_mode;
23
unsigned int dmic_channel;
24
};
25
26
static int get_chan_reg(unsigned int channel)
27
{
28
switch (channel) {
29
case 8:
30
fallthrough;
31
case 7:
32
return AFE_DMIC3_UL_SRC_CON0;
33
case 6:
34
fallthrough;
35
case 5:
36
return AFE_DMIC2_UL_SRC_CON0;
37
case 4:
38
fallthrough;
39
case 3:
40
return AFE_DMIC1_UL_SRC_CON0;
41
case 2:
42
fallthrough;
43
case 1:
44
return AFE_DMIC0_UL_SRC_CON0;
45
default:
46
return -EINVAL;
47
}
48
}
49
50
/* DAI Drivers */
51
52
static void audio_dmic_adda_enable(struct mtk_base_afe *afe)
53
{
54
mt8365_dai_enable_adda_on(afe);
55
regmap_update_bits(afe->regmap, AFE_ADDA_UL_DL_CON0,
56
AFE_ADDA_UL_DL_DMIC_CLKDIV_ON,
57
AFE_ADDA_UL_DL_DMIC_CLKDIV_ON);
58
}
59
60
static void audio_dmic_adda_disable(struct mtk_base_afe *afe)
61
{
62
regmap_update_bits(afe->regmap, AFE_ADDA_UL_DL_CON0,
63
AFE_ADDA_UL_DL_DMIC_CLKDIV_ON,
64
~AFE_ADDA_UL_DL_DMIC_CLKDIV_ON);
65
mt8365_dai_disable_adda_on(afe);
66
}
67
68
static void mt8365_dai_enable_dmic(struct mtk_base_afe *afe,
69
struct snd_pcm_substream *substream,
70
struct snd_soc_dai *dai)
71
{
72
struct mt8365_afe_private *afe_priv = afe->platform_priv;
73
struct mt8365_dmic_data *dmic_data = afe_priv->dai_priv[MT8365_AFE_IO_DMIC];
74
unsigned int val_mask;
75
int reg = get_chan_reg(dmic_data->dmic_channel);
76
77
if (reg < 0)
78
return;
79
80
/* val and mask will be always same to enable */
81
val_mask = DMIC_TOP_CON_CH1_ON |
82
DMIC_TOP_CON_CH2_ON |
83
DMIC_TOP_CON_SRC_ON;
84
85
regmap_update_bits(afe->regmap, reg, val_mask, val_mask);
86
}
87
88
static void mt8365_dai_disable_dmic(struct mtk_base_afe *afe,
89
struct snd_pcm_substream *substream,
90
struct snd_soc_dai *dai)
91
{
92
struct mt8365_afe_private *afe_priv = afe->platform_priv;
93
struct mt8365_dmic_data *dmic_data = afe_priv->dai_priv[MT8365_AFE_IO_DMIC];
94
unsigned int mask;
95
int reg = get_chan_reg(dmic_data->dmic_channel);
96
97
if (reg < 0)
98
return;
99
100
dev_dbg(afe->dev, "%s dmic_channel %d\n", __func__, dmic_data->dmic_channel);
101
102
mask = DMIC_TOP_CON_CH1_ON |
103
DMIC_TOP_CON_CH2_ON |
104
DMIC_TOP_CON_SRC_ON |
105
DMIC_TOP_CON_SDM3_LEVEL_MODE;
106
107
/* Set all masked values to 0 */
108
regmap_update_bits(afe->regmap, reg, mask, 0);
109
}
110
111
static int mt8365_dai_configure_dmic(struct mtk_base_afe *afe,
112
struct snd_pcm_substream *substream,
113
struct snd_soc_dai *dai)
114
{
115
struct mt8365_afe_private *afe_priv = afe->platform_priv;
116
struct mt8365_dmic_data *dmic_data = afe_priv->dai_priv[MT8365_AFE_IO_DMIC];
117
bool two_wire_mode = dmic_data->two_wire_mode;
118
unsigned int clk_phase_sel_ch1 = dmic_data->clk_phase_sel_ch1;
119
unsigned int clk_phase_sel_ch2 = dmic_data->clk_phase_sel_ch2;
120
unsigned int val = 0;
121
unsigned int rate = dai->symmetric_rate;
122
int reg = get_chan_reg(dai->symmetric_channels);
123
124
if (reg < 0)
125
return -EINVAL;
126
127
dmic_data->dmic_channel = dai->symmetric_channels;
128
129
val |= DMIC_TOP_CON_SDM3_LEVEL_MODE;
130
131
if (two_wire_mode) {
132
val |= DMIC_TOP_CON_TWO_WIRE_MODE;
133
} else {
134
val |= FIELD_PREP(DMIC_TOP_CON_CK_PHASE_SEL_CH1,
135
clk_phase_sel_ch1);
136
val |= FIELD_PREP(DMIC_TOP_CON_CK_PHASE_SEL_CH2,
137
clk_phase_sel_ch2);
138
}
139
140
switch (rate) {
141
case 48000:
142
val |= DMIC_TOP_CON_VOICE_MODE_48K;
143
break;
144
case 32000:
145
val |= DMIC_TOP_CON_VOICE_MODE_32K;
146
break;
147
case 16000:
148
val |= DMIC_TOP_CON_VOICE_MODE_16K;
149
break;
150
case 8000:
151
val |= DMIC_TOP_CON_VOICE_MODE_8K;
152
break;
153
default:
154
return -EINVAL;
155
}
156
157
regmap_update_bits(afe->regmap, reg, DMIC_TOP_CON_CONFIG_MASK, val);
158
159
return 0;
160
}
161
162
static int mt8365_dai_dmic_startup(struct snd_pcm_substream *substream,
163
struct snd_soc_dai *dai)
164
{
165
struct mtk_base_afe *afe = snd_soc_dai_get_drvdata(dai);
166
167
mt8365_afe_enable_main_clk(afe);
168
169
mt8365_afe_enable_top_cg(afe, MT8365_TOP_CG_DMIC0_ADC);
170
mt8365_afe_enable_top_cg(afe, MT8365_TOP_CG_DMIC1_ADC);
171
mt8365_afe_enable_top_cg(afe, MT8365_TOP_CG_DMIC2_ADC);
172
mt8365_afe_enable_top_cg(afe, MT8365_TOP_CG_DMIC3_ADC);
173
174
audio_dmic_adda_enable(afe);
175
176
return 0;
177
}
178
179
static void mt8365_dai_dmic_shutdown(struct snd_pcm_substream *substream,
180
struct snd_soc_dai *dai)
181
{
182
struct mtk_base_afe *afe = snd_soc_dai_get_drvdata(dai);
183
184
mt8365_dai_disable_dmic(afe, substream, dai);
185
audio_dmic_adda_disable(afe);
186
/* HW Request delay 125us before CG off */
187
usleep_range(125, 300);
188
mt8365_afe_disable_top_cg(afe, MT8365_TOP_CG_DMIC3_ADC);
189
mt8365_afe_disable_top_cg(afe, MT8365_TOP_CG_DMIC2_ADC);
190
mt8365_afe_disable_top_cg(afe, MT8365_TOP_CG_DMIC1_ADC);
191
mt8365_afe_disable_top_cg(afe, MT8365_TOP_CG_DMIC0_ADC);
192
193
mt8365_afe_disable_main_clk(afe);
194
}
195
196
static int mt8365_dai_dmic_prepare(struct snd_pcm_substream *substream,
197
struct snd_soc_dai *dai)
198
{
199
struct mtk_base_afe *afe = snd_soc_dai_get_drvdata(dai);
200
201
mt8365_dai_configure_dmic(afe, substream, dai);
202
mt8365_dai_enable_dmic(afe, substream, dai);
203
204
return 0;
205
}
206
207
static const struct snd_soc_dai_ops mt8365_afe_dmic_ops = {
208
.startup = mt8365_dai_dmic_startup,
209
.shutdown = mt8365_dai_dmic_shutdown,
210
.prepare = mt8365_dai_dmic_prepare,
211
};
212
213
static struct snd_soc_dai_driver mtk_dai_dmic_driver[] = {
214
{
215
.name = "DMIC",
216
.id = MT8365_AFE_IO_DMIC,
217
.capture = {
218
.stream_name = "DMIC Capture",
219
.channels_min = 1,
220
.channels_max = 8,
221
.rates = SNDRV_PCM_RATE_16000 |
222
SNDRV_PCM_RATE_32000 |
223
SNDRV_PCM_RATE_48000,
224
.formats = SNDRV_PCM_FMTBIT_S16_LE |
225
SNDRV_PCM_FMTBIT_S32_LE,
226
},
227
.ops = &mt8365_afe_dmic_ops,
228
}
229
};
230
231
/* DAI Controls */
232
233
/* Values for 48kHz mode */
234
static const char * const iir_mode_src[] = {
235
"SW custom", "5Hz", "10Hz", "25Hz", "50Hz", "65Hz"
236
};
237
238
static SOC_ENUM_SINGLE_DECL(iir_mode, AFE_DMIC0_UL_SRC_CON0, 7, iir_mode_src);
239
240
static const struct snd_kcontrol_new mtk_dai_dmic_controls[] = {
241
SOC_SINGLE("DMIC IIR Switch", AFE_DMIC0_UL_SRC_CON0, DMIC_TOP_CON_IIR_ON, 1, 0),
242
SOC_ENUM("DMIC IIR Mode", iir_mode),
243
};
244
245
/* DAI widget */
246
247
static const struct snd_soc_dapm_widget mtk_dai_dmic_widgets[] = {
248
SND_SOC_DAPM_INPUT("DMIC In"),
249
};
250
251
/* DAI route */
252
253
static const struct snd_soc_dapm_route mtk_dai_dmic_routes[] = {
254
{"I14", NULL, "DMIC Capture"},
255
{"I15", NULL, "DMIC Capture"},
256
{"I16", NULL, "DMIC Capture"},
257
{"I17", NULL, "DMIC Capture"},
258
{"I18", NULL, "DMIC Capture"},
259
{"I19", NULL, "DMIC Capture"},
260
{"I20", NULL, "DMIC Capture"},
261
{"I21", NULL, "DMIC Capture"},
262
{"DMIC Capture", NULL, "DMIC In"},
263
};
264
265
static int init_dmic_priv_data(struct mtk_base_afe *afe)
266
{
267
struct mt8365_afe_private *afe_priv = afe->platform_priv;
268
struct mt8365_dmic_data *dmic_priv;
269
struct device_node *np = afe->dev->of_node;
270
unsigned int temps[4];
271
int ret;
272
273
dmic_priv = devm_kzalloc(afe->dev, sizeof(*dmic_priv), GFP_KERNEL);
274
if (!dmic_priv)
275
return -ENOMEM;
276
277
ret = of_property_read_u32_array(np, "mediatek,dmic-mode",
278
&temps[0],
279
1);
280
if (ret == 0)
281
dmic_priv->two_wire_mode = !!temps[0];
282
283
if (!dmic_priv->two_wire_mode) {
284
dmic_priv->clk_phase_sel_ch1 = 0;
285
dmic_priv->clk_phase_sel_ch2 = 4;
286
}
287
288
afe_priv->dai_priv[MT8365_AFE_IO_DMIC] = dmic_priv;
289
return 0;
290
}
291
292
int mt8365_dai_dmic_register(struct mtk_base_afe *afe)
293
{
294
struct mtk_base_afe_dai *dai;
295
296
dai = devm_kzalloc(afe->dev, sizeof(*dai), GFP_KERNEL);
297
if (!dai)
298
return -ENOMEM;
299
300
list_add(&dai->list, &afe->sub_dais);
301
dai->dai_drivers = mtk_dai_dmic_driver;
302
dai->num_dai_drivers = ARRAY_SIZE(mtk_dai_dmic_driver);
303
dai->controls = mtk_dai_dmic_controls;
304
dai->num_controls = ARRAY_SIZE(mtk_dai_dmic_controls);
305
dai->dapm_widgets = mtk_dai_dmic_widgets;
306
dai->num_dapm_widgets = ARRAY_SIZE(mtk_dai_dmic_widgets);
307
dai->dapm_routes = mtk_dai_dmic_routes;
308
dai->num_dapm_routes = ARRAY_SIZE(mtk_dai_dmic_routes);
309
return init_dmic_priv_data(afe);
310
}
311
312