1 // SPDX-License-Identifier: GPL-2.0
3 // MediaTek ALSA SoC Audio DAI I2S Control
5 // Copyright (c) 2020 MediaTek Inc.
6 // Author: Shane Chien <shane.chien@mediatek.com>
9 #include <linux/regmap.h>
10 #include <sound/pcm_params.h>
12 #include "mt8192-afe-common.h"
13 #include "mt8192-interconnection.h"
16 AUD_TX_LCH_RPT_NO_REPEAT
= 0,
17 AUD_TX_LCH_RPT_REPEAT
= 1
20 enum AUD_VBT_16K_MODE
{
21 AUD_VBT_16K_MODE_DISABLE
= 0,
22 AUD_VBT_16K_MODE_ENABLE
= 1
26 AUD_EXT_MODEM_SELECT_INTERNAL
= 0,
27 AUD_EXT_MODEM_SELECT_EXTERNAL
= 1
30 enum AUD_PCM_SYNC_TYPE
{
31 /* bck sync length = 1 */
32 AUD_PCM_ONE_BCK_CYCLE_SYNC
= 0,
33 /* bck sync length = PCM_INTF_CON1[9:13] */
34 AUD_PCM_EXTENDED_BCK_CYCLE_SYNC
= 1
38 AUD_BT_MODE_DUAL_MIC_ON_TX
= 0,
39 AUD_BT_MODE_SINGLE_MIC_ON_TX
= 1
42 enum AUD_PCM_AFIFO_SRC
{
43 /* slave mode & external modem uses different crystal */
44 AUD_PCM_AFIFO_ASRC
= 0,
45 /* slave mode & external modem uses the same crystal */
46 AUD_PCM_AFIFO_AFIFO
= 1
49 enum AUD_PCM_CLOCK_SOURCE
{
50 AUD_PCM_CLOCK_MASTER_MODE
= 0,
51 AUD_PCM_CLOCK_SLAVE_MODE
= 1
55 AUD_PCM_WLEN_PCM_32_BCK_CYCLES
= 0,
56 AUD_PCM_WLEN_PCM_64_BCK_CYCLES
= 1
60 AUD_PCM_MODE_PCM_MODE_8K
= 0,
61 AUD_PCM_MODE_PCM_MODE_16K
= 1,
62 AUD_PCM_MODE_PCM_MODE_32K
= 2,
63 AUD_PCM_MODE_PCM_MODE_48K
= 3,
69 AUD_PCM_FMT_PCM_MODE_A
= 2,
70 AUD_PCM_FMT_PCM_MODE_B
= 3
73 enum AUD_BCLK_OUT_INV
{
74 AUD_BCLK_OUT_INV_NO_INVERSE
= 0,
75 AUD_BCLK_OUT_INV_INVERSE
= 1
79 AUD_PCM_EN_DISABLE
= 0,
84 static const struct snd_kcontrol_new mtk_pcm_1_playback_ch1_mix
[] = {
85 SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH1", AFE_CONN7
,
87 SOC_DAPM_SINGLE_AUTODISABLE("DL2_CH1", AFE_CONN7
,
89 SOC_DAPM_SINGLE_AUTODISABLE("DL4_CH1", AFE_CONN7_1
,
93 static const struct snd_kcontrol_new mtk_pcm_1_playback_ch2_mix
[] = {
94 SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH2", AFE_CONN8
,
96 SOC_DAPM_SINGLE_AUTODISABLE("DL2_CH2", AFE_CONN8
,
98 SOC_DAPM_SINGLE_AUTODISABLE("DL4_CH2", AFE_CONN8_1
,
102 static const struct snd_kcontrol_new mtk_pcm_1_playback_ch4_mix
[] = {
103 SOC_DAPM_SINGLE_AUTODISABLE("I2S0_CH1", AFE_CONN27
,
105 SOC_DAPM_SINGLE_AUTODISABLE("I2S0_CH2", AFE_CONN27
,
107 SOC_DAPM_SINGLE_AUTODISABLE("DL1_CH1", AFE_CONN27
,
109 SOC_DAPM_SINGLE_AUTODISABLE("I2S2_CH1", AFE_CONN27
,
111 SOC_DAPM_SINGLE_AUTODISABLE("I2S2_CH2", AFE_CONN27
,
113 SOC_DAPM_SINGLE_AUTODISABLE("DL4_CH1", AFE_CONN27_1
,
117 static const struct snd_kcontrol_new mtk_pcm_2_playback_ch1_mix
[] = {
118 SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH1", AFE_CONN17
,
119 I_ADDA_UL_CH1
, 1, 0),
120 SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH2", AFE_CONN17
,
121 I_ADDA_UL_CH2
, 1, 0),
122 SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH3", AFE_CONN17
,
123 I_ADDA_UL_CH3
, 1, 0),
124 SOC_DAPM_SINGLE_AUTODISABLE("DL2_CH1", AFE_CONN17
,
126 SOC_DAPM_SINGLE_AUTODISABLE("DL4_CH1", AFE_CONN17_1
,
130 static const struct snd_kcontrol_new mtk_pcm_2_playback_ch2_mix
[] = {
131 SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH1", AFE_CONN18
,
132 I_ADDA_UL_CH1
, 1, 0),
133 SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH2", AFE_CONN18
,
134 I_ADDA_UL_CH2
, 1, 0),
135 SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH3", AFE_CONN18
,
136 I_ADDA_UL_CH3
, 1, 0),
137 SOC_DAPM_SINGLE_AUTODISABLE("DL2_CH2", AFE_CONN18
,
139 SOC_DAPM_SINGLE_AUTODISABLE("DL4_CH2", AFE_CONN18_1
,
143 static const struct snd_kcontrol_new mtk_pcm_2_playback_ch3_mix
[] = {
144 SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH3", AFE_CONN23
,
145 I_ADDA_UL_CH3
, 1, 0),
148 static const struct snd_kcontrol_new mtk_pcm_2_playback_ch4_mix
[] = {
149 SOC_DAPM_SINGLE_AUTODISABLE("I2S0_CH1", AFE_CONN24
,
151 SOC_DAPM_SINGLE_AUTODISABLE("I2S0_CH2", AFE_CONN24
,
153 SOC_DAPM_SINGLE_AUTODISABLE("DL1_CH1", AFE_CONN24
,
155 SOC_DAPM_SINGLE_AUTODISABLE("I2S2_CH1", AFE_CONN24
,
157 SOC_DAPM_SINGLE_AUTODISABLE("I2S2_CH2", AFE_CONN24
,
159 SOC_DAPM_SINGLE_AUTODISABLE("DL4_CH1", AFE_CONN24_1
,
163 static const struct snd_kcontrol_new mtk_pcm_2_playback_ch5_mix
[] = {
164 SOC_DAPM_SINGLE_AUTODISABLE("I2S0_CH2", AFE_CONN25
,
166 SOC_DAPM_SINGLE_AUTODISABLE("DL1_CH2", AFE_CONN25
,
168 SOC_DAPM_SINGLE_AUTODISABLE("I2S2_CH2", AFE_CONN25
,
170 SOC_DAPM_SINGLE_AUTODISABLE("DL4_CH2", AFE_CONN25_1
,
174 static int mtk_pcm_en_event(struct snd_soc_dapm_widget
*w
,
175 struct snd_kcontrol
*kcontrol
,
178 struct snd_soc_component
*cmpnt
= snd_soc_dapm_to_component(w
->dapm
);
179 struct mtk_base_afe
*afe
= snd_soc_component_get_drvdata(cmpnt
);
181 dev_info(afe
->dev
, "%s(), name %s, event 0x%x\n",
182 __func__
, w
->name
, event
);
186 static const struct snd_soc_dapm_widget mtk_dai_pcm_widgets
[] = {
187 /* inter-connections */
188 SND_SOC_DAPM_MIXER("PCM_1_PB_CH1", SND_SOC_NOPM
, 0, 0,
189 mtk_pcm_1_playback_ch1_mix
,
190 ARRAY_SIZE(mtk_pcm_1_playback_ch1_mix
)),
191 SND_SOC_DAPM_MIXER("PCM_1_PB_CH2", SND_SOC_NOPM
, 0, 0,
192 mtk_pcm_1_playback_ch2_mix
,
193 ARRAY_SIZE(mtk_pcm_1_playback_ch2_mix
)),
194 SND_SOC_DAPM_MIXER("PCM_1_PB_CH4", SND_SOC_NOPM
, 0, 0,
195 mtk_pcm_1_playback_ch4_mix
,
196 ARRAY_SIZE(mtk_pcm_1_playback_ch4_mix
)),
197 SND_SOC_DAPM_MIXER("PCM_2_PB_CH1", SND_SOC_NOPM
, 0, 0,
198 mtk_pcm_2_playback_ch1_mix
,
199 ARRAY_SIZE(mtk_pcm_2_playback_ch1_mix
)),
200 SND_SOC_DAPM_MIXER("PCM_2_PB_CH2", SND_SOC_NOPM
, 0, 0,
201 mtk_pcm_2_playback_ch2_mix
,
202 ARRAY_SIZE(mtk_pcm_2_playback_ch2_mix
)),
203 SND_SOC_DAPM_MIXER("PCM_2_PB_CH3", SND_SOC_NOPM
, 0, 0,
204 mtk_pcm_2_playback_ch3_mix
,
205 ARRAY_SIZE(mtk_pcm_2_playback_ch3_mix
)),
206 SND_SOC_DAPM_MIXER("PCM_2_PB_CH4", SND_SOC_NOPM
, 0, 0,
207 mtk_pcm_2_playback_ch4_mix
,
208 ARRAY_SIZE(mtk_pcm_2_playback_ch4_mix
)),
209 SND_SOC_DAPM_MIXER("PCM_2_PB_CH5", SND_SOC_NOPM
, 0, 0,
210 mtk_pcm_2_playback_ch5_mix
,
211 ARRAY_SIZE(mtk_pcm_2_playback_ch5_mix
)),
213 SND_SOC_DAPM_SUPPLY("PCM_1_EN",
214 PCM_INTF_CON1
, PCM_EN_SFT
, 0,
216 SND_SOC_DAPM_PRE_PMU
| SND_SOC_DAPM_POST_PMD
),
218 SND_SOC_DAPM_SUPPLY("PCM_2_EN",
219 PCM2_INTF_CON
, PCM2_EN_SFT
, 0,
221 SND_SOC_DAPM_PRE_PMU
| SND_SOC_DAPM_POST_PMD
),
223 SND_SOC_DAPM_INPUT("MD1_TO_AFE"),
224 SND_SOC_DAPM_INPUT("MD2_TO_AFE"),
225 SND_SOC_DAPM_OUTPUT("AFE_TO_MD1"),
226 SND_SOC_DAPM_OUTPUT("AFE_TO_MD2"),
229 static const struct snd_soc_dapm_route mtk_dai_pcm_routes
[] = {
230 {"PCM 1 Playback", NULL
, "PCM_1_PB_CH1"},
231 {"PCM 1 Playback", NULL
, "PCM_1_PB_CH2"},
232 {"PCM 1 Playback", NULL
, "PCM_1_PB_CH4"},
233 {"PCM 2 Playback", NULL
, "PCM_2_PB_CH1"},
234 {"PCM 2 Playback", NULL
, "PCM_2_PB_CH2"},
235 {"PCM 2 Playback", NULL
, "PCM_2_PB_CH3"},
236 {"PCM 2 Playback", NULL
, "PCM_2_PB_CH4"},
237 {"PCM 2 Playback", NULL
, "PCM_2_PB_CH5"},
239 {"PCM 1 Playback", NULL
, "PCM_1_EN"},
240 {"PCM 2 Playback", NULL
, "PCM_2_EN"},
241 {"PCM 1 Capture", NULL
, "PCM_1_EN"},
242 {"PCM 2 Capture", NULL
, "PCM_2_EN"},
244 {"AFE_TO_MD1", NULL
, "PCM 2 Playback"},
245 {"AFE_TO_MD2", NULL
, "PCM 1 Playback"},
246 {"PCM 2 Capture", NULL
, "MD1_TO_AFE"},
247 {"PCM 1 Capture", NULL
, "MD2_TO_AFE"},
249 {"PCM_1_PB_CH1", "DL2_CH1", "DL2"},
250 {"PCM_1_PB_CH2", "DL2_CH2", "DL2"},
251 {"PCM_1_PB_CH4", "DL1_CH1", "DL1"},
252 {"PCM_2_PB_CH1", "DL2_CH1", "DL2"},
253 {"PCM_2_PB_CH2", "DL2_CH2", "DL2"},
254 {"PCM_2_PB_CH4", "DL1_CH1", "DL1"},
256 {"PCM_1_PB_CH1", "DL4_CH1", "DL4"},
257 {"PCM_1_PB_CH2", "DL4_CH2", "DL4"},
258 {"PCM_1_PB_CH4", "DL4_CH1", "DL4"},
259 {"PCM_2_PB_CH1", "DL4_CH1", "DL4"},
260 {"PCM_2_PB_CH2", "DL4_CH2", "DL4"},
261 {"PCM_2_PB_CH4", "DL4_CH1", "DL4"},
262 {"PCM_1_PB_CH4", "I2S0_CH1", "I2S0"},
263 {"PCM_2_PB_CH4", "I2S2_CH1", "I2S2"},
264 {"PCM_2_PB_CH5", "DL1_CH2", "DL1"},
265 {"PCM_2_PB_CH5", "DL4_CH2", "DL4"},
266 {"PCM_2_PB_CH5", "I2S0_CH2", "I2S0"},
267 {"PCM_2_PB_CH5", "I2S2_CH2", "I2S2"},
271 static int mtk_dai_pcm_hw_params(struct snd_pcm_substream
*substream
,
272 struct snd_pcm_hw_params
*params
,
273 struct snd_soc_dai
*dai
)
275 struct mtk_base_afe
*afe
= snd_soc_dai_get_drvdata(dai
);
276 unsigned int rate
= params_rate(params
);
277 unsigned int rate_reg
= mt8192_rate_transform(afe
->dev
, rate
, dai
->id
);
278 unsigned int pcm_con
= 0;
280 dev_info(afe
->dev
, "%s(), id %d, stream %d, rate %d, rate_reg %d, widget active p %d, c %d\n",
286 dai
->playback_widget
->active
,
287 dai
->capture_widget
->active
);
289 if (dai
->playback_widget
->active
|| dai
->capture_widget
->active
)
293 case MT8192_DAI_PCM_1
:
294 pcm_con
|= AUD_BCLK_OUT_INV_NO_INVERSE
<< PCM_BCLK_OUT_INV_SFT
;
295 pcm_con
|= AUD_TX_LCH_RPT_NO_REPEAT
<< PCM_TX_LCH_RPT_SFT
;
296 pcm_con
|= AUD_VBT_16K_MODE_DISABLE
<< PCM_VBT_16K_MODE_SFT
;
297 pcm_con
|= AUD_EXT_MODEM_SELECT_INTERNAL
<< PCM_EXT_MODEM_SFT
;
298 pcm_con
|= 0 << PCM_SYNC_LENGTH_SFT
;
299 pcm_con
|= AUD_PCM_ONE_BCK_CYCLE_SYNC
<< PCM_SYNC_TYPE_SFT
;
300 pcm_con
|= AUD_BT_MODE_DUAL_MIC_ON_TX
<< PCM_BT_MODE_SFT
;
301 pcm_con
|= AUD_PCM_AFIFO_AFIFO
<< PCM_BYP_ASRC_SFT
;
302 pcm_con
|= AUD_PCM_CLOCK_SLAVE_MODE
<< PCM_SLAVE_SFT
;
303 pcm_con
|= rate_reg
<< PCM_MODE_SFT
;
304 pcm_con
|= AUD_PCM_FMT_PCM_MODE_B
<< PCM_FMT_SFT
;
306 regmap_update_bits(afe
->regmap
, PCM_INTF_CON1
,
307 0xfffffffe, pcm_con
);
309 case MT8192_DAI_PCM_2
:
310 pcm_con
|= AUD_TX_LCH_RPT_NO_REPEAT
<< PCM2_TX_LCH_RPT_SFT
;
311 pcm_con
|= AUD_VBT_16K_MODE_DISABLE
<< PCM2_VBT_16K_MODE_SFT
;
312 pcm_con
|= AUD_BT_MODE_DUAL_MIC_ON_TX
<< PCM2_BT_MODE_SFT
;
313 pcm_con
|= AUD_PCM_AFIFO_AFIFO
<< PCM2_AFIFO_SFT
;
314 pcm_con
|= AUD_PCM_WLEN_PCM_32_BCK_CYCLES
<< PCM2_WLEN_SFT
;
315 pcm_con
|= rate_reg
<< PCM2_MODE_SFT
;
316 pcm_con
|= AUD_PCM_FMT_PCM_MODE_B
<< PCM2_FMT_SFT
;
318 regmap_update_bits(afe
->regmap
, PCM2_INTF_CON
,
319 0xfffffffe, pcm_con
);
322 dev_warn(afe
->dev
, "%s(), id %d not support\n",
330 static const struct snd_soc_dai_ops mtk_dai_pcm_ops
= {
331 .hw_params
= mtk_dai_pcm_hw_params
,
335 #define MTK_PCM_RATES (SNDRV_PCM_RATE_8000 |\
336 SNDRV_PCM_RATE_16000 |\
337 SNDRV_PCM_RATE_32000 |\
338 SNDRV_PCM_RATE_48000)
340 #define MTK_PCM_FORMATS (SNDRV_PCM_FMTBIT_S16_LE |\
341 SNDRV_PCM_FMTBIT_S24_LE |\
342 SNDRV_PCM_FMTBIT_S32_LE)
344 static struct snd_soc_dai_driver mtk_dai_pcm_driver
[] = {
347 .id
= MT8192_DAI_PCM_1
,
349 .stream_name
= "PCM 1 Playback",
352 .rates
= MTK_PCM_RATES
,
353 .formats
= MTK_PCM_FORMATS
,
356 .stream_name
= "PCM 1 Capture",
359 .rates
= MTK_PCM_RATES
,
360 .formats
= MTK_PCM_FORMATS
,
362 .ops
= &mtk_dai_pcm_ops
,
363 .symmetric_rates
= 1,
364 .symmetric_samplebits
= 1,
368 .id
= MT8192_DAI_PCM_2
,
370 .stream_name
= "PCM 2 Playback",
373 .rates
= MTK_PCM_RATES
,
374 .formats
= MTK_PCM_FORMATS
,
377 .stream_name
= "PCM 2 Capture",
380 .rates
= MTK_PCM_RATES
,
381 .formats
= MTK_PCM_FORMATS
,
383 .ops
= &mtk_dai_pcm_ops
,
384 .symmetric_rates
= 1,
385 .symmetric_samplebits
= 1,
389 int mt8192_dai_pcm_register(struct mtk_base_afe
*afe
)
391 struct mtk_base_afe_dai
*dai
;
393 dev_info(afe
->dev
, "%s()\n", __func__
);
395 dai
= devm_kzalloc(afe
->dev
, sizeof(*dai
), GFP_KERNEL
);
399 list_add(&dai
->list
, &afe
->sub_dais
);
401 dai
->dai_drivers
= mtk_dai_pcm_driver
;
402 dai
->num_dai_drivers
= ARRAY_SIZE(mtk_dai_pcm_driver
);
404 dai
->dapm_widgets
= mtk_dai_pcm_widgets
;
405 dai
->num_dapm_widgets
= ARRAY_SIZE(mtk_dai_pcm_widgets
);
406 dai
->dapm_routes
= mtk_dai_pcm_routes
;
407 dai
->num_dapm_routes
= ARRAY_SIZE(mtk_dai_pcm_routes
);