1 // SPDX-License-Identifier: GPL-2.0
3 // MediaTek ALSA SoC Audio DAI ADDA Control
5 // Copyright (c) 2018 MediaTek Inc.
6 // Author: KaiChieh Chuang <kaichieh.chuang@mediatek.com>
8 #include <linux/regmap.h>
9 #include <linux/delay.h>
10 #include "mt6797-afe-common.h"
11 #include "mt6797-interconnection.h"
12 #include "mt6797-reg.h"
15 MTK_AFE_ADDA_DL_RATE_8K
= 0,
16 MTK_AFE_ADDA_DL_RATE_11K
= 1,
17 MTK_AFE_ADDA_DL_RATE_12K
= 2,
18 MTK_AFE_ADDA_DL_RATE_16K
= 3,
19 MTK_AFE_ADDA_DL_RATE_22K
= 4,
20 MTK_AFE_ADDA_DL_RATE_24K
= 5,
21 MTK_AFE_ADDA_DL_RATE_32K
= 6,
22 MTK_AFE_ADDA_DL_RATE_44K
= 7,
23 MTK_AFE_ADDA_DL_RATE_48K
= 8,
24 MTK_AFE_ADDA_DL_RATE_96K
= 9,
25 MTK_AFE_ADDA_DL_RATE_192K
= 10,
29 MTK_AFE_ADDA_UL_RATE_8K
= 0,
30 MTK_AFE_ADDA_UL_RATE_16K
= 1,
31 MTK_AFE_ADDA_UL_RATE_32K
= 2,
32 MTK_AFE_ADDA_UL_RATE_48K
= 3,
33 MTK_AFE_ADDA_UL_RATE_96K
= 4,
34 MTK_AFE_ADDA_UL_RATE_192K
= 5,
35 MTK_AFE_ADDA_UL_RATE_48K_HD
= 6,
38 static unsigned int adda_dl_rate_transform(struct mtk_base_afe
*afe
,
43 return MTK_AFE_ADDA_DL_RATE_8K
;
45 return MTK_AFE_ADDA_DL_RATE_11K
;
47 return MTK_AFE_ADDA_DL_RATE_12K
;
49 return MTK_AFE_ADDA_DL_RATE_16K
;
51 return MTK_AFE_ADDA_DL_RATE_22K
;
53 return MTK_AFE_ADDA_DL_RATE_24K
;
55 return MTK_AFE_ADDA_DL_RATE_32K
;
57 return MTK_AFE_ADDA_DL_RATE_44K
;
59 return MTK_AFE_ADDA_DL_RATE_48K
;
61 return MTK_AFE_ADDA_DL_RATE_96K
;
63 return MTK_AFE_ADDA_DL_RATE_192K
;
65 dev_warn(afe
->dev
, "%s(), rate %d invalid, use 48kHz!!!\n",
67 return MTK_AFE_ADDA_DL_RATE_48K
;
71 static unsigned int adda_ul_rate_transform(struct mtk_base_afe
*afe
,
76 return MTK_AFE_ADDA_UL_RATE_8K
;
78 return MTK_AFE_ADDA_UL_RATE_16K
;
80 return MTK_AFE_ADDA_UL_RATE_32K
;
82 return MTK_AFE_ADDA_UL_RATE_48K
;
84 return MTK_AFE_ADDA_UL_RATE_96K
;
86 return MTK_AFE_ADDA_UL_RATE_192K
;
88 dev_warn(afe
->dev
, "%s(), rate %d invalid, use 48kHz!!!\n",
90 return MTK_AFE_ADDA_UL_RATE_48K
;
95 static const struct snd_kcontrol_new mtk_adda_dl_ch1_mix
[] = {
96 SOC_DAPM_SINGLE_AUTODISABLE("DL1_CH1", AFE_CONN3
, I_DL1_CH1
, 1, 0),
97 SOC_DAPM_SINGLE_AUTODISABLE("DL2_CH1", AFE_CONN3
, I_DL2_CH1
, 1, 0),
98 SOC_DAPM_SINGLE_AUTODISABLE("DL3_CH1", AFE_CONN3
, I_DL3_CH1
, 1, 0),
99 SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH2", AFE_CONN3
,
100 I_ADDA_UL_CH2
, 1, 0),
101 SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH1", AFE_CONN3
,
102 I_ADDA_UL_CH1
, 1, 0),
103 SOC_DAPM_SINGLE_AUTODISABLE("PCM_1_CAP_CH1", AFE_CONN3
,
104 I_PCM_1_CAP_CH1
, 1, 0),
105 SOC_DAPM_SINGLE_AUTODISABLE("PCM_2_CAP_CH1", AFE_CONN3
,
106 I_PCM_2_CAP_CH1
, 1, 0),
109 static const struct snd_kcontrol_new mtk_adda_dl_ch2_mix
[] = {
110 SOC_DAPM_SINGLE_AUTODISABLE("DL1_CH1", AFE_CONN4
, I_DL1_CH1
, 1, 0),
111 SOC_DAPM_SINGLE_AUTODISABLE("DL1_CH2", AFE_CONN4
, I_DL1_CH2
, 1, 0),
112 SOC_DAPM_SINGLE_AUTODISABLE("DL2_CH1", AFE_CONN4
, I_DL2_CH1
, 1, 0),
113 SOC_DAPM_SINGLE_AUTODISABLE("DL2_CH2", AFE_CONN4
, I_DL2_CH2
, 1, 0),
114 SOC_DAPM_SINGLE_AUTODISABLE("DL3_CH1", AFE_CONN4
, I_DL3_CH1
, 1, 0),
115 SOC_DAPM_SINGLE_AUTODISABLE("DL3_CH2", AFE_CONN4
, I_DL3_CH2
, 1, 0),
116 SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH2", AFE_CONN4
,
117 I_ADDA_UL_CH2
, 1, 0),
118 SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH1", AFE_CONN4
,
119 I_ADDA_UL_CH1
, 1, 0),
120 SOC_DAPM_SINGLE_AUTODISABLE("PCM_1_CAP_CH1", AFE_CONN4
,
121 I_PCM_1_CAP_CH1
, 1, 0),
122 SOC_DAPM_SINGLE_AUTODISABLE("PCM_2_CAP_CH1", AFE_CONN4
,
123 I_PCM_2_CAP_CH1
, 1, 0),
124 SOC_DAPM_SINGLE_AUTODISABLE("PCM_1_CAP_CH2", AFE_CONN4
,
125 I_PCM_1_CAP_CH2
, 1, 0),
126 SOC_DAPM_SINGLE_AUTODISABLE("PCM_2_CAP_CH2", AFE_CONN4
,
127 I_PCM_2_CAP_CH2
, 1, 0),
130 static int mtk_adda_ul_event(struct snd_soc_dapm_widget
*w
,
131 struct snd_kcontrol
*kcontrol
,
134 struct snd_soc_component
*cmpnt
= snd_soc_dapm_to_component(w
->dapm
);
135 struct mtk_base_afe
*afe
= snd_soc_component_get_drvdata(cmpnt
);
137 dev_dbg(afe
->dev
, "%s(), name %s, event 0x%x\n",
138 __func__
, w
->name
, event
);
141 case SND_SOC_DAPM_POST_PMD
:
142 /* should delayed 1/fs(smallest is 8k) = 125us before afe off */
143 usleep_range(125, 135);
153 SUPPLY_SEQ_AUD_TOP_PDN
,
154 SUPPLY_SEQ_ADDA_AFE_ON
,
155 SUPPLY_SEQ_ADDA_DL_ON
,
156 SUPPLY_SEQ_ADDA_UL_ON
,
159 static const struct snd_soc_dapm_widget mtk_dai_adda_widgets
[] = {
161 SND_SOC_DAPM_MIXER("ADDA_DL_CH1", SND_SOC_NOPM
, 0, 0,
163 ARRAY_SIZE(mtk_adda_dl_ch1_mix
)),
164 SND_SOC_DAPM_MIXER("ADDA_DL_CH2", SND_SOC_NOPM
, 0, 0,
166 ARRAY_SIZE(mtk_adda_dl_ch2_mix
)),
168 SND_SOC_DAPM_SUPPLY_S("ADDA Enable", SUPPLY_SEQ_ADDA_AFE_ON
,
169 AFE_ADDA_UL_DL_CON0
, ADDA_AFE_ON_SFT
, 0,
172 SND_SOC_DAPM_SUPPLY_S("ADDA Playback Enable", SUPPLY_SEQ_ADDA_DL_ON
,
173 AFE_ADDA_DL_SRC2_CON0
,
174 DL_2_SRC_ON_TMP_CTL_PRE_SFT
, 0,
177 SND_SOC_DAPM_SUPPLY_S("ADDA Capture Enable", SUPPLY_SEQ_ADDA_UL_ON
,
178 AFE_ADDA_UL_SRC_CON0
,
179 UL_SRC_ON_TMP_CTL_SFT
, 0,
181 SND_SOC_DAPM_POST_PMD
),
183 SND_SOC_DAPM_SUPPLY_S("aud_dac_clk", SUPPLY_SEQ_AUD_TOP_PDN
,
184 AUDIO_TOP_CON0
, PDN_DAC_SFT
, 1,
186 SND_SOC_DAPM_SUPPLY_S("aud_dac_predis_clk", SUPPLY_SEQ_AUD_TOP_PDN
,
187 AUDIO_TOP_CON0
, PDN_DAC_PREDIS_SFT
, 1,
190 SND_SOC_DAPM_SUPPLY_S("aud_adc_clk", SUPPLY_SEQ_AUD_TOP_PDN
,
191 AUDIO_TOP_CON0
, PDN_ADC_SFT
, 1,
194 SND_SOC_DAPM_CLOCK_SUPPLY("mtkaif_26m_clk"),
197 static const struct snd_soc_dapm_route mtk_dai_adda_routes
[] = {
199 {"ADDA_DL_CH1", "DL1_CH1", "DL1"},
200 {"ADDA_DL_CH2", "DL1_CH1", "DL1"},
201 {"ADDA_DL_CH2", "DL1_CH2", "DL1"},
203 {"ADDA_DL_CH1", "DL2_CH1", "DL2"},
204 {"ADDA_DL_CH2", "DL2_CH1", "DL2"},
205 {"ADDA_DL_CH2", "DL2_CH2", "DL2"},
207 {"ADDA_DL_CH1", "DL3_CH1", "DL3"},
208 {"ADDA_DL_CH2", "DL3_CH1", "DL3"},
209 {"ADDA_DL_CH2", "DL3_CH2", "DL3"},
211 {"ADDA Playback", NULL
, "ADDA_DL_CH1"},
212 {"ADDA Playback", NULL
, "ADDA_DL_CH2"},
215 {"ADDA Playback", NULL
, "ADDA Enable"},
216 {"ADDA Playback", NULL
, "ADDA Playback Enable"},
217 {"ADDA Capture", NULL
, "ADDA Enable"},
218 {"ADDA Capture", NULL
, "ADDA Capture Enable"},
221 {"ADDA Playback", NULL
, "mtkaif_26m_clk"},
222 {"ADDA Playback", NULL
, "aud_dac_clk"},
223 {"ADDA Playback", NULL
, "aud_dac_predis_clk"},
225 {"ADDA Capture", NULL
, "mtkaif_26m_clk"},
226 {"ADDA Capture", NULL
, "aud_adc_clk"},
230 static int mtk_dai_adda_hw_params(struct snd_pcm_substream
*substream
,
231 struct snd_pcm_hw_params
*params
,
232 struct snd_soc_dai
*dai
)
234 struct mtk_base_afe
*afe
= snd_soc_dai_get_drvdata(dai
);
235 unsigned int rate
= params_rate(params
);
237 dev_dbg(afe
->dev
, "%s(), id %d, stream %d, rate %d\n",
238 __func__
, dai
->id
, substream
->stream
, rate
);
240 if (substream
->stream
== SNDRV_PCM_STREAM_PLAYBACK
) {
241 unsigned int dl_src2_con0
= 0;
242 unsigned int dl_src2_con1
= 0;
244 /* clean predistortion */
245 regmap_write(afe
->regmap
, AFE_ADDA_PREDIS_CON0
, 0);
246 regmap_write(afe
->regmap
, AFE_ADDA_PREDIS_CON1
, 0);
248 /* set input sampling rate */
249 dl_src2_con0
= adda_dl_rate_transform(afe
, rate
) << 28;
251 /* set output mode */
254 dl_src2_con0
|= (0x1 << 24); /* UP_SAMPLING_RATE_X2 */
255 dl_src2_con0
|= 1 << 14;
258 dl_src2_con0
|= (0x2 << 24); /* UP_SAMPLING_RATE_X4 */
259 dl_src2_con0
|= 1 << 14;
262 dl_src2_con0
|= (0x3 << 24); /* UP_SAMPLING_RATE_X8 */
266 /* turn off mute function */
267 dl_src2_con0
|= (0x03 << 11);
269 /* set voice input data if input sample rate is 8k or 16k */
270 if (rate
== 8000 || rate
== 16000)
271 dl_src2_con0
|= 0x01 << 5;
274 /* SA suggest apply -0.3db to audio/speech path */
275 dl_src2_con1
= 0xf74f0000;
277 /* SA suggest apply -0.3db to audio/speech path
278 * with DL gain set to half,
279 * 0xFFFF = 0dB -> 0x8000 = 0dB when 96k, 192k
281 dl_src2_con1
= 0x7ba70000;
284 /* turn on down-link gain */
285 dl_src2_con0
= dl_src2_con0
| (0x01 << 1);
287 regmap_write(afe
->regmap
, AFE_ADDA_DL_SRC2_CON0
, dl_src2_con0
);
288 regmap_write(afe
->regmap
, AFE_ADDA_DL_SRC2_CON1
, dl_src2_con1
);
290 unsigned int voice_mode
= 0;
291 unsigned int ul_src_con0
= 0; /* default value */
293 /* Using Internal ADC */
294 regmap_update_bits(afe
->regmap
,
299 voice_mode
= adda_ul_rate_transform(afe
, rate
);
301 ul_src_con0
|= (voice_mode
<< 17) & (0x7 << 17);
303 /* up8x txif sat on */
304 regmap_write(afe
->regmap
, AFE_ADDA_NEWIF_CFG0
, 0x03F87201);
306 if (rate
>= 96000) { /* hires */
307 /* use hires format [1 0 23] */
308 regmap_update_bits(afe
->regmap
,
313 regmap_update_bits(afe
->regmap
,
317 } else { /* normal 8~48k */
318 /* use fixed 260k anc path */
319 regmap_update_bits(afe
->regmap
,
325 ul_src_con0
|= 0x1 << 20;
328 regmap_update_bits(afe
->regmap
,
333 regmap_update_bits(afe
->regmap
,
334 AFE_ADDA_UL_SRC_CON0
,
342 static const struct snd_soc_dai_ops mtk_dai_adda_ops
= {
343 .hw_params
= mtk_dai_adda_hw_params
,
347 #define MTK_ADDA_PLAYBACK_RATES (SNDRV_PCM_RATE_8000_48000 |\
348 SNDRV_PCM_RATE_96000 |\
349 SNDRV_PCM_RATE_192000)
351 #define MTK_ADDA_CAPTURE_RATES (SNDRV_PCM_RATE_8000 |\
352 SNDRV_PCM_RATE_16000 |\
353 SNDRV_PCM_RATE_32000 |\
354 SNDRV_PCM_RATE_48000 |\
355 SNDRV_PCM_RATE_96000 |\
356 SNDRV_PCM_RATE_192000)
358 #define MTK_ADDA_FORMATS (SNDRV_PCM_FMTBIT_S16_LE |\
359 SNDRV_PCM_FMTBIT_S24_LE |\
360 SNDRV_PCM_FMTBIT_S32_LE)
362 static struct snd_soc_dai_driver mtk_dai_adda_driver
[] = {
365 .id
= MT6797_DAI_ADDA
,
367 .stream_name
= "ADDA Playback",
370 .rates
= MTK_ADDA_PLAYBACK_RATES
,
371 .formats
= MTK_ADDA_FORMATS
,
374 .stream_name
= "ADDA Capture",
377 .rates
= MTK_ADDA_CAPTURE_RATES
,
378 .formats
= MTK_ADDA_FORMATS
,
380 .ops
= &mtk_dai_adda_ops
,
384 int mt6797_dai_adda_register(struct mtk_base_afe
*afe
)
386 struct mtk_base_afe_dai
*dai
;
388 dai
= devm_kzalloc(afe
->dev
, sizeof(*dai
), GFP_KERNEL
);
392 list_add(&dai
->list
, &afe
->sub_dais
);
394 dai
->dai_drivers
= mtk_dai_adda_driver
;
395 dai
->num_dai_drivers
= ARRAY_SIZE(mtk_dai_adda_driver
);
397 dai
->dapm_widgets
= mtk_dai_adda_widgets
;
398 dai
->num_dapm_widgets
= ARRAY_SIZE(mtk_dai_adda_widgets
);
399 dai
->dapm_routes
= mtk_dai_adda_routes
;
400 dai
->num_dapm_routes
= ARRAY_SIZE(mtk_dai_adda_routes
);