1*55cac93dSJiaxin Yu // SPDX-License-Identifier: GPL-2.0
2*55cac93dSJiaxin Yu //
3*55cac93dSJiaxin Yu // MediaTek ALSA SoC Audio DAI Hostless Control
4*55cac93dSJiaxin Yu //
5*55cac93dSJiaxin Yu // Copyright (c) 2022 MediaTek Inc.
6*55cac93dSJiaxin Yu // Author: Jiaxin Yu <jiaxin.yu@mediatek.com>
7*55cac93dSJiaxin Yu
8*55cac93dSJiaxin Yu #include "mt8186-afe-common.h"
9*55cac93dSJiaxin Yu
10*55cac93dSJiaxin Yu static const struct snd_pcm_hardware mt8186_hostless_hardware = {
11*55cac93dSJiaxin Yu .info = (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED |
12*55cac93dSJiaxin Yu SNDRV_PCM_INFO_MMAP_VALID),
13*55cac93dSJiaxin Yu .period_bytes_min = 256,
14*55cac93dSJiaxin Yu .period_bytes_max = 4 * 48 * 1024,
15*55cac93dSJiaxin Yu .periods_min = 2,
16*55cac93dSJiaxin Yu .periods_max = 256,
17*55cac93dSJiaxin Yu .buffer_bytes_max = 4 * 48 * 1024,
18*55cac93dSJiaxin Yu .fifo_size = 0,
19*55cac93dSJiaxin Yu };
20*55cac93dSJiaxin Yu
21*55cac93dSJiaxin Yu /* dai component */
22*55cac93dSJiaxin Yu static const struct snd_soc_dapm_route mtk_dai_hostless_routes[] = {
23*55cac93dSJiaxin Yu /* Hostless ADDA Loopback */
24*55cac93dSJiaxin Yu {"ADDA_DL_CH1", "ADDA_UL_CH1 Switch", "Hostless LPBK DL"},
25*55cac93dSJiaxin Yu {"ADDA_DL_CH1", "ADDA_UL_CH2 Switch", "Hostless LPBK DL"},
26*55cac93dSJiaxin Yu {"ADDA_DL_CH2", "ADDA_UL_CH1 Switch", "Hostless LPBK DL"},
27*55cac93dSJiaxin Yu {"ADDA_DL_CH2", "ADDA_UL_CH2 Switch", "Hostless LPBK DL"},
28*55cac93dSJiaxin Yu {"I2S1_CH1", "ADDA_UL_CH1 Switch", "Hostless LPBK DL"},
29*55cac93dSJiaxin Yu {"I2S1_CH2", "ADDA_UL_CH2 Switch", "Hostless LPBK DL"},
30*55cac93dSJiaxin Yu {"I2S3_CH1", "ADDA_UL_CH1 Switch", "Hostless LPBK DL"},
31*55cac93dSJiaxin Yu {"I2S3_CH1", "ADDA_UL_CH2 Switch", "Hostless LPBK DL"},
32*55cac93dSJiaxin Yu {"I2S3_CH2", "ADDA_UL_CH1 Switch", "Hostless LPBK DL"},
33*55cac93dSJiaxin Yu {"I2S3_CH2", "ADDA_UL_CH2 Switch", "Hostless LPBK DL"},
34*55cac93dSJiaxin Yu {"Hostless LPBK UL", NULL, "ADDA_UL_Mux"},
35*55cac93dSJiaxin Yu
36*55cac93dSJiaxin Yu /* Hostelss FM */
37*55cac93dSJiaxin Yu /* connsys_i2s to hw gain 1*/
38*55cac93dSJiaxin Yu {"Hostless FM UL", NULL, "Connsys I2S"},
39*55cac93dSJiaxin Yu
40*55cac93dSJiaxin Yu {"HW_GAIN1_IN_CH1", "CONNSYS_I2S_CH1 Switch", "Hostless FM DL"},
41*55cac93dSJiaxin Yu {"HW_GAIN1_IN_CH2", "CONNSYS_I2S_CH2 Switch", "Hostless FM DL"},
42*55cac93dSJiaxin Yu /* hw gain to adda dl */
43*55cac93dSJiaxin Yu {"Hostless FM UL", NULL, "HW Gain 1 Out"},
44*55cac93dSJiaxin Yu
45*55cac93dSJiaxin Yu {"ADDA_DL_CH1", "GAIN1_OUT_CH1 Switch", "Hostless FM DL"},
46*55cac93dSJiaxin Yu {"ADDA_DL_CH2", "GAIN1_OUT_CH2 Switch", "Hostless FM DL"},
47*55cac93dSJiaxin Yu /* hw gain to i2s3 */
48*55cac93dSJiaxin Yu {"I2S3_CH1", "GAIN1_OUT_CH1 Switch", "Hostless FM DL"},
49*55cac93dSJiaxin Yu {"I2S3_CH2", "GAIN1_OUT_CH2 Switch", "Hostless FM DL"},
50*55cac93dSJiaxin Yu /* hw gain to i2s1 */
51*55cac93dSJiaxin Yu {"I2S1_CH1", "GAIN1_OUT_CH1 Switch", "Hostless FM DL"},
52*55cac93dSJiaxin Yu {"I2S1_CH2", "GAIN1_OUT_CH2 Switch", "Hostless FM DL"},
53*55cac93dSJiaxin Yu
54*55cac93dSJiaxin Yu /* Hostless_SRC */
55*55cac93dSJiaxin Yu {"ADDA_DL_CH1", "SRC_1_OUT_CH1 Switch", "Hostless_SRC_1_DL"},
56*55cac93dSJiaxin Yu {"ADDA_DL_CH2", "SRC_1_OUT_CH2 Switch", "Hostless_SRC_1_DL"},
57*55cac93dSJiaxin Yu {"I2S1_CH1", "SRC_1_OUT_CH1 Switch", "Hostless_SRC_1_DL"},
58*55cac93dSJiaxin Yu {"I2S1_CH2", "SRC_1_OUT_CH2 Switch", "Hostless_SRC_1_DL"},
59*55cac93dSJiaxin Yu {"I2S3_CH1", "SRC_1_OUT_CH1 Switch", "Hostless_SRC_1_DL"},
60*55cac93dSJiaxin Yu {"I2S3_CH2", "SRC_1_OUT_CH2 Switch", "Hostless_SRC_1_DL"},
61*55cac93dSJiaxin Yu {"Hostless_SRC_1_UL", NULL, "HW_SRC_1_Out"},
62*55cac93dSJiaxin Yu
63*55cac93dSJiaxin Yu /* Hostless_SRC_bargein */
64*55cac93dSJiaxin Yu {"HW_SRC_1_IN_CH1", "I2S0_CH1 Switch", "Hostless_SRC_Bargein_DL"},
65*55cac93dSJiaxin Yu {"HW_SRC_1_IN_CH2", "I2S0_CH2 Switch", "Hostless_SRC_Bargein_DL"},
66*55cac93dSJiaxin Yu {"Hostless_SRC_Bargein_UL", NULL, "I2S0"},
67*55cac93dSJiaxin Yu
68*55cac93dSJiaxin Yu /* Hostless AAudio */
69*55cac93dSJiaxin Yu {"Hostless HW Gain AAudio In", NULL, "HW Gain 2 In"},
70*55cac93dSJiaxin Yu {"Hostless SRC AAudio UL", NULL, "HW Gain 2 Out"},
71*55cac93dSJiaxin Yu {"HW_SRC_2_IN_CH1", "HW_GAIN2_OUT_CH1 Switch", "Hostless SRC AAudio DL"},
72*55cac93dSJiaxin Yu {"HW_SRC_2_IN_CH2", "HW_GAIN2_OUT_CH2 Switch", "Hostless SRC AAudio DL"},
73*55cac93dSJiaxin Yu };
74*55cac93dSJiaxin Yu
75*55cac93dSJiaxin Yu /* dai ops */
mtk_dai_hostless_startup(struct snd_pcm_substream * substream,struct snd_soc_dai * dai)76*55cac93dSJiaxin Yu static int mtk_dai_hostless_startup(struct snd_pcm_substream *substream,
77*55cac93dSJiaxin Yu struct snd_soc_dai *dai)
78*55cac93dSJiaxin Yu {
79*55cac93dSJiaxin Yu struct mtk_base_afe *afe = snd_soc_dai_get_drvdata(dai);
80*55cac93dSJiaxin Yu struct snd_pcm_runtime *runtime = substream->runtime;
81*55cac93dSJiaxin Yu int ret;
82*55cac93dSJiaxin Yu
83*55cac93dSJiaxin Yu snd_soc_set_runtime_hwparams(substream, &mt8186_hostless_hardware);
84*55cac93dSJiaxin Yu
85*55cac93dSJiaxin Yu ret = snd_pcm_hw_constraint_integer(runtime,
86*55cac93dSJiaxin Yu SNDRV_PCM_HW_PARAM_PERIODS);
87*55cac93dSJiaxin Yu if (ret < 0) {
88*55cac93dSJiaxin Yu dev_err(afe->dev, "snd_pcm_hw_constraint_integer failed\n");
89*55cac93dSJiaxin Yu return ret;
90*55cac93dSJiaxin Yu }
91*55cac93dSJiaxin Yu
92*55cac93dSJiaxin Yu return 0;
93*55cac93dSJiaxin Yu }
94*55cac93dSJiaxin Yu
95*55cac93dSJiaxin Yu static const struct snd_soc_dai_ops mtk_dai_hostless_ops = {
96*55cac93dSJiaxin Yu .startup = mtk_dai_hostless_startup,
97*55cac93dSJiaxin Yu };
98*55cac93dSJiaxin Yu
99*55cac93dSJiaxin Yu /* dai driver */
100*55cac93dSJiaxin Yu #define MTK_HOSTLESS_RATES (SNDRV_PCM_RATE_8000_48000 |\
101*55cac93dSJiaxin Yu SNDRV_PCM_RATE_88200 |\
102*55cac93dSJiaxin Yu SNDRV_PCM_RATE_96000 |\
103*55cac93dSJiaxin Yu SNDRV_PCM_RATE_176400 |\
104*55cac93dSJiaxin Yu SNDRV_PCM_RATE_192000)
105*55cac93dSJiaxin Yu
106*55cac93dSJiaxin Yu #define MTK_HOSTLESS_FORMATS (SNDRV_PCM_FMTBIT_S16_LE |\
107*55cac93dSJiaxin Yu SNDRV_PCM_FMTBIT_S24_LE |\
108*55cac93dSJiaxin Yu SNDRV_PCM_FMTBIT_S32_LE)
109*55cac93dSJiaxin Yu
110*55cac93dSJiaxin Yu static struct snd_soc_dai_driver mtk_dai_hostless_driver[] = {
111*55cac93dSJiaxin Yu {
112*55cac93dSJiaxin Yu .name = "Hostless LPBK DAI",
113*55cac93dSJiaxin Yu .id = MT8186_DAI_HOSTLESS_LPBK,
114*55cac93dSJiaxin Yu .playback = {
115*55cac93dSJiaxin Yu .stream_name = "Hostless LPBK DL",
116*55cac93dSJiaxin Yu .channels_min = 1,
117*55cac93dSJiaxin Yu .channels_max = 2,
118*55cac93dSJiaxin Yu .rates = MTK_HOSTLESS_RATES,
119*55cac93dSJiaxin Yu .formats = MTK_HOSTLESS_FORMATS,
120*55cac93dSJiaxin Yu },
121*55cac93dSJiaxin Yu .capture = {
122*55cac93dSJiaxin Yu .stream_name = "Hostless LPBK UL",
123*55cac93dSJiaxin Yu .channels_min = 1,
124*55cac93dSJiaxin Yu .channels_max = 2,
125*55cac93dSJiaxin Yu .rates = MTK_HOSTLESS_RATES,
126*55cac93dSJiaxin Yu .formats = MTK_HOSTLESS_FORMATS,
127*55cac93dSJiaxin Yu },
128*55cac93dSJiaxin Yu .ops = &mtk_dai_hostless_ops,
129*55cac93dSJiaxin Yu },
130*55cac93dSJiaxin Yu {
131*55cac93dSJiaxin Yu .name = "Hostless FM DAI",
132*55cac93dSJiaxin Yu .id = MT8186_DAI_HOSTLESS_FM,
133*55cac93dSJiaxin Yu .playback = {
134*55cac93dSJiaxin Yu .stream_name = "Hostless FM DL",
135*55cac93dSJiaxin Yu .channels_min = 1,
136*55cac93dSJiaxin Yu .channels_max = 2,
137*55cac93dSJiaxin Yu .rates = MTK_HOSTLESS_RATES,
138*55cac93dSJiaxin Yu .formats = MTK_HOSTLESS_FORMATS,
139*55cac93dSJiaxin Yu },
140*55cac93dSJiaxin Yu .capture = {
141*55cac93dSJiaxin Yu .stream_name = "Hostless FM UL",
142*55cac93dSJiaxin Yu .channels_min = 1,
143*55cac93dSJiaxin Yu .channels_max = 2,
144*55cac93dSJiaxin Yu .rates = MTK_HOSTLESS_RATES,
145*55cac93dSJiaxin Yu .formats = MTK_HOSTLESS_FORMATS,
146*55cac93dSJiaxin Yu },
147*55cac93dSJiaxin Yu .ops = &mtk_dai_hostless_ops,
148*55cac93dSJiaxin Yu },
149*55cac93dSJiaxin Yu {
150*55cac93dSJiaxin Yu .name = "Hostless_SRC_1_DAI",
151*55cac93dSJiaxin Yu .id = MT8186_DAI_HOSTLESS_SRC_1,
152*55cac93dSJiaxin Yu .playback = {
153*55cac93dSJiaxin Yu .stream_name = "Hostless_SRC_1_DL",
154*55cac93dSJiaxin Yu .channels_min = 1,
155*55cac93dSJiaxin Yu .channels_max = 2,
156*55cac93dSJiaxin Yu .rates = MTK_HOSTLESS_RATES,
157*55cac93dSJiaxin Yu .formats = MTK_HOSTLESS_FORMATS,
158*55cac93dSJiaxin Yu },
159*55cac93dSJiaxin Yu .capture = {
160*55cac93dSJiaxin Yu .stream_name = "Hostless_SRC_1_UL",
161*55cac93dSJiaxin Yu .channels_min = 1,
162*55cac93dSJiaxin Yu .channels_max = 2,
163*55cac93dSJiaxin Yu .rates = MTK_HOSTLESS_RATES,
164*55cac93dSJiaxin Yu .formats = MTK_HOSTLESS_FORMATS,
165*55cac93dSJiaxin Yu },
166*55cac93dSJiaxin Yu .ops = &mtk_dai_hostless_ops,
167*55cac93dSJiaxin Yu },
168*55cac93dSJiaxin Yu {
169*55cac93dSJiaxin Yu .name = "Hostless_SRC_Bargein_DAI",
170*55cac93dSJiaxin Yu .id = MT8186_DAI_HOSTLESS_SRC_BARGEIN,
171*55cac93dSJiaxin Yu .playback = {
172*55cac93dSJiaxin Yu .stream_name = "Hostless_SRC_Bargein_DL",
173*55cac93dSJiaxin Yu .channels_min = 1,
174*55cac93dSJiaxin Yu .channels_max = 2,
175*55cac93dSJiaxin Yu .rates = MTK_HOSTLESS_RATES,
176*55cac93dSJiaxin Yu .formats = MTK_HOSTLESS_FORMATS,
177*55cac93dSJiaxin Yu },
178*55cac93dSJiaxin Yu .capture = {
179*55cac93dSJiaxin Yu .stream_name = "Hostless_SRC_Bargein_UL",
180*55cac93dSJiaxin Yu .channels_min = 1,
181*55cac93dSJiaxin Yu .channels_max = 2,
182*55cac93dSJiaxin Yu .rates = MTK_HOSTLESS_RATES,
183*55cac93dSJiaxin Yu .formats = MTK_HOSTLESS_FORMATS,
184*55cac93dSJiaxin Yu },
185*55cac93dSJiaxin Yu .ops = &mtk_dai_hostless_ops,
186*55cac93dSJiaxin Yu },
187*55cac93dSJiaxin Yu /* BE dai */
188*55cac93dSJiaxin Yu {
189*55cac93dSJiaxin Yu .name = "Hostless_UL1 DAI",
190*55cac93dSJiaxin Yu .id = MT8186_DAI_HOSTLESS_UL1,
191*55cac93dSJiaxin Yu .capture = {
192*55cac93dSJiaxin Yu .stream_name = "Hostless_UL1 UL",
193*55cac93dSJiaxin Yu .channels_min = 1,
194*55cac93dSJiaxin Yu .channels_max = 4,
195*55cac93dSJiaxin Yu .rates = MTK_HOSTLESS_RATES,
196*55cac93dSJiaxin Yu .formats = MTK_HOSTLESS_FORMATS,
197*55cac93dSJiaxin Yu },
198*55cac93dSJiaxin Yu .ops = &mtk_dai_hostless_ops,
199*55cac93dSJiaxin Yu },
200*55cac93dSJiaxin Yu {
201*55cac93dSJiaxin Yu .name = "Hostless_UL2 DAI",
202*55cac93dSJiaxin Yu .id = MT8186_DAI_HOSTLESS_UL2,
203*55cac93dSJiaxin Yu .capture = {
204*55cac93dSJiaxin Yu .stream_name = "Hostless_UL2 UL",
205*55cac93dSJiaxin Yu .channels_min = 1,
206*55cac93dSJiaxin Yu .channels_max = 4,
207*55cac93dSJiaxin Yu .rates = MTK_HOSTLESS_RATES,
208*55cac93dSJiaxin Yu .formats = MTK_HOSTLESS_FORMATS,
209*55cac93dSJiaxin Yu },
210*55cac93dSJiaxin Yu .ops = &mtk_dai_hostless_ops,
211*55cac93dSJiaxin Yu },
212*55cac93dSJiaxin Yu {
213*55cac93dSJiaxin Yu .name = "Hostless_UL3 DAI",
214*55cac93dSJiaxin Yu .id = MT8186_DAI_HOSTLESS_UL3,
215*55cac93dSJiaxin Yu .capture = {
216*55cac93dSJiaxin Yu .stream_name = "Hostless_UL3 UL",
217*55cac93dSJiaxin Yu .channels_min = 1,
218*55cac93dSJiaxin Yu .channels_max = 2,
219*55cac93dSJiaxin Yu .rates = MTK_HOSTLESS_RATES,
220*55cac93dSJiaxin Yu .formats = MTK_HOSTLESS_FORMATS,
221*55cac93dSJiaxin Yu },
222*55cac93dSJiaxin Yu .ops = &mtk_dai_hostless_ops,
223*55cac93dSJiaxin Yu },
224*55cac93dSJiaxin Yu {
225*55cac93dSJiaxin Yu .name = "Hostless_UL5 DAI",
226*55cac93dSJiaxin Yu .id = MT8186_DAI_HOSTLESS_UL5,
227*55cac93dSJiaxin Yu .capture = {
228*55cac93dSJiaxin Yu .stream_name = "Hostless_UL5 UL",
229*55cac93dSJiaxin Yu .channels_min = 1,
230*55cac93dSJiaxin Yu .channels_max = 12,
231*55cac93dSJiaxin Yu .rates = MTK_HOSTLESS_RATES,
232*55cac93dSJiaxin Yu .formats = MTK_HOSTLESS_FORMATS,
233*55cac93dSJiaxin Yu },
234*55cac93dSJiaxin Yu .ops = &mtk_dai_hostless_ops,
235*55cac93dSJiaxin Yu },
236*55cac93dSJiaxin Yu {
237*55cac93dSJiaxin Yu .name = "Hostless_UL6 DAI",
238*55cac93dSJiaxin Yu .id = MT8186_DAI_HOSTLESS_UL6,
239*55cac93dSJiaxin Yu .capture = {
240*55cac93dSJiaxin Yu .stream_name = "Hostless_UL6 UL",
241*55cac93dSJiaxin Yu .channels_min = 1,
242*55cac93dSJiaxin Yu .channels_max = 2,
243*55cac93dSJiaxin Yu .rates = MTK_HOSTLESS_RATES,
244*55cac93dSJiaxin Yu .formats = MTK_HOSTLESS_FORMATS,
245*55cac93dSJiaxin Yu },
246*55cac93dSJiaxin Yu .ops = &mtk_dai_hostless_ops,
247*55cac93dSJiaxin Yu },
248*55cac93dSJiaxin Yu {
249*55cac93dSJiaxin Yu .name = "Hostless HW Gain AAudio DAI",
250*55cac93dSJiaxin Yu .id = MT8186_DAI_HOSTLESS_HW_GAIN_AAUDIO,
251*55cac93dSJiaxin Yu .capture = {
252*55cac93dSJiaxin Yu .stream_name = "Hostless HW Gain AAudio In",
253*55cac93dSJiaxin Yu .channels_min = 1,
254*55cac93dSJiaxin Yu .channels_max = 2,
255*55cac93dSJiaxin Yu .rates = MTK_HOSTLESS_RATES,
256*55cac93dSJiaxin Yu .formats = MTK_HOSTLESS_FORMATS,
257*55cac93dSJiaxin Yu },
258*55cac93dSJiaxin Yu .ops = &mtk_dai_hostless_ops,
259*55cac93dSJiaxin Yu },
260*55cac93dSJiaxin Yu {
261*55cac93dSJiaxin Yu .name = "Hostless SRC AAudio DAI",
262*55cac93dSJiaxin Yu .id = MT8186_DAI_HOSTLESS_SRC_AAUDIO,
263*55cac93dSJiaxin Yu .playback = {
264*55cac93dSJiaxin Yu .stream_name = "Hostless SRC AAudio DL",
265*55cac93dSJiaxin Yu .channels_min = 1,
266*55cac93dSJiaxin Yu .channels_max = 2,
267*55cac93dSJiaxin Yu .rates = MTK_HOSTLESS_RATES,
268*55cac93dSJiaxin Yu .formats = MTK_HOSTLESS_FORMATS,
269*55cac93dSJiaxin Yu },
270*55cac93dSJiaxin Yu .capture = {
271*55cac93dSJiaxin Yu .stream_name = "Hostless SRC AAudio UL",
272*55cac93dSJiaxin Yu .channels_min = 1,
273*55cac93dSJiaxin Yu .channels_max = 2,
274*55cac93dSJiaxin Yu .rates = MTK_HOSTLESS_RATES,
275*55cac93dSJiaxin Yu .formats = MTK_HOSTLESS_FORMATS,
276*55cac93dSJiaxin Yu },
277*55cac93dSJiaxin Yu .ops = &mtk_dai_hostless_ops,
278*55cac93dSJiaxin Yu },
279*55cac93dSJiaxin Yu };
280*55cac93dSJiaxin Yu
mt8186_dai_hostless_register(struct mtk_base_afe * afe)281*55cac93dSJiaxin Yu int mt8186_dai_hostless_register(struct mtk_base_afe *afe)
282*55cac93dSJiaxin Yu {
283*55cac93dSJiaxin Yu struct mtk_base_afe_dai *dai;
284*55cac93dSJiaxin Yu
285*55cac93dSJiaxin Yu dai = devm_kzalloc(afe->dev, sizeof(*dai), GFP_KERNEL);
286*55cac93dSJiaxin Yu if (!dai)
287*55cac93dSJiaxin Yu return -ENOMEM;
288*55cac93dSJiaxin Yu
289*55cac93dSJiaxin Yu list_add(&dai->list, &afe->sub_dais);
290*55cac93dSJiaxin Yu
291*55cac93dSJiaxin Yu dai->dai_drivers = mtk_dai_hostless_driver;
292*55cac93dSJiaxin Yu dai->num_dai_drivers = ARRAY_SIZE(mtk_dai_hostless_driver);
293*55cac93dSJiaxin Yu
294*55cac93dSJiaxin Yu dai->dapm_routes = mtk_dai_hostless_routes;
295*55cac93dSJiaxin Yu dai->num_dapm_routes = ARRAY_SIZE(mtk_dai_hostless_routes);
296*55cac93dSJiaxin Yu
297*55cac93dSJiaxin Yu return 0;
298*55cac93dSJiaxin Yu }
299