]>
Commit | Line | Data |
---|---|---|
1 | /* | |
2 | * Mediatek ALSA SoC AFE platform driver for 2701 | |
3 | * | |
4 | * Copyright (c) 2016 MediaTek Inc. | |
5 | * Author: Garlic Tseng <garlic.tseng@mediatek.com> | |
6 | * Ir Lian <ir.lian@mediatek.com> | |
7 | * | |
8 | * This program is free software; you can redistribute it and/or modify | |
9 | * it under the terms of the GNU General Public License version 2 and | |
10 | * only version 2 as published by the Free Software Foundation. | |
11 | * | |
12 | * This program is distributed in the hope that it will be useful, | |
13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
15 | * GNU General Public License for more details. | |
16 | */ | |
17 | ||
18 | #include <linux/delay.h> | |
19 | #include <linux/module.h> | |
20 | #include <linux/of.h> | |
21 | #include <linux/of_address.h> | |
22 | #include <linux/pm_runtime.h> | |
23 | #include <sound/soc.h> | |
24 | ||
25 | #include "mt2701-afe-common.h" | |
26 | ||
27 | #include "mt2701-afe-clock-ctrl.h" | |
28 | #include "../common/mtk-afe-platform-driver.h" | |
29 | #include "../common/mtk-afe-fe-dai.h" | |
30 | ||
31 | #define AFE_IRQ_STATUS_BITS 0xff | |
32 | ||
33 | static const struct snd_pcm_hardware mt2701_afe_hardware = { | |
34 | .info = SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED | |
35 | | SNDRV_PCM_INFO_RESUME | SNDRV_PCM_INFO_MMAP_VALID, | |
36 | .formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_LE | |
37 | | SNDRV_PCM_FMTBIT_S32_LE, | |
38 | .period_bytes_min = 1024, | |
39 | .period_bytes_max = 1024 * 256, | |
40 | .periods_min = 4, | |
41 | .periods_max = 1024, | |
42 | .buffer_bytes_max = 1024 * 1024 * 16, | |
43 | .fifo_size = 0, | |
44 | }; | |
45 | ||
46 | struct mt2701_afe_rate { | |
47 | unsigned int rate; | |
48 | unsigned int regvalue; | |
49 | }; | |
50 | ||
51 | static const struct mt2701_afe_rate mt2701_afe_i2s_rates[] = { | |
52 | { .rate = 8000, .regvalue = 0 }, | |
53 | { .rate = 12000, .regvalue = 1 }, | |
54 | { .rate = 16000, .regvalue = 2 }, | |
55 | { .rate = 24000, .regvalue = 3 }, | |
56 | { .rate = 32000, .regvalue = 4 }, | |
57 | { .rate = 48000, .regvalue = 5 }, | |
58 | { .rate = 96000, .regvalue = 6 }, | |
59 | { .rate = 192000, .regvalue = 7 }, | |
60 | { .rate = 384000, .regvalue = 8 }, | |
61 | { .rate = 7350, .regvalue = 16 }, | |
62 | { .rate = 11025, .regvalue = 17 }, | |
63 | { .rate = 14700, .regvalue = 18 }, | |
64 | { .rate = 22050, .regvalue = 19 }, | |
65 | { .rate = 29400, .regvalue = 20 }, | |
66 | { .rate = 44100, .regvalue = 21 }, | |
67 | { .rate = 88200, .regvalue = 22 }, | |
68 | { .rate = 176400, .regvalue = 23 }, | |
69 | { .rate = 352800, .regvalue = 24 }, | |
70 | }; | |
71 | ||
72 | static int mt2701_dai_num_to_i2s(struct mtk_base_afe *afe, int num) | |
73 | { | |
74 | int val = num - MT2701_IO_I2S; | |
75 | ||
76 | if (val < 0 || val >= MT2701_I2S_NUM) { | |
77 | dev_err(afe->dev, "%s, num not available, num %d, val %d\n", | |
78 | __func__, num, val); | |
79 | return -EINVAL; | |
80 | } | |
81 | return val; | |
82 | } | |
83 | ||
84 | static int mt2701_afe_i2s_fs(unsigned int sample_rate) | |
85 | { | |
86 | int i; | |
87 | ||
88 | for (i = 0; i < ARRAY_SIZE(mt2701_afe_i2s_rates); i++) | |
89 | if (mt2701_afe_i2s_rates[i].rate == sample_rate) | |
90 | return mt2701_afe_i2s_rates[i].regvalue; | |
91 | ||
92 | return -EINVAL; | |
93 | } | |
94 | ||
95 | static int mt2701_afe_i2s_startup(struct snd_pcm_substream *substream, | |
96 | struct snd_soc_dai *dai) | |
97 | { | |
98 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | |
99 | struct mtk_base_afe *afe = snd_soc_platform_get_drvdata(rtd->platform); | |
100 | struct mt2701_afe_private *afe_priv = afe->platform_priv; | |
101 | int i2s_num = mt2701_dai_num_to_i2s(afe, dai->id); | |
102 | int clk_num = MT2701_AUD_AUD_I2S1_MCLK + i2s_num; | |
103 | int ret = 0; | |
104 | ||
105 | if (i2s_num < 0) | |
106 | return i2s_num; | |
107 | ||
108 | /* enable mclk */ | |
109 | ret = clk_prepare_enable(afe_priv->clocks[clk_num]); | |
110 | if (ret) | |
111 | dev_err(afe->dev, "Failed to enable mclk for I2S: %d\n", | |
112 | i2s_num); | |
113 | ||
114 | return ret; | |
115 | } | |
116 | ||
117 | static int mt2701_afe_i2s_path_shutdown(struct snd_pcm_substream *substream, | |
118 | struct snd_soc_dai *dai, | |
119 | int dir_invert) | |
120 | { | |
121 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | |
122 | struct mtk_base_afe *afe = snd_soc_platform_get_drvdata(rtd->platform); | |
123 | struct mt2701_afe_private *afe_priv = afe->platform_priv; | |
124 | int i2s_num = mt2701_dai_num_to_i2s(afe, dai->id); | |
125 | struct mt2701_i2s_path *i2s_path; | |
126 | const struct mt2701_i2s_data *i2s_data; | |
127 | int stream_dir = substream->stream; | |
128 | ||
129 | if (i2s_num < 0) | |
130 | return i2s_num; | |
131 | ||
132 | i2s_path = &afe_priv->i2s_path[i2s_num]; | |
133 | ||
134 | if (dir_invert) { | |
135 | if (stream_dir == SNDRV_PCM_STREAM_PLAYBACK) | |
136 | stream_dir = SNDRV_PCM_STREAM_CAPTURE; | |
137 | else | |
138 | stream_dir = SNDRV_PCM_STREAM_PLAYBACK; | |
139 | } | |
140 | i2s_data = i2s_path->i2s_data[stream_dir]; | |
141 | ||
142 | i2s_path->on[stream_dir]--; | |
143 | if (i2s_path->on[stream_dir] < 0) { | |
144 | dev_warn(afe->dev, "i2s_path->on: %d, dir: %d\n", | |
145 | i2s_path->on[stream_dir], stream_dir); | |
146 | i2s_path->on[stream_dir] = 0; | |
147 | } | |
148 | if (i2s_path->on[stream_dir]) | |
149 | return 0; | |
150 | ||
151 | /* disable i2s */ | |
152 | regmap_update_bits(afe->regmap, i2s_data->i2s_ctrl_reg, | |
153 | ASYS_I2S_CON_I2S_EN, 0); | |
154 | regmap_update_bits(afe->regmap, AUDIO_TOP_CON4, | |
155 | 1 << i2s_data->i2s_pwn_shift, | |
156 | 1 << i2s_data->i2s_pwn_shift); | |
157 | return 0; | |
158 | } | |
159 | ||
160 | static void mt2701_afe_i2s_shutdown(struct snd_pcm_substream *substream, | |
161 | struct snd_soc_dai *dai) | |
162 | { | |
163 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | |
164 | struct mtk_base_afe *afe = snd_soc_platform_get_drvdata(rtd->platform); | |
165 | struct mt2701_afe_private *afe_priv = afe->platform_priv; | |
166 | int i2s_num = mt2701_dai_num_to_i2s(afe, dai->id); | |
167 | struct mt2701_i2s_path *i2s_path; | |
168 | int clk_num = MT2701_AUD_AUD_I2S1_MCLK + i2s_num; | |
169 | ||
170 | if (i2s_num < 0) | |
171 | return; | |
172 | ||
173 | i2s_path = &afe_priv->i2s_path[i2s_num]; | |
174 | ||
175 | if (i2s_path->occupied[substream->stream]) | |
176 | i2s_path->occupied[substream->stream] = 0; | |
177 | else | |
178 | goto I2S_UNSTART; | |
179 | ||
180 | mt2701_afe_i2s_path_shutdown(substream, dai, 0); | |
181 | ||
182 | /* need to disable i2s-out path when disable i2s-in */ | |
183 | if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) | |
184 | mt2701_afe_i2s_path_shutdown(substream, dai, 1); | |
185 | ||
186 | I2S_UNSTART: | |
187 | /* disable mclk */ | |
188 | clk_disable_unprepare(afe_priv->clocks[clk_num]); | |
189 | } | |
190 | ||
191 | static int mt2701_i2s_path_prepare_enable(struct snd_pcm_substream *substream, | |
192 | struct snd_soc_dai *dai, | |
193 | int dir_invert) | |
194 | { | |
195 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | |
196 | struct mtk_base_afe *afe = snd_soc_platform_get_drvdata(rtd->platform); | |
197 | struct mt2701_afe_private *afe_priv = afe->platform_priv; | |
198 | int i2s_num = mt2701_dai_num_to_i2s(afe, dai->id); | |
199 | struct mt2701_i2s_path *i2s_path; | |
200 | const struct mt2701_i2s_data *i2s_data; | |
201 | struct snd_pcm_runtime * const runtime = substream->runtime; | |
202 | int reg, fs, w_len = 1; /* now we support bck 64bits only */ | |
203 | int stream_dir = substream->stream; | |
204 | unsigned int mask = 0, val = 0; | |
205 | ||
206 | if (i2s_num < 0) | |
207 | return i2s_num; | |
208 | ||
209 | i2s_path = &afe_priv->i2s_path[i2s_num]; | |
210 | ||
211 | if (dir_invert) { | |
212 | if (stream_dir == SNDRV_PCM_STREAM_PLAYBACK) | |
213 | stream_dir = SNDRV_PCM_STREAM_CAPTURE; | |
214 | else | |
215 | stream_dir = SNDRV_PCM_STREAM_PLAYBACK; | |
216 | } | |
217 | i2s_data = i2s_path->i2s_data[stream_dir]; | |
218 | ||
219 | /* no need to enable if already done */ | |
220 | i2s_path->on[stream_dir]++; | |
221 | ||
222 | if (i2s_path->on[stream_dir] != 1) | |
223 | return 0; | |
224 | ||
225 | fs = mt2701_afe_i2s_fs(runtime->rate); | |
226 | ||
227 | mask = ASYS_I2S_CON_FS | | |
228 | ASYS_I2S_CON_I2S_COUPLE_MODE | /* 0 */ | |
229 | ASYS_I2S_CON_I2S_MODE | | |
230 | ASYS_I2S_CON_WIDE_MODE; | |
231 | ||
232 | val = ASYS_I2S_CON_FS_SET(fs) | | |
233 | ASYS_I2S_CON_I2S_MODE | | |
234 | ASYS_I2S_CON_WIDE_MODE_SET(w_len); | |
235 | ||
236 | if (stream_dir == SNDRV_PCM_STREAM_CAPTURE) { | |
237 | mask |= ASYS_I2S_IN_PHASE_FIX; | |
238 | val |= ASYS_I2S_IN_PHASE_FIX; | |
239 | } | |
240 | ||
241 | regmap_update_bits(afe->regmap, i2s_data->i2s_ctrl_reg, mask, val); | |
242 | ||
243 | if (stream_dir == SNDRV_PCM_STREAM_PLAYBACK) | |
244 | reg = ASMO_TIMING_CON1; | |
245 | else | |
246 | reg = ASMI_TIMING_CON1; | |
247 | ||
248 | regmap_update_bits(afe->regmap, reg, | |
249 | i2s_data->i2s_asrc_fs_mask | |
250 | << i2s_data->i2s_asrc_fs_shift, | |
251 | fs << i2s_data->i2s_asrc_fs_shift); | |
252 | ||
253 | /* enable i2s */ | |
254 | regmap_update_bits(afe->regmap, AUDIO_TOP_CON4, | |
255 | 1 << i2s_data->i2s_pwn_shift, | |
256 | 0 << i2s_data->i2s_pwn_shift); | |
257 | ||
258 | /* reset i2s hw status before enable */ | |
259 | regmap_update_bits(afe->regmap, i2s_data->i2s_ctrl_reg, | |
260 | ASYS_I2S_CON_RESET, ASYS_I2S_CON_RESET); | |
261 | udelay(1); | |
262 | regmap_update_bits(afe->regmap, i2s_data->i2s_ctrl_reg, | |
263 | ASYS_I2S_CON_RESET, 0); | |
264 | udelay(1); | |
265 | regmap_update_bits(afe->regmap, i2s_data->i2s_ctrl_reg, | |
266 | ASYS_I2S_CON_I2S_EN, ASYS_I2S_CON_I2S_EN); | |
267 | return 0; | |
268 | } | |
269 | ||
270 | static int mt2701_afe_i2s_prepare(struct snd_pcm_substream *substream, | |
271 | struct snd_soc_dai *dai) | |
272 | { | |
273 | int clk_domain; | |
274 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | |
275 | struct mtk_base_afe *afe = snd_soc_platform_get_drvdata(rtd->platform); | |
276 | struct mt2701_afe_private *afe_priv = afe->platform_priv; | |
277 | int i2s_num = mt2701_dai_num_to_i2s(afe, dai->id); | |
278 | struct mt2701_i2s_path *i2s_path; | |
279 | int mclk_rate; | |
280 | ||
281 | if (i2s_num < 0) | |
282 | return i2s_num; | |
283 | ||
284 | i2s_path = &afe_priv->i2s_path[i2s_num]; | |
285 | mclk_rate = i2s_path->mclk_rate; | |
286 | ||
287 | if (i2s_path->occupied[substream->stream]) | |
288 | return -EBUSY; | |
289 | i2s_path->occupied[substream->stream] = 1; | |
290 | ||
291 | if (MT2701_PLL_DOMAIN_0_RATE % mclk_rate == 0) { | |
292 | clk_domain = 0; | |
293 | } else if (MT2701_PLL_DOMAIN_1_RATE % mclk_rate == 0) { | |
294 | clk_domain = 1; | |
295 | } else { | |
296 | dev_err(dai->dev, "%s() bad mclk rate %d\n", | |
297 | __func__, mclk_rate); | |
298 | return -EINVAL; | |
299 | } | |
300 | mt2701_mclk_configuration(afe, i2s_num, clk_domain, mclk_rate); | |
301 | ||
302 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { | |
303 | mt2701_i2s_path_prepare_enable(substream, dai, 0); | |
304 | } else { | |
305 | /* need to enable i2s-out path when enable i2s-in */ | |
306 | /* prepare for another direction "out" */ | |
307 | mt2701_i2s_path_prepare_enable(substream, dai, 1); | |
308 | /* prepare for "in" */ | |
309 | mt2701_i2s_path_prepare_enable(substream, dai, 0); | |
310 | } | |
311 | ||
312 | return 0; | |
313 | } | |
314 | ||
315 | static int mt2701_afe_i2s_set_sysclk(struct snd_soc_dai *dai, int clk_id, | |
316 | unsigned int freq, int dir) | |
317 | { | |
318 | struct mtk_base_afe *afe = dev_get_drvdata(dai->dev); | |
319 | struct mt2701_afe_private *afe_priv = afe->platform_priv; | |
320 | int i2s_num = mt2701_dai_num_to_i2s(afe, dai->id); | |
321 | ||
322 | if (i2s_num < 0) | |
323 | return i2s_num; | |
324 | ||
325 | /* mclk */ | |
326 | if (dir == SND_SOC_CLOCK_IN) { | |
327 | dev_warn(dai->dev, | |
328 | "%s() warning: mt2701 doesn't support mclk input\n", | |
329 | __func__); | |
330 | return -EINVAL; | |
331 | } | |
332 | afe_priv->i2s_path[i2s_num].mclk_rate = freq; | |
333 | return 0; | |
334 | } | |
335 | ||
336 | static int mt2701_btmrg_startup(struct snd_pcm_substream *substream, | |
337 | struct snd_soc_dai *dai) | |
338 | { | |
339 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | |
340 | struct mtk_base_afe *afe = snd_soc_platform_get_drvdata(rtd->platform); | |
341 | struct mt2701_afe_private *afe_priv = afe->platform_priv; | |
342 | ||
343 | regmap_update_bits(afe->regmap, AUDIO_TOP_CON4, | |
344 | AUDIO_TOP_CON4_PDN_MRGIF, 0); | |
345 | ||
346 | afe_priv->mrg_enable[substream->stream] = 1; | |
347 | return 0; | |
348 | } | |
349 | ||
350 | static int mt2701_btmrg_hw_params(struct snd_pcm_substream *substream, | |
351 | struct snd_pcm_hw_params *params, | |
352 | struct snd_soc_dai *dai) | |
353 | { | |
354 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | |
355 | struct mtk_base_afe *afe = snd_soc_platform_get_drvdata(rtd->platform); | |
356 | int stream_fs; | |
357 | u32 val, msk; | |
358 | ||
359 | stream_fs = params_rate(params); | |
360 | ||
361 | if ((stream_fs != 8000) && (stream_fs != 16000)) { | |
362 | dev_err(afe->dev, "%s() btmgr not supprt this stream_fs %d\n", | |
363 | __func__, stream_fs); | |
364 | return -EINVAL; | |
365 | } | |
366 | ||
367 | regmap_update_bits(afe->regmap, AFE_MRGIF_CON, | |
368 | AFE_MRGIF_CON_I2S_MODE_MASK, | |
369 | AFE_MRGIF_CON_I2S_MODE_32K); | |
370 | ||
371 | val = AFE_DAIBT_CON0_BT_FUNC_EN | AFE_DAIBT_CON0_BT_FUNC_RDY | |
372 | | AFE_DAIBT_CON0_MRG_USE; | |
373 | msk = val; | |
374 | ||
375 | if (stream_fs == 16000) | |
376 | val |= AFE_DAIBT_CON0_BT_WIDE_MODE_EN; | |
377 | ||
378 | msk |= AFE_DAIBT_CON0_BT_WIDE_MODE_EN; | |
379 | ||
380 | regmap_update_bits(afe->regmap, AFE_DAIBT_CON0, msk, val); | |
381 | ||
382 | regmap_update_bits(afe->regmap, AFE_DAIBT_CON0, | |
383 | AFE_DAIBT_CON0_DAIBT_EN, | |
384 | AFE_DAIBT_CON0_DAIBT_EN); | |
385 | regmap_update_bits(afe->regmap, AFE_MRGIF_CON, | |
386 | AFE_MRGIF_CON_MRG_I2S_EN, | |
387 | AFE_MRGIF_CON_MRG_I2S_EN); | |
388 | regmap_update_bits(afe->regmap, AFE_MRGIF_CON, | |
389 | AFE_MRGIF_CON_MRG_EN, | |
390 | AFE_MRGIF_CON_MRG_EN); | |
391 | return 0; | |
392 | } | |
393 | ||
394 | static void mt2701_btmrg_shutdown(struct snd_pcm_substream *substream, | |
395 | struct snd_soc_dai *dai) | |
396 | { | |
397 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | |
398 | struct mtk_base_afe *afe = snd_soc_platform_get_drvdata(rtd->platform); | |
399 | struct mt2701_afe_private *afe_priv = afe->platform_priv; | |
400 | ||
401 | /* if the other direction stream is not occupied */ | |
402 | if (!afe_priv->mrg_enable[!substream->stream]) { | |
403 | regmap_update_bits(afe->regmap, AFE_DAIBT_CON0, | |
404 | AFE_DAIBT_CON0_DAIBT_EN, 0); | |
405 | regmap_update_bits(afe->regmap, AFE_MRGIF_CON, | |
406 | AFE_MRGIF_CON_MRG_EN, 0); | |
407 | regmap_update_bits(afe->regmap, AFE_MRGIF_CON, | |
408 | AFE_MRGIF_CON_MRG_I2S_EN, 0); | |
409 | regmap_update_bits(afe->regmap, AUDIO_TOP_CON4, | |
410 | AUDIO_TOP_CON4_PDN_MRGIF, | |
411 | AUDIO_TOP_CON4_PDN_MRGIF); | |
412 | } | |
413 | afe_priv->mrg_enable[substream->stream] = 0; | |
414 | } | |
415 | ||
416 | static int mt2701_simple_fe_startup(struct snd_pcm_substream *substream, | |
417 | struct snd_soc_dai *dai) | |
418 | { | |
419 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | |
420 | struct mtk_base_afe *afe = snd_soc_platform_get_drvdata(rtd->platform); | |
421 | int stream_dir = substream->stream; | |
422 | int memif_num = rtd->cpu_dai->id; | |
423 | struct mtk_base_afe_memif *memif_tmp; | |
424 | ||
425 | /* can't run single DL & DLM at the same time */ | |
426 | if (stream_dir == SNDRV_PCM_STREAM_PLAYBACK) { | |
427 | memif_tmp = &afe->memif[MT2701_MEMIF_DLM]; | |
428 | if (memif_tmp->substream) { | |
429 | dev_warn(afe->dev, "%s memif is not available, stream_dir %d, memif_num %d\n", | |
430 | __func__, stream_dir, memif_num); | |
431 | return -EBUSY; | |
432 | } | |
433 | } | |
434 | return mtk_afe_fe_startup(substream, dai); | |
435 | } | |
436 | ||
437 | static int mt2701_simple_fe_hw_params(struct snd_pcm_substream *substream, | |
438 | struct snd_pcm_hw_params *params, | |
439 | struct snd_soc_dai *dai) | |
440 | { | |
441 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | |
442 | struct mtk_base_afe *afe = snd_soc_platform_get_drvdata(rtd->platform); | |
443 | int stream_dir = substream->stream; | |
444 | ||
445 | /* single DL use PAIR_INTERLEAVE */ | |
446 | if (stream_dir == SNDRV_PCM_STREAM_PLAYBACK) { | |
447 | regmap_update_bits(afe->regmap, | |
448 | AFE_MEMIF_PBUF_SIZE, | |
449 | AFE_MEMIF_PBUF_SIZE_DLM_MASK, | |
450 | AFE_MEMIF_PBUF_SIZE_PAIR_INTERLEAVE); | |
451 | } | |
452 | return mtk_afe_fe_hw_params(substream, params, dai); | |
453 | } | |
454 | ||
455 | static int mt2701_dlm_fe_startup(struct snd_pcm_substream *substream, | |
456 | struct snd_soc_dai *dai) | |
457 | { | |
458 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | |
459 | struct mtk_base_afe *afe = snd_soc_platform_get_drvdata(rtd->platform); | |
460 | struct mtk_base_afe_memif *memif_tmp; | |
461 | const struct mtk_base_memif_data *memif_data; | |
462 | int i; | |
463 | ||
464 | for (i = MT2701_MEMIF_DL1; i < MT2701_MEMIF_DL_SINGLE_NUM; ++i) { | |
465 | memif_tmp = &afe->memif[i]; | |
466 | if (memif_tmp->substream) | |
467 | return -EBUSY; | |
468 | } | |
469 | ||
470 | /* enable agent for all signal DL (due to hw design) */ | |
471 | for (i = MT2701_MEMIF_DL1; i < MT2701_MEMIF_DL_SINGLE_NUM; ++i) { | |
472 | memif_data = afe->memif[i].data; | |
473 | regmap_update_bits(afe->regmap, | |
474 | memif_data->agent_disable_reg, | |
475 | 1 << memif_data->agent_disable_shift, | |
476 | 0 << memif_data->agent_disable_shift); | |
477 | } | |
478 | ||
479 | return mtk_afe_fe_startup(substream, dai); | |
480 | } | |
481 | ||
482 | static void mt2701_dlm_fe_shutdown(struct snd_pcm_substream *substream, | |
483 | struct snd_soc_dai *dai) | |
484 | { | |
485 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | |
486 | struct mtk_base_afe *afe = snd_soc_platform_get_drvdata(rtd->platform); | |
487 | const struct mtk_base_memif_data *memif_data; | |
488 | int i; | |
489 | ||
490 | for (i = MT2701_MEMIF_DL1; i < MT2701_MEMIF_DL_SINGLE_NUM; ++i) { | |
491 | memif_data = afe->memif[i].data; | |
492 | regmap_update_bits(afe->regmap, | |
493 | memif_data->agent_disable_reg, | |
494 | 1 << memif_data->agent_disable_shift, | |
495 | 1 << memif_data->agent_disable_shift); | |
496 | } | |
497 | return mtk_afe_fe_shutdown(substream, dai); | |
498 | } | |
499 | ||
500 | static int mt2701_dlm_fe_hw_params(struct snd_pcm_substream *substream, | |
501 | struct snd_pcm_hw_params *params, | |
502 | struct snd_soc_dai *dai) | |
503 | { | |
504 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | |
505 | struct mtk_base_afe *afe = snd_soc_platform_get_drvdata(rtd->platform); | |
506 | int channels = params_channels(params); | |
507 | ||
508 | regmap_update_bits(afe->regmap, | |
509 | AFE_MEMIF_PBUF_SIZE, | |
510 | AFE_MEMIF_PBUF_SIZE_DLM_MASK, | |
511 | AFE_MEMIF_PBUF_SIZE_FULL_INTERLEAVE); | |
512 | regmap_update_bits(afe->regmap, | |
513 | AFE_MEMIF_PBUF_SIZE, | |
514 | AFE_MEMIF_PBUF_SIZE_DLM_BYTE_MASK, | |
515 | AFE_MEMIF_PBUF_SIZE_DLM_32BYTES); | |
516 | regmap_update_bits(afe->regmap, | |
517 | AFE_MEMIF_PBUF_SIZE, | |
518 | AFE_MEMIF_PBUF_SIZE_DLM_CH_MASK, | |
519 | AFE_MEMIF_PBUF_SIZE_DLM_CH(channels)); | |
520 | ||
521 | return mtk_afe_fe_hw_params(substream, params, dai); | |
522 | } | |
523 | ||
524 | static int mt2701_dlm_fe_trigger(struct snd_pcm_substream *substream, | |
525 | int cmd, struct snd_soc_dai *dai) | |
526 | { | |
527 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | |
528 | struct mtk_base_afe *afe = snd_soc_platform_get_drvdata(rtd->platform); | |
529 | struct mtk_base_afe_memif *memif_tmp = &afe->memif[MT2701_MEMIF_DL1]; | |
530 | ||
531 | switch (cmd) { | |
532 | case SNDRV_PCM_TRIGGER_START: | |
533 | case SNDRV_PCM_TRIGGER_RESUME: | |
534 | regmap_update_bits(afe->regmap, memif_tmp->data->enable_reg, | |
535 | 1 << memif_tmp->data->enable_shift, | |
536 | 1 << memif_tmp->data->enable_shift); | |
537 | mtk_afe_fe_trigger(substream, cmd, dai); | |
538 | return 0; | |
539 | case SNDRV_PCM_TRIGGER_STOP: | |
540 | case SNDRV_PCM_TRIGGER_SUSPEND: | |
541 | mtk_afe_fe_trigger(substream, cmd, dai); | |
542 | regmap_update_bits(afe->regmap, memif_tmp->data->enable_reg, | |
543 | 1 << memif_tmp->data->enable_shift, 0); | |
544 | ||
545 | return 0; | |
546 | default: | |
547 | return -EINVAL; | |
548 | } | |
549 | } | |
550 | ||
551 | static int mt2701_memif_fs(struct snd_pcm_substream *substream, | |
552 | unsigned int rate) | |
553 | { | |
554 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | |
555 | int fs; | |
556 | ||
557 | if (rtd->cpu_dai->id != MT2701_MEMIF_ULBT) | |
558 | fs = mt2701_afe_i2s_fs(rate); | |
559 | else | |
560 | fs = (rate == 16000 ? 1 : 0); | |
561 | return fs; | |
562 | } | |
563 | ||
564 | static int mt2701_irq_fs(struct snd_pcm_substream *substream, unsigned int rate) | |
565 | { | |
566 | return mt2701_afe_i2s_fs(rate); | |
567 | } | |
568 | ||
569 | /* FE DAIs */ | |
570 | static const struct snd_soc_dai_ops mt2701_single_memif_dai_ops = { | |
571 | .startup = mt2701_simple_fe_startup, | |
572 | .shutdown = mtk_afe_fe_shutdown, | |
573 | .hw_params = mt2701_simple_fe_hw_params, | |
574 | .hw_free = mtk_afe_fe_hw_free, | |
575 | .prepare = mtk_afe_fe_prepare, | |
576 | .trigger = mtk_afe_fe_trigger, | |
577 | ||
578 | }; | |
579 | ||
580 | static const struct snd_soc_dai_ops mt2701_dlm_memif_dai_ops = { | |
581 | .startup = mt2701_dlm_fe_startup, | |
582 | .shutdown = mt2701_dlm_fe_shutdown, | |
583 | .hw_params = mt2701_dlm_fe_hw_params, | |
584 | .hw_free = mtk_afe_fe_hw_free, | |
585 | .prepare = mtk_afe_fe_prepare, | |
586 | .trigger = mt2701_dlm_fe_trigger, | |
587 | }; | |
588 | ||
589 | /* I2S BE DAIs */ | |
590 | static const struct snd_soc_dai_ops mt2701_afe_i2s_ops = { | |
591 | .startup = mt2701_afe_i2s_startup, | |
592 | .shutdown = mt2701_afe_i2s_shutdown, | |
593 | .prepare = mt2701_afe_i2s_prepare, | |
594 | .set_sysclk = mt2701_afe_i2s_set_sysclk, | |
595 | }; | |
596 | ||
597 | /* MRG BE DAIs */ | |
598 | static const struct snd_soc_dai_ops mt2701_btmrg_ops = { | |
599 | .startup = mt2701_btmrg_startup, | |
600 | .shutdown = mt2701_btmrg_shutdown, | |
601 | .hw_params = mt2701_btmrg_hw_params, | |
602 | }; | |
603 | ||
604 | static struct snd_soc_dai_driver mt2701_afe_pcm_dais[] = { | |
605 | /* FE DAIs: memory intefaces to CPU */ | |
606 | { | |
607 | .name = "PCMO0", | |
608 | .id = MT2701_MEMIF_DL1, | |
609 | .suspend = mtk_afe_dai_suspend, | |
610 | .resume = mtk_afe_dai_resume, | |
611 | .playback = { | |
612 | .stream_name = "DL1", | |
613 | .channels_min = 1, | |
614 | .channels_max = 2, | |
615 | .rates = SNDRV_PCM_RATE_8000_192000, | |
616 | .formats = (SNDRV_PCM_FMTBIT_S16_LE | |
617 | | SNDRV_PCM_FMTBIT_S24_LE | |
618 | | SNDRV_PCM_FMTBIT_S32_LE) | |
619 | }, | |
620 | .ops = &mt2701_single_memif_dai_ops, | |
621 | }, | |
622 | { | |
623 | .name = "PCM_multi", | |
624 | .id = MT2701_MEMIF_DLM, | |
625 | .suspend = mtk_afe_dai_suspend, | |
626 | .resume = mtk_afe_dai_resume, | |
627 | .playback = { | |
628 | .stream_name = "DLM", | |
629 | .channels_min = 1, | |
630 | .channels_max = 8, | |
631 | .rates = SNDRV_PCM_RATE_8000_192000, | |
632 | .formats = (SNDRV_PCM_FMTBIT_S16_LE | |
633 | | SNDRV_PCM_FMTBIT_S24_LE | |
634 | | SNDRV_PCM_FMTBIT_S32_LE) | |
635 | ||
636 | }, | |
637 | .ops = &mt2701_dlm_memif_dai_ops, | |
638 | }, | |
639 | { | |
640 | .name = "PCM0", | |
641 | .id = MT2701_MEMIF_UL1, | |
642 | .suspend = mtk_afe_dai_suspend, | |
643 | .resume = mtk_afe_dai_resume, | |
644 | .capture = { | |
645 | .stream_name = "UL1", | |
646 | .channels_min = 1, | |
647 | .channels_max = 2, | |
648 | .rates = SNDRV_PCM_RATE_8000_48000, | |
649 | .formats = (SNDRV_PCM_FMTBIT_S16_LE | |
650 | | SNDRV_PCM_FMTBIT_S24_LE | |
651 | | SNDRV_PCM_FMTBIT_S32_LE) | |
652 | }, | |
653 | .ops = &mt2701_single_memif_dai_ops, | |
654 | }, | |
655 | { | |
656 | .name = "PCM1", | |
657 | .id = MT2701_MEMIF_UL2, | |
658 | .suspend = mtk_afe_dai_suspend, | |
659 | .resume = mtk_afe_dai_resume, | |
660 | .capture = { | |
661 | .stream_name = "UL2", | |
662 | .channels_min = 1, | |
663 | .channels_max = 2, | |
664 | .rates = SNDRV_PCM_RATE_8000_192000, | |
665 | .formats = (SNDRV_PCM_FMTBIT_S16_LE | |
666 | | SNDRV_PCM_FMTBIT_S24_LE | |
667 | | SNDRV_PCM_FMTBIT_S32_LE) | |
668 | ||
669 | }, | |
670 | .ops = &mt2701_single_memif_dai_ops, | |
671 | }, | |
672 | { | |
673 | .name = "PCM_BT_DL", | |
674 | .id = MT2701_MEMIF_DLBT, | |
675 | .suspend = mtk_afe_dai_suspend, | |
676 | .resume = mtk_afe_dai_resume, | |
677 | .playback = { | |
678 | .stream_name = "DLBT", | |
679 | .channels_min = 1, | |
680 | .channels_max = 1, | |
681 | .rates = (SNDRV_PCM_RATE_8000 | |
682 | | SNDRV_PCM_RATE_16000), | |
683 | .formats = SNDRV_PCM_FMTBIT_S16_LE, | |
684 | }, | |
685 | .ops = &mt2701_single_memif_dai_ops, | |
686 | }, | |
687 | { | |
688 | .name = "PCM_BT_UL", | |
689 | .id = MT2701_MEMIF_ULBT, | |
690 | .suspend = mtk_afe_dai_suspend, | |
691 | .resume = mtk_afe_dai_resume, | |
692 | .capture = { | |
693 | .stream_name = "ULBT", | |
694 | .channels_min = 1, | |
695 | .channels_max = 1, | |
696 | .rates = (SNDRV_PCM_RATE_8000 | |
697 | | SNDRV_PCM_RATE_16000), | |
698 | .formats = SNDRV_PCM_FMTBIT_S16_LE, | |
699 | }, | |
700 | .ops = &mt2701_single_memif_dai_ops, | |
701 | }, | |
702 | /* BE DAIs */ | |
703 | { | |
704 | .name = "I2S0", | |
705 | .id = MT2701_IO_I2S, | |
706 | .playback = { | |
707 | .stream_name = "I2S0 Playback", | |
708 | .channels_min = 1, | |
709 | .channels_max = 2, | |
710 | .rates = SNDRV_PCM_RATE_8000_192000, | |
711 | .formats = (SNDRV_PCM_FMTBIT_S16_LE | |
712 | | SNDRV_PCM_FMTBIT_S24_LE | |
713 | | SNDRV_PCM_FMTBIT_S32_LE) | |
714 | ||
715 | }, | |
716 | .capture = { | |
717 | .stream_name = "I2S0 Capture", | |
718 | .channels_min = 1, | |
719 | .channels_max = 2, | |
720 | .rates = SNDRV_PCM_RATE_8000_192000, | |
721 | .formats = (SNDRV_PCM_FMTBIT_S16_LE | |
722 | | SNDRV_PCM_FMTBIT_S24_LE | |
723 | | SNDRV_PCM_FMTBIT_S32_LE) | |
724 | ||
725 | }, | |
726 | .ops = &mt2701_afe_i2s_ops, | |
727 | .symmetric_rates = 1, | |
728 | }, | |
729 | { | |
730 | .name = "I2S1", | |
731 | .id = MT2701_IO_2ND_I2S, | |
732 | .playback = { | |
733 | .stream_name = "I2S1 Playback", | |
734 | .channels_min = 1, | |
735 | .channels_max = 2, | |
736 | .rates = SNDRV_PCM_RATE_8000_192000, | |
737 | .formats = (SNDRV_PCM_FMTBIT_S16_LE | |
738 | | SNDRV_PCM_FMTBIT_S24_LE | |
739 | | SNDRV_PCM_FMTBIT_S32_LE) | |
740 | }, | |
741 | .capture = { | |
742 | .stream_name = "I2S1 Capture", | |
743 | .channels_min = 1, | |
744 | .channels_max = 2, | |
745 | .rates = SNDRV_PCM_RATE_8000_192000, | |
746 | .formats = (SNDRV_PCM_FMTBIT_S16_LE | |
747 | | SNDRV_PCM_FMTBIT_S24_LE | |
748 | | SNDRV_PCM_FMTBIT_S32_LE) | |
749 | }, | |
750 | .ops = &mt2701_afe_i2s_ops, | |
751 | .symmetric_rates = 1, | |
752 | }, | |
753 | { | |
754 | .name = "I2S2", | |
755 | .id = MT2701_IO_3RD_I2S, | |
756 | .playback = { | |
757 | .stream_name = "I2S2 Playback", | |
758 | .channels_min = 1, | |
759 | .channels_max = 2, | |
760 | .rates = SNDRV_PCM_RATE_8000_192000, | |
761 | .formats = (SNDRV_PCM_FMTBIT_S16_LE | |
762 | | SNDRV_PCM_FMTBIT_S24_LE | |
763 | | SNDRV_PCM_FMTBIT_S32_LE) | |
764 | }, | |
765 | .capture = { | |
766 | .stream_name = "I2S2 Capture", | |
767 | .channels_min = 1, | |
768 | .channels_max = 2, | |
769 | .rates = SNDRV_PCM_RATE_8000_192000, | |
770 | .formats = (SNDRV_PCM_FMTBIT_S16_LE | |
771 | | SNDRV_PCM_FMTBIT_S24_LE | |
772 | | SNDRV_PCM_FMTBIT_S32_LE) | |
773 | }, | |
774 | .ops = &mt2701_afe_i2s_ops, | |
775 | .symmetric_rates = 1, | |
776 | }, | |
777 | { | |
778 | .name = "I2S3", | |
779 | .id = MT2701_IO_4TH_I2S, | |
780 | .playback = { | |
781 | .stream_name = "I2S3 Playback", | |
782 | .channels_min = 1, | |
783 | .channels_max = 2, | |
784 | .rates = SNDRV_PCM_RATE_8000_192000, | |
785 | .formats = (SNDRV_PCM_FMTBIT_S16_LE | |
786 | | SNDRV_PCM_FMTBIT_S24_LE | |
787 | | SNDRV_PCM_FMTBIT_S32_LE) | |
788 | }, | |
789 | .capture = { | |
790 | .stream_name = "I2S3 Capture", | |
791 | .channels_min = 1, | |
792 | .channels_max = 2, | |
793 | .rates = SNDRV_PCM_RATE_8000_192000, | |
794 | .formats = (SNDRV_PCM_FMTBIT_S16_LE | |
795 | | SNDRV_PCM_FMTBIT_S24_LE | |
796 | | SNDRV_PCM_FMTBIT_S32_LE) | |
797 | }, | |
798 | .ops = &mt2701_afe_i2s_ops, | |
799 | .symmetric_rates = 1, | |
800 | }, | |
801 | { | |
802 | .name = "MRG BT", | |
803 | .id = MT2701_IO_MRG, | |
804 | .playback = { | |
805 | .stream_name = "BT Playback", | |
806 | .channels_min = 1, | |
807 | .channels_max = 1, | |
808 | .rates = (SNDRV_PCM_RATE_8000 | |
809 | | SNDRV_PCM_RATE_16000), | |
810 | .formats = SNDRV_PCM_FMTBIT_S16_LE, | |
811 | }, | |
812 | .capture = { | |
813 | .stream_name = "BT Capture", | |
814 | .channels_min = 1, | |
815 | .channels_max = 1, | |
816 | .rates = (SNDRV_PCM_RATE_8000 | |
817 | | SNDRV_PCM_RATE_16000), | |
818 | .formats = SNDRV_PCM_FMTBIT_S16_LE, | |
819 | }, | |
820 | .ops = &mt2701_btmrg_ops, | |
821 | .symmetric_rates = 1, | |
822 | } | |
823 | }; | |
824 | ||
825 | static const struct snd_kcontrol_new mt2701_afe_o00_mix[] = { | |
826 | SOC_DAPM_SINGLE_AUTODISABLE("I00 Switch", AFE_CONN0, 0, 1, 0), | |
827 | }; | |
828 | ||
829 | static const struct snd_kcontrol_new mt2701_afe_o01_mix[] = { | |
830 | SOC_DAPM_SINGLE_AUTODISABLE("I01 Switch", AFE_CONN1, 1, 1, 0), | |
831 | }; | |
832 | ||
833 | static const struct snd_kcontrol_new mt2701_afe_o02_mix[] = { | |
834 | SOC_DAPM_SINGLE_AUTODISABLE("I02 Switch", AFE_CONN2, 2, 1, 0), | |
835 | }; | |
836 | ||
837 | static const struct snd_kcontrol_new mt2701_afe_o03_mix[] = { | |
838 | SOC_DAPM_SINGLE_AUTODISABLE("I03 Switch", AFE_CONN3, 3, 1, 0), | |
839 | }; | |
840 | ||
841 | static const struct snd_kcontrol_new mt2701_afe_o14_mix[] = { | |
842 | SOC_DAPM_SINGLE_AUTODISABLE("I26 Switch", AFE_CONN14, 26, 1, 0), | |
843 | }; | |
844 | ||
845 | static const struct snd_kcontrol_new mt2701_afe_o15_mix[] = { | |
846 | SOC_DAPM_SINGLE_AUTODISABLE("I12 Switch", AFE_CONN15, 12, 1, 0), | |
847 | }; | |
848 | ||
849 | static const struct snd_kcontrol_new mt2701_afe_o16_mix[] = { | |
850 | SOC_DAPM_SINGLE_AUTODISABLE("I13 Switch", AFE_CONN16, 13, 1, 0), | |
851 | }; | |
852 | ||
853 | static const struct snd_kcontrol_new mt2701_afe_o17_mix[] = { | |
854 | SOC_DAPM_SINGLE_AUTODISABLE("I14 Switch", AFE_CONN17, 14, 1, 0), | |
855 | }; | |
856 | ||
857 | static const struct snd_kcontrol_new mt2701_afe_o18_mix[] = { | |
858 | SOC_DAPM_SINGLE_AUTODISABLE("I15 Switch", AFE_CONN18, 15, 1, 0), | |
859 | }; | |
860 | ||
861 | static const struct snd_kcontrol_new mt2701_afe_o19_mix[] = { | |
862 | SOC_DAPM_SINGLE_AUTODISABLE("I16 Switch", AFE_CONN19, 16, 1, 0), | |
863 | }; | |
864 | ||
865 | static const struct snd_kcontrol_new mt2701_afe_o20_mix[] = { | |
866 | SOC_DAPM_SINGLE_AUTODISABLE("I17 Switch", AFE_CONN20, 17, 1, 0), | |
867 | }; | |
868 | ||
869 | static const struct snd_kcontrol_new mt2701_afe_o21_mix[] = { | |
870 | SOC_DAPM_SINGLE_AUTODISABLE("I18 Switch", AFE_CONN21, 18, 1, 0), | |
871 | }; | |
872 | ||
873 | static const struct snd_kcontrol_new mt2701_afe_o22_mix[] = { | |
874 | SOC_DAPM_SINGLE_AUTODISABLE("I19 Switch", AFE_CONN22, 19, 1, 0), | |
875 | }; | |
876 | ||
877 | static const struct snd_kcontrol_new mt2701_afe_o23_mix[] = { | |
878 | SOC_DAPM_SINGLE_AUTODISABLE("I20 Switch", AFE_CONN23, 20, 1, 0), | |
879 | }; | |
880 | ||
881 | static const struct snd_kcontrol_new mt2701_afe_o24_mix[] = { | |
882 | SOC_DAPM_SINGLE_AUTODISABLE("I21 Switch", AFE_CONN24, 21, 1, 0), | |
883 | }; | |
884 | ||
885 | static const struct snd_kcontrol_new mt2701_afe_o31_mix[] = { | |
886 | SOC_DAPM_SINGLE_AUTODISABLE("I35 Switch", AFE_CONN41, 9, 1, 0), | |
887 | }; | |
888 | ||
889 | static const struct snd_kcontrol_new mt2701_afe_i02_mix[] = { | |
890 | SOC_DAPM_SINGLE("I2S0 Switch", SND_SOC_NOPM, 0, 1, 0), | |
891 | }; | |
892 | ||
893 | static const struct snd_kcontrol_new mt2701_afe_multi_ch_out_i2s0[] = { | |
894 | SOC_DAPM_SINGLE_AUTODISABLE("Multich I2S0 Out Switch", | |
895 | ASYS_I2SO1_CON, 26, 1, 0), | |
896 | }; | |
897 | ||
898 | static const struct snd_kcontrol_new mt2701_afe_multi_ch_out_i2s1[] = { | |
899 | SOC_DAPM_SINGLE_AUTODISABLE("Multich I2S1 Out Switch", | |
900 | ASYS_I2SO2_CON, 26, 1, 0), | |
901 | }; | |
902 | ||
903 | static const struct snd_kcontrol_new mt2701_afe_multi_ch_out_i2s2[] = { | |
904 | SOC_DAPM_SINGLE_AUTODISABLE("Multich I2S2 Out Switch", | |
905 | PWR2_TOP_CON, 17, 1, 0), | |
906 | }; | |
907 | ||
908 | static const struct snd_kcontrol_new mt2701_afe_multi_ch_out_i2s3[] = { | |
909 | SOC_DAPM_SINGLE_AUTODISABLE("Multich I2S3 Out Switch", | |
910 | PWR2_TOP_CON, 18, 1, 0), | |
911 | }; | |
912 | ||
913 | static const struct snd_kcontrol_new mt2701_afe_multi_ch_out_i2s4[] = { | |
914 | SOC_DAPM_SINGLE_AUTODISABLE("Multich I2S4 Out Switch", | |
915 | PWR2_TOP_CON, 19, 1, 0), | |
916 | }; | |
917 | ||
918 | static const struct snd_kcontrol_new mt2701_afe_multi_ch_out_asrc0[] = { | |
919 | SOC_DAPM_SINGLE_AUTODISABLE("Asrc0 out Switch", AUDIO_TOP_CON4, 14, 1, | |
920 | 1), | |
921 | }; | |
922 | ||
923 | static const struct snd_kcontrol_new mt2701_afe_multi_ch_out_asrc1[] = { | |
924 | SOC_DAPM_SINGLE_AUTODISABLE("Asrc1 out Switch", AUDIO_TOP_CON4, 15, 1, | |
925 | 1), | |
926 | }; | |
927 | ||
928 | static const struct snd_kcontrol_new mt2701_afe_multi_ch_out_asrc2[] = { | |
929 | SOC_DAPM_SINGLE_AUTODISABLE("Asrc2 out Switch", PWR2_TOP_CON, 6, 1, | |
930 | 1), | |
931 | }; | |
932 | ||
933 | static const struct snd_kcontrol_new mt2701_afe_multi_ch_out_asrc3[] = { | |
934 | SOC_DAPM_SINGLE_AUTODISABLE("Asrc3 out Switch", PWR2_TOP_CON, 7, 1, | |
935 | 1), | |
936 | }; | |
937 | ||
938 | static const struct snd_kcontrol_new mt2701_afe_multi_ch_out_asrc4[] = { | |
939 | SOC_DAPM_SINGLE_AUTODISABLE("Asrc4 out Switch", PWR2_TOP_CON, 8, 1, | |
940 | 1), | |
941 | }; | |
942 | ||
943 | static const struct snd_soc_dapm_widget mt2701_afe_pcm_widgets[] = { | |
944 | /* inter-connections */ | |
945 | SND_SOC_DAPM_MIXER("I00", SND_SOC_NOPM, 0, 0, NULL, 0), | |
946 | SND_SOC_DAPM_MIXER("I01", SND_SOC_NOPM, 0, 0, NULL, 0), | |
947 | SND_SOC_DAPM_MIXER("I02", SND_SOC_NOPM, 0, 0, mt2701_afe_i02_mix, | |
948 | ARRAY_SIZE(mt2701_afe_i02_mix)), | |
949 | SND_SOC_DAPM_MIXER("I03", SND_SOC_NOPM, 0, 0, NULL, 0), | |
950 | SND_SOC_DAPM_MIXER("I12", SND_SOC_NOPM, 0, 0, NULL, 0), | |
951 | SND_SOC_DAPM_MIXER("I13", SND_SOC_NOPM, 0, 0, NULL, 0), | |
952 | SND_SOC_DAPM_MIXER("I14", SND_SOC_NOPM, 0, 0, NULL, 0), | |
953 | SND_SOC_DAPM_MIXER("I15", SND_SOC_NOPM, 0, 0, NULL, 0), | |
954 | SND_SOC_DAPM_MIXER("I16", SND_SOC_NOPM, 0, 0, NULL, 0), | |
955 | SND_SOC_DAPM_MIXER("I17", SND_SOC_NOPM, 0, 0, NULL, 0), | |
956 | SND_SOC_DAPM_MIXER("I18", SND_SOC_NOPM, 0, 0, NULL, 0), | |
957 | SND_SOC_DAPM_MIXER("I19", SND_SOC_NOPM, 0, 0, NULL, 0), | |
958 | SND_SOC_DAPM_MIXER("I26", SND_SOC_NOPM, 0, 0, NULL, 0), | |
959 | SND_SOC_DAPM_MIXER("I35", SND_SOC_NOPM, 0, 0, NULL, 0), | |
960 | ||
961 | SND_SOC_DAPM_MIXER("O00", SND_SOC_NOPM, 0, 0, mt2701_afe_o00_mix, | |
962 | ARRAY_SIZE(mt2701_afe_o00_mix)), | |
963 | SND_SOC_DAPM_MIXER("O01", SND_SOC_NOPM, 0, 0, mt2701_afe_o01_mix, | |
964 | ARRAY_SIZE(mt2701_afe_o01_mix)), | |
965 | SND_SOC_DAPM_MIXER("O02", SND_SOC_NOPM, 0, 0, mt2701_afe_o02_mix, | |
966 | ARRAY_SIZE(mt2701_afe_o02_mix)), | |
967 | SND_SOC_DAPM_MIXER("O03", SND_SOC_NOPM, 0, 0, mt2701_afe_o03_mix, | |
968 | ARRAY_SIZE(mt2701_afe_o03_mix)), | |
969 | SND_SOC_DAPM_MIXER("O14", SND_SOC_NOPM, 0, 0, mt2701_afe_o14_mix, | |
970 | ARRAY_SIZE(mt2701_afe_o14_mix)), | |
971 | SND_SOC_DAPM_MIXER("O15", SND_SOC_NOPM, 0, 0, mt2701_afe_o15_mix, | |
972 | ARRAY_SIZE(mt2701_afe_o15_mix)), | |
973 | SND_SOC_DAPM_MIXER("O16", SND_SOC_NOPM, 0, 0, mt2701_afe_o16_mix, | |
974 | ARRAY_SIZE(mt2701_afe_o16_mix)), | |
975 | SND_SOC_DAPM_MIXER("O17", SND_SOC_NOPM, 0, 0, mt2701_afe_o17_mix, | |
976 | ARRAY_SIZE(mt2701_afe_o17_mix)), | |
977 | SND_SOC_DAPM_MIXER("O18", SND_SOC_NOPM, 0, 0, mt2701_afe_o18_mix, | |
978 | ARRAY_SIZE(mt2701_afe_o18_mix)), | |
979 | SND_SOC_DAPM_MIXER("O19", SND_SOC_NOPM, 0, 0, mt2701_afe_o19_mix, | |
980 | ARRAY_SIZE(mt2701_afe_o19_mix)), | |
981 | SND_SOC_DAPM_MIXER("O20", SND_SOC_NOPM, 0, 0, mt2701_afe_o20_mix, | |
982 | ARRAY_SIZE(mt2701_afe_o20_mix)), | |
983 | SND_SOC_DAPM_MIXER("O21", SND_SOC_NOPM, 0, 0, mt2701_afe_o21_mix, | |
984 | ARRAY_SIZE(mt2701_afe_o21_mix)), | |
985 | SND_SOC_DAPM_MIXER("O22", SND_SOC_NOPM, 0, 0, mt2701_afe_o22_mix, | |
986 | ARRAY_SIZE(mt2701_afe_o22_mix)), | |
987 | SND_SOC_DAPM_MIXER("O31", SND_SOC_NOPM, 0, 0, mt2701_afe_o31_mix, | |
988 | ARRAY_SIZE(mt2701_afe_o31_mix)), | |
989 | ||
990 | SND_SOC_DAPM_MIXER("I12I13", SND_SOC_NOPM, 0, 0, | |
991 | mt2701_afe_multi_ch_out_i2s0, | |
992 | ARRAY_SIZE(mt2701_afe_multi_ch_out_i2s0)), | |
993 | SND_SOC_DAPM_MIXER("I14I15", SND_SOC_NOPM, 0, 0, | |
994 | mt2701_afe_multi_ch_out_i2s1, | |
995 | ARRAY_SIZE(mt2701_afe_multi_ch_out_i2s1)), | |
996 | SND_SOC_DAPM_MIXER("I16I17", SND_SOC_NOPM, 0, 0, | |
997 | mt2701_afe_multi_ch_out_i2s2, | |
998 | ARRAY_SIZE(mt2701_afe_multi_ch_out_i2s2)), | |
999 | SND_SOC_DAPM_MIXER("I18I19", SND_SOC_NOPM, 0, 0, | |
1000 | mt2701_afe_multi_ch_out_i2s3, | |
1001 | ARRAY_SIZE(mt2701_afe_multi_ch_out_i2s3)), | |
1002 | ||
1003 | SND_SOC_DAPM_MIXER("ASRC_O0", SND_SOC_NOPM, 0, 0, | |
1004 | mt2701_afe_multi_ch_out_asrc0, | |
1005 | ARRAY_SIZE(mt2701_afe_multi_ch_out_asrc0)), | |
1006 | SND_SOC_DAPM_MIXER("ASRC_O1", SND_SOC_NOPM, 0, 0, | |
1007 | mt2701_afe_multi_ch_out_asrc1, | |
1008 | ARRAY_SIZE(mt2701_afe_multi_ch_out_asrc1)), | |
1009 | SND_SOC_DAPM_MIXER("ASRC_O2", SND_SOC_NOPM, 0, 0, | |
1010 | mt2701_afe_multi_ch_out_asrc2, | |
1011 | ARRAY_SIZE(mt2701_afe_multi_ch_out_asrc2)), | |
1012 | SND_SOC_DAPM_MIXER("ASRC_O3", SND_SOC_NOPM, 0, 0, | |
1013 | mt2701_afe_multi_ch_out_asrc3, | |
1014 | ARRAY_SIZE(mt2701_afe_multi_ch_out_asrc3)), | |
1015 | }; | |
1016 | ||
1017 | static const struct snd_soc_dapm_route mt2701_afe_pcm_routes[] = { | |
1018 | {"I12", NULL, "DL1"}, | |
1019 | {"I13", NULL, "DL1"}, | |
1020 | {"I35", NULL, "DLBT"}, | |
1021 | ||
1022 | {"I2S0 Playback", NULL, "O15"}, | |
1023 | {"I2S0 Playback", NULL, "O16"}, | |
1024 | ||
1025 | {"I2S1 Playback", NULL, "O17"}, | |
1026 | {"I2S1 Playback", NULL, "O18"}, | |
1027 | {"I2S2 Playback", NULL, "O19"}, | |
1028 | {"I2S2 Playback", NULL, "O20"}, | |
1029 | {"I2S3 Playback", NULL, "O21"}, | |
1030 | {"I2S3 Playback", NULL, "O22"}, | |
1031 | {"BT Playback", NULL, "O31"}, | |
1032 | ||
1033 | {"UL1", NULL, "O00"}, | |
1034 | {"UL1", NULL, "O01"}, | |
1035 | {"UL2", NULL, "O02"}, | |
1036 | {"UL2", NULL, "O03"}, | |
1037 | {"ULBT", NULL, "O14"}, | |
1038 | ||
1039 | {"I00", NULL, "I2S0 Capture"}, | |
1040 | {"I01", NULL, "I2S0 Capture"}, | |
1041 | ||
1042 | {"I02", NULL, "I2S1 Capture"}, | |
1043 | {"I03", NULL, "I2S1 Capture"}, | |
1044 | /* I02,03 link to UL2, also need to open I2S0 */ | |
1045 | {"I02", "I2S0 Switch", "I2S0 Capture"}, | |
1046 | ||
1047 | {"I26", NULL, "BT Capture"}, | |
1048 | ||
1049 | {"ASRC_O0", "Asrc0 out Switch", "DLM"}, | |
1050 | {"ASRC_O1", "Asrc1 out Switch", "DLM"}, | |
1051 | {"ASRC_O2", "Asrc2 out Switch", "DLM"}, | |
1052 | {"ASRC_O3", "Asrc3 out Switch", "DLM"}, | |
1053 | ||
1054 | {"I12I13", "Multich I2S0 Out Switch", "ASRC_O0"}, | |
1055 | {"I14I15", "Multich I2S1 Out Switch", "ASRC_O1"}, | |
1056 | {"I16I17", "Multich I2S2 Out Switch", "ASRC_O2"}, | |
1057 | {"I18I19", "Multich I2S3 Out Switch", "ASRC_O3"}, | |
1058 | ||
1059 | { "I12", NULL, "I12I13" }, | |
1060 | { "I13", NULL, "I12I13" }, | |
1061 | { "I14", NULL, "I14I15" }, | |
1062 | { "I15", NULL, "I14I15" }, | |
1063 | { "I16", NULL, "I16I17" }, | |
1064 | { "I17", NULL, "I16I17" }, | |
1065 | { "I18", NULL, "I18I19" }, | |
1066 | { "I19", NULL, "I18I19" }, | |
1067 | ||
1068 | { "O00", "I00 Switch", "I00" }, | |
1069 | { "O01", "I01 Switch", "I01" }, | |
1070 | { "O02", "I02 Switch", "I02" }, | |
1071 | { "O03", "I03 Switch", "I03" }, | |
1072 | { "O14", "I26 Switch", "I26" }, | |
1073 | { "O15", "I12 Switch", "I12" }, | |
1074 | { "O16", "I13 Switch", "I13" }, | |
1075 | { "O17", "I14 Switch", "I14" }, | |
1076 | { "O18", "I15 Switch", "I15" }, | |
1077 | { "O19", "I16 Switch", "I16" }, | |
1078 | { "O20", "I17 Switch", "I17" }, | |
1079 | { "O21", "I18 Switch", "I18" }, | |
1080 | { "O22", "I19 Switch", "I19" }, | |
1081 | { "O31", "I35 Switch", "I35" }, | |
1082 | ||
1083 | }; | |
1084 | ||
1085 | static const struct snd_soc_component_driver mt2701_afe_pcm_dai_component = { | |
1086 | .name = "mt2701-afe-pcm-dai", | |
1087 | .dapm_widgets = mt2701_afe_pcm_widgets, | |
1088 | .num_dapm_widgets = ARRAY_SIZE(mt2701_afe_pcm_widgets), | |
1089 | .dapm_routes = mt2701_afe_pcm_routes, | |
1090 | .num_dapm_routes = ARRAY_SIZE(mt2701_afe_pcm_routes), | |
1091 | }; | |
1092 | ||
1093 | static const struct mtk_base_memif_data memif_data[MT2701_MEMIF_NUM] = { | |
1094 | { | |
1095 | .name = "DL1", | |
1096 | .id = MT2701_MEMIF_DL1, | |
1097 | .reg_ofs_base = AFE_DL1_BASE, | |
1098 | .reg_ofs_cur = AFE_DL1_CUR, | |
1099 | .fs_reg = AFE_DAC_CON1, | |
1100 | .fs_shift = 0, | |
1101 | .fs_maskbit = 0x1f, | |
1102 | .mono_reg = AFE_DAC_CON3, | |
1103 | .mono_shift = 16, | |
1104 | .enable_reg = AFE_DAC_CON0, | |
1105 | .enable_shift = 1, | |
1106 | .hd_reg = AFE_MEMIF_HD_CON0, | |
1107 | .hd_shift = 0, | |
1108 | .agent_disable_reg = AUDIO_TOP_CON5, | |
1109 | .agent_disable_shift = 6, | |
1110 | .msb_reg = -1, | |
1111 | .msb_shift = -1, | |
1112 | }, | |
1113 | { | |
1114 | .name = "DL2", | |
1115 | .id = MT2701_MEMIF_DL2, | |
1116 | .reg_ofs_base = AFE_DL2_BASE, | |
1117 | .reg_ofs_cur = AFE_DL2_CUR, | |
1118 | .fs_reg = AFE_DAC_CON1, | |
1119 | .fs_shift = 5, | |
1120 | .fs_maskbit = 0x1f, | |
1121 | .mono_reg = AFE_DAC_CON3, | |
1122 | .mono_shift = 17, | |
1123 | .enable_reg = AFE_DAC_CON0, | |
1124 | .enable_shift = 2, | |
1125 | .hd_reg = AFE_MEMIF_HD_CON0, | |
1126 | .hd_shift = 2, | |
1127 | .agent_disable_reg = AUDIO_TOP_CON5, | |
1128 | .agent_disable_shift = 7, | |
1129 | .msb_reg = -1, | |
1130 | .msb_shift = -1, | |
1131 | }, | |
1132 | { | |
1133 | .name = "DL3", | |
1134 | .id = MT2701_MEMIF_DL3, | |
1135 | .reg_ofs_base = AFE_DL3_BASE, | |
1136 | .reg_ofs_cur = AFE_DL3_CUR, | |
1137 | .fs_reg = AFE_DAC_CON1, | |
1138 | .fs_shift = 10, | |
1139 | .fs_maskbit = 0x1f, | |
1140 | .mono_reg = AFE_DAC_CON3, | |
1141 | .mono_shift = 18, | |
1142 | .enable_reg = AFE_DAC_CON0, | |
1143 | .enable_shift = 3, | |
1144 | .hd_reg = AFE_MEMIF_HD_CON0, | |
1145 | .hd_shift = 4, | |
1146 | .agent_disable_reg = AUDIO_TOP_CON5, | |
1147 | .agent_disable_shift = 8, | |
1148 | .msb_reg = -1, | |
1149 | .msb_shift = -1, | |
1150 | }, | |
1151 | { | |
1152 | .name = "DL4", | |
1153 | .id = MT2701_MEMIF_DL4, | |
1154 | .reg_ofs_base = AFE_DL4_BASE, | |
1155 | .reg_ofs_cur = AFE_DL4_CUR, | |
1156 | .fs_reg = AFE_DAC_CON1, | |
1157 | .fs_shift = 15, | |
1158 | .fs_maskbit = 0x1f, | |
1159 | .mono_reg = AFE_DAC_CON3, | |
1160 | .mono_shift = 19, | |
1161 | .enable_reg = AFE_DAC_CON0, | |
1162 | .enable_shift = 4, | |
1163 | .hd_reg = AFE_MEMIF_HD_CON0, | |
1164 | .hd_shift = 6, | |
1165 | .agent_disable_reg = AUDIO_TOP_CON5, | |
1166 | .agent_disable_shift = 9, | |
1167 | .msb_reg = -1, | |
1168 | .msb_shift = -1, | |
1169 | }, | |
1170 | { | |
1171 | .name = "DL5", | |
1172 | .id = MT2701_MEMIF_DL5, | |
1173 | .reg_ofs_base = AFE_DL5_BASE, | |
1174 | .reg_ofs_cur = AFE_DL5_CUR, | |
1175 | .fs_reg = AFE_DAC_CON1, | |
1176 | .fs_shift = 20, | |
1177 | .fs_maskbit = 0x1f, | |
1178 | .mono_reg = AFE_DAC_CON3, | |
1179 | .mono_shift = 20, | |
1180 | .enable_reg = AFE_DAC_CON0, | |
1181 | .enable_shift = 5, | |
1182 | .hd_reg = AFE_MEMIF_HD_CON0, | |
1183 | .hd_shift = 8, | |
1184 | .agent_disable_reg = AUDIO_TOP_CON5, | |
1185 | .agent_disable_shift = 10, | |
1186 | .msb_reg = -1, | |
1187 | .msb_shift = -1, | |
1188 | }, | |
1189 | { | |
1190 | .name = "DLM", | |
1191 | .id = MT2701_MEMIF_DLM, | |
1192 | .reg_ofs_base = AFE_DLMCH_BASE, | |
1193 | .reg_ofs_cur = AFE_DLMCH_CUR, | |
1194 | .fs_reg = AFE_DAC_CON1, | |
1195 | .fs_shift = 0, | |
1196 | .fs_maskbit = 0x1f, | |
1197 | .mono_reg = -1, | |
1198 | .mono_shift = -1, | |
1199 | .enable_reg = AFE_DAC_CON0, | |
1200 | .enable_shift = 7, | |
1201 | .hd_reg = AFE_MEMIF_PBUF_SIZE, | |
1202 | .hd_shift = 28, | |
1203 | .agent_disable_reg = AUDIO_TOP_CON5, | |
1204 | .agent_disable_shift = 12, | |
1205 | .msb_reg = -1, | |
1206 | .msb_shift = -1, | |
1207 | }, | |
1208 | { | |
1209 | .name = "UL1", | |
1210 | .id = MT2701_MEMIF_UL1, | |
1211 | .reg_ofs_base = AFE_VUL_BASE, | |
1212 | .reg_ofs_cur = AFE_VUL_CUR, | |
1213 | .fs_reg = AFE_DAC_CON2, | |
1214 | .fs_shift = 0, | |
1215 | .fs_maskbit = 0x1f, | |
1216 | .mono_reg = AFE_DAC_CON4, | |
1217 | .mono_shift = 0, | |
1218 | .enable_reg = AFE_DAC_CON0, | |
1219 | .enable_shift = 10, | |
1220 | .hd_reg = AFE_MEMIF_HD_CON1, | |
1221 | .hd_shift = 0, | |
1222 | .agent_disable_reg = AUDIO_TOP_CON5, | |
1223 | .agent_disable_shift = 0, | |
1224 | .msb_reg = -1, | |
1225 | .msb_shift = -1, | |
1226 | }, | |
1227 | { | |
1228 | .name = "UL2", | |
1229 | .id = MT2701_MEMIF_UL2, | |
1230 | .reg_ofs_base = AFE_UL2_BASE, | |
1231 | .reg_ofs_cur = AFE_UL2_CUR, | |
1232 | .fs_reg = AFE_DAC_CON2, | |
1233 | .fs_shift = 5, | |
1234 | .fs_maskbit = 0x1f, | |
1235 | .mono_reg = AFE_DAC_CON4, | |
1236 | .mono_shift = 2, | |
1237 | .enable_reg = AFE_DAC_CON0, | |
1238 | .enable_shift = 11, | |
1239 | .hd_reg = AFE_MEMIF_HD_CON1, | |
1240 | .hd_shift = 2, | |
1241 | .agent_disable_reg = AUDIO_TOP_CON5, | |
1242 | .agent_disable_shift = 1, | |
1243 | .msb_reg = -1, | |
1244 | .msb_shift = -1, | |
1245 | }, | |
1246 | { | |
1247 | .name = "UL3", | |
1248 | .id = MT2701_MEMIF_UL3, | |
1249 | .reg_ofs_base = AFE_UL3_BASE, | |
1250 | .reg_ofs_cur = AFE_UL3_CUR, | |
1251 | .fs_reg = AFE_DAC_CON2, | |
1252 | .fs_shift = 10, | |
1253 | .fs_maskbit = 0x1f, | |
1254 | .mono_reg = AFE_DAC_CON4, | |
1255 | .mono_shift = 4, | |
1256 | .enable_reg = AFE_DAC_CON0, | |
1257 | .enable_shift = 12, | |
1258 | .hd_reg = AFE_MEMIF_HD_CON0, | |
1259 | .hd_shift = 0, | |
1260 | .agent_disable_reg = AUDIO_TOP_CON5, | |
1261 | .agent_disable_shift = 2, | |
1262 | .msb_reg = -1, | |
1263 | .msb_shift = -1, | |
1264 | }, | |
1265 | { | |
1266 | .name = "UL4", | |
1267 | .id = MT2701_MEMIF_UL4, | |
1268 | .reg_ofs_base = AFE_UL4_BASE, | |
1269 | .reg_ofs_cur = AFE_UL4_CUR, | |
1270 | .fs_reg = AFE_DAC_CON2, | |
1271 | .fs_shift = 15, | |
1272 | .fs_maskbit = 0x1f, | |
1273 | .mono_reg = AFE_DAC_CON4, | |
1274 | .mono_shift = 6, | |
1275 | .enable_reg = AFE_DAC_CON0, | |
1276 | .enable_shift = 13, | |
1277 | .hd_reg = AFE_MEMIF_HD_CON0, | |
1278 | .hd_shift = 6, | |
1279 | .agent_disable_reg = AUDIO_TOP_CON5, | |
1280 | .agent_disable_shift = 3, | |
1281 | .msb_reg = -1, | |
1282 | .msb_shift = -1, | |
1283 | }, | |
1284 | { | |
1285 | .name = "UL5", | |
1286 | .id = MT2701_MEMIF_UL5, | |
1287 | .reg_ofs_base = AFE_UL5_BASE, | |
1288 | .reg_ofs_cur = AFE_UL5_CUR, | |
1289 | .fs_reg = AFE_DAC_CON2, | |
1290 | .fs_shift = 20, | |
1291 | .mono_reg = AFE_DAC_CON4, | |
1292 | .mono_shift = 8, | |
1293 | .fs_maskbit = 0x1f, | |
1294 | .enable_reg = AFE_DAC_CON0, | |
1295 | .enable_shift = 14, | |
1296 | .hd_reg = AFE_MEMIF_HD_CON0, | |
1297 | .hd_shift = 8, | |
1298 | .agent_disable_reg = AUDIO_TOP_CON5, | |
1299 | .agent_disable_shift = 4, | |
1300 | .msb_reg = -1, | |
1301 | .msb_shift = -1, | |
1302 | }, | |
1303 | { | |
1304 | .name = "DLBT", | |
1305 | .id = MT2701_MEMIF_DLBT, | |
1306 | .reg_ofs_base = AFE_ARB1_BASE, | |
1307 | .reg_ofs_cur = AFE_ARB1_CUR, | |
1308 | .fs_reg = AFE_DAC_CON3, | |
1309 | .fs_shift = 10, | |
1310 | .fs_maskbit = 0x1f, | |
1311 | .mono_reg = AFE_DAC_CON3, | |
1312 | .mono_shift = 22, | |
1313 | .enable_reg = AFE_DAC_CON0, | |
1314 | .enable_shift = 8, | |
1315 | .hd_reg = AFE_MEMIF_HD_CON0, | |
1316 | .hd_shift = 14, | |
1317 | .agent_disable_reg = AUDIO_TOP_CON5, | |
1318 | .agent_disable_shift = 13, | |
1319 | .msb_reg = -1, | |
1320 | .msb_shift = -1, | |
1321 | }, | |
1322 | { | |
1323 | .name = "ULBT", | |
1324 | .id = MT2701_MEMIF_ULBT, | |
1325 | .reg_ofs_base = AFE_DAI_BASE, | |
1326 | .reg_ofs_cur = AFE_DAI_CUR, | |
1327 | .fs_reg = AFE_DAC_CON2, | |
1328 | .fs_shift = 30, | |
1329 | .fs_maskbit = 0x1, | |
1330 | .mono_reg = -1, | |
1331 | .mono_shift = -1, | |
1332 | .enable_reg = AFE_DAC_CON0, | |
1333 | .enable_shift = 17, | |
1334 | .hd_reg = AFE_MEMIF_HD_CON1, | |
1335 | .hd_shift = 20, | |
1336 | .agent_disable_reg = AUDIO_TOP_CON5, | |
1337 | .agent_disable_shift = 16, | |
1338 | .msb_reg = -1, | |
1339 | .msb_shift = -1, | |
1340 | }, | |
1341 | }; | |
1342 | ||
1343 | static const struct mtk_base_irq_data irq_data[MT2701_IRQ_ASYS_END] = { | |
1344 | { | |
1345 | .id = MT2701_IRQ_ASYS_IRQ1, | |
1346 | .irq_cnt_reg = ASYS_IRQ1_CON, | |
1347 | .irq_cnt_shift = 0, | |
1348 | .irq_cnt_maskbit = 0xffffff, | |
1349 | .irq_fs_reg = ASYS_IRQ1_CON, | |
1350 | .irq_fs_shift = 24, | |
1351 | .irq_fs_maskbit = 0x1f, | |
1352 | .irq_en_reg = ASYS_IRQ1_CON, | |
1353 | .irq_en_shift = 31, | |
1354 | .irq_clr_reg = ASYS_IRQ_CLR, | |
1355 | .irq_clr_shift = 0, | |
1356 | }, | |
1357 | { | |
1358 | .id = MT2701_IRQ_ASYS_IRQ2, | |
1359 | .irq_cnt_reg = ASYS_IRQ2_CON, | |
1360 | .irq_cnt_shift = 0, | |
1361 | .irq_cnt_maskbit = 0xffffff, | |
1362 | .irq_fs_reg = ASYS_IRQ2_CON, | |
1363 | .irq_fs_shift = 24, | |
1364 | .irq_fs_maskbit = 0x1f, | |
1365 | .irq_en_reg = ASYS_IRQ2_CON, | |
1366 | .irq_en_shift = 31, | |
1367 | .irq_clr_reg = ASYS_IRQ_CLR, | |
1368 | .irq_clr_shift = 1, | |
1369 | }, | |
1370 | { | |
1371 | .id = MT2701_IRQ_ASYS_IRQ3, | |
1372 | .irq_cnt_reg = ASYS_IRQ3_CON, | |
1373 | .irq_cnt_shift = 0, | |
1374 | .irq_cnt_maskbit = 0xffffff, | |
1375 | .irq_fs_reg = ASYS_IRQ3_CON, | |
1376 | .irq_fs_shift = 24, | |
1377 | .irq_fs_maskbit = 0x1f, | |
1378 | .irq_en_reg = ASYS_IRQ3_CON, | |
1379 | .irq_en_shift = 31, | |
1380 | .irq_clr_reg = ASYS_IRQ_CLR, | |
1381 | .irq_clr_shift = 2, | |
1382 | } | |
1383 | }; | |
1384 | ||
1385 | static const struct mt2701_i2s_data mt2701_i2s_data[MT2701_I2S_NUM][2] = { | |
1386 | { | |
1387 | { | |
1388 | .i2s_ctrl_reg = ASYS_I2SO1_CON, | |
1389 | .i2s_pwn_shift = 6, | |
1390 | .i2s_asrc_fs_shift = 0, | |
1391 | .i2s_asrc_fs_mask = 0x1f, | |
1392 | ||
1393 | }, | |
1394 | { | |
1395 | .i2s_ctrl_reg = ASYS_I2SIN1_CON, | |
1396 | .i2s_pwn_shift = 0, | |
1397 | .i2s_asrc_fs_shift = 0, | |
1398 | .i2s_asrc_fs_mask = 0x1f, | |
1399 | ||
1400 | }, | |
1401 | }, | |
1402 | { | |
1403 | { | |
1404 | .i2s_ctrl_reg = ASYS_I2SO2_CON, | |
1405 | .i2s_pwn_shift = 7, | |
1406 | .i2s_asrc_fs_shift = 5, | |
1407 | .i2s_asrc_fs_mask = 0x1f, | |
1408 | ||
1409 | }, | |
1410 | { | |
1411 | .i2s_ctrl_reg = ASYS_I2SIN2_CON, | |
1412 | .i2s_pwn_shift = 1, | |
1413 | .i2s_asrc_fs_shift = 5, | |
1414 | .i2s_asrc_fs_mask = 0x1f, | |
1415 | ||
1416 | }, | |
1417 | }, | |
1418 | { | |
1419 | { | |
1420 | .i2s_ctrl_reg = ASYS_I2SO3_CON, | |
1421 | .i2s_pwn_shift = 8, | |
1422 | .i2s_asrc_fs_shift = 10, | |
1423 | .i2s_asrc_fs_mask = 0x1f, | |
1424 | ||
1425 | }, | |
1426 | { | |
1427 | .i2s_ctrl_reg = ASYS_I2SIN3_CON, | |
1428 | .i2s_pwn_shift = 2, | |
1429 | .i2s_asrc_fs_shift = 10, | |
1430 | .i2s_asrc_fs_mask = 0x1f, | |
1431 | ||
1432 | }, | |
1433 | }, | |
1434 | { | |
1435 | { | |
1436 | .i2s_ctrl_reg = ASYS_I2SO4_CON, | |
1437 | .i2s_pwn_shift = 9, | |
1438 | .i2s_asrc_fs_shift = 15, | |
1439 | .i2s_asrc_fs_mask = 0x1f, | |
1440 | ||
1441 | }, | |
1442 | { | |
1443 | .i2s_ctrl_reg = ASYS_I2SIN4_CON, | |
1444 | .i2s_pwn_shift = 3, | |
1445 | .i2s_asrc_fs_shift = 15, | |
1446 | .i2s_asrc_fs_mask = 0x1f, | |
1447 | ||
1448 | }, | |
1449 | }, | |
1450 | }; | |
1451 | ||
1452 | static const struct regmap_config mt2701_afe_regmap_config = { | |
1453 | .reg_bits = 32, | |
1454 | .reg_stride = 4, | |
1455 | .val_bits = 32, | |
1456 | .max_register = AFE_END_ADDR, | |
1457 | .cache_type = REGCACHE_NONE, | |
1458 | }; | |
1459 | ||
1460 | static irqreturn_t mt2701_asys_isr(int irq_id, void *dev) | |
1461 | { | |
1462 | int id; | |
1463 | struct mtk_base_afe *afe = dev; | |
1464 | struct mtk_base_afe_memif *memif; | |
1465 | struct mtk_base_afe_irq *irq; | |
1466 | u32 status; | |
1467 | ||
1468 | regmap_read(afe->regmap, ASYS_IRQ_STATUS, &status); | |
1469 | regmap_write(afe->regmap, ASYS_IRQ_CLR, status); | |
1470 | ||
1471 | for (id = 0; id < MT2701_MEMIF_NUM; ++id) { | |
1472 | memif = &afe->memif[id]; | |
1473 | if (memif->irq_usage < 0) | |
1474 | continue; | |
1475 | irq = &afe->irqs[memif->irq_usage]; | |
1476 | if (status & 1 << (irq->irq_data->irq_clr_shift)) | |
1477 | snd_pcm_period_elapsed(memif->substream); | |
1478 | } | |
1479 | return IRQ_HANDLED; | |
1480 | } | |
1481 | ||
1482 | static int mt2701_afe_runtime_suspend(struct device *dev) | |
1483 | { | |
1484 | struct mtk_base_afe *afe = dev_get_drvdata(dev); | |
1485 | ||
1486 | mt2701_afe_disable_clock(afe); | |
1487 | return 0; | |
1488 | } | |
1489 | ||
1490 | static int mt2701_afe_runtime_resume(struct device *dev) | |
1491 | { | |
1492 | struct mtk_base_afe *afe = dev_get_drvdata(dev); | |
1493 | ||
1494 | return mt2701_afe_enable_clock(afe); | |
1495 | } | |
1496 | ||
1497 | static int mt2701_afe_pcm_dev_probe(struct platform_device *pdev) | |
1498 | { | |
1499 | struct mtk_base_afe *afe; | |
1500 | struct mt2701_afe_private *afe_priv; | |
1501 | struct resource *res; | |
1502 | struct device *dev; | |
1503 | int i, irq_id, ret; | |
1504 | ||
1505 | afe = devm_kzalloc(&pdev->dev, sizeof(*afe), GFP_KERNEL); | |
1506 | if (!afe) | |
1507 | return -ENOMEM; | |
1508 | afe->platform_priv = devm_kzalloc(&pdev->dev, sizeof(*afe_priv), | |
1509 | GFP_KERNEL); | |
1510 | if (!afe->platform_priv) | |
1511 | return -ENOMEM; | |
1512 | afe_priv = afe->platform_priv; | |
1513 | ||
1514 | afe->dev = &pdev->dev; | |
1515 | dev = afe->dev; | |
1516 | ||
1517 | irq_id = platform_get_irq_byname(pdev, "asys"); | |
1518 | if (irq_id < 0) { | |
1519 | dev_err(dev, "unable to get ASYS IRQ\n"); | |
1520 | return irq_id; | |
1521 | } | |
1522 | ||
1523 | ret = devm_request_irq(dev, irq_id, mt2701_asys_isr, | |
1524 | IRQF_TRIGGER_NONE, "asys-isr", (void *)afe); | |
1525 | if (ret) { | |
1526 | dev_err(dev, "could not request_irq for asys-isr\n"); | |
1527 | return ret; | |
1528 | } | |
1529 | ||
1530 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | |
1531 | ||
1532 | afe->base_addr = devm_ioremap_resource(&pdev->dev, res); | |
1533 | ||
1534 | if (IS_ERR(afe->base_addr)) | |
1535 | return PTR_ERR(afe->base_addr); | |
1536 | ||
1537 | afe->regmap = devm_regmap_init_mmio(&pdev->dev, afe->base_addr, | |
1538 | &mt2701_afe_regmap_config); | |
1539 | if (IS_ERR(afe->regmap)) | |
1540 | return PTR_ERR(afe->regmap); | |
1541 | ||
1542 | mutex_init(&afe->irq_alloc_lock); | |
1543 | ||
1544 | /* memif initialize */ | |
1545 | afe->memif_size = MT2701_MEMIF_NUM; | |
1546 | afe->memif = devm_kcalloc(dev, afe->memif_size, sizeof(*afe->memif), | |
1547 | GFP_KERNEL); | |
1548 | ||
1549 | if (!afe->memif) | |
1550 | return -ENOMEM; | |
1551 | ||
1552 | for (i = 0; i < afe->memif_size; i++) { | |
1553 | afe->memif[i].data = &memif_data[i]; | |
1554 | afe->memif[i].irq_usage = -1; | |
1555 | } | |
1556 | ||
1557 | /* irq initialize */ | |
1558 | afe->irqs_size = MT2701_IRQ_ASYS_END; | |
1559 | afe->irqs = devm_kcalloc(dev, afe->irqs_size, sizeof(*afe->irqs), | |
1560 | GFP_KERNEL); | |
1561 | ||
1562 | if (!afe->irqs) | |
1563 | return -ENOMEM; | |
1564 | ||
1565 | for (i = 0; i < afe->irqs_size; i++) | |
1566 | afe->irqs[i].irq_data = &irq_data[i]; | |
1567 | ||
1568 | /* I2S initialize */ | |
1569 | for (i = 0; i < MT2701_I2S_NUM; i++) { | |
1570 | afe_priv->i2s_path[i].i2s_data[I2S_OUT] | |
1571 | = &mt2701_i2s_data[i][I2S_OUT]; | |
1572 | afe_priv->i2s_path[i].i2s_data[I2S_IN] | |
1573 | = &mt2701_i2s_data[i][I2S_IN]; | |
1574 | } | |
1575 | ||
1576 | afe->mtk_afe_hardware = &mt2701_afe_hardware; | |
1577 | afe->memif_fs = mt2701_memif_fs; | |
1578 | afe->irq_fs = mt2701_irq_fs; | |
1579 | ||
1580 | afe->reg_back_up_list = mt2701_afe_backup_list; | |
1581 | afe->reg_back_up_list_num = ARRAY_SIZE(mt2701_afe_backup_list); | |
1582 | afe->runtime_resume = mt2701_afe_runtime_resume; | |
1583 | afe->runtime_suspend = mt2701_afe_runtime_suspend; | |
1584 | ||
1585 | /* initial audio related clock */ | |
1586 | ret = mt2701_init_clock(afe); | |
1587 | if (ret) { | |
1588 | dev_err(dev, "init clock error\n"); | |
1589 | return ret; | |
1590 | } | |
1591 | ||
1592 | platform_set_drvdata(pdev, afe); | |
1593 | pm_runtime_enable(&pdev->dev); | |
1594 | if (!pm_runtime_enabled(&pdev->dev)) | |
1595 | goto err_pm_disable; | |
1596 | pm_runtime_get_sync(&pdev->dev); | |
1597 | ||
1598 | ret = snd_soc_register_platform(&pdev->dev, &mtk_afe_pcm_platform); | |
1599 | if (ret) { | |
1600 | dev_warn(dev, "err_platform\n"); | |
1601 | goto err_platform; | |
1602 | } | |
1603 | ||
1604 | ret = snd_soc_register_component(&pdev->dev, | |
1605 | &mt2701_afe_pcm_dai_component, | |
1606 | mt2701_afe_pcm_dais, | |
1607 | ARRAY_SIZE(mt2701_afe_pcm_dais)); | |
1608 | if (ret) { | |
1609 | dev_warn(dev, "err_dai_component\n"); | |
1610 | goto err_dai_component; | |
1611 | } | |
1612 | ||
1613 | mt2701_afe_runtime_resume(&pdev->dev); | |
1614 | ||
1615 | return 0; | |
1616 | ||
1617 | err_dai_component: | |
1618 | snd_soc_unregister_component(&pdev->dev); | |
1619 | ||
1620 | err_platform: | |
1621 | snd_soc_unregister_platform(&pdev->dev); | |
1622 | ||
1623 | err_pm_disable: | |
1624 | pm_runtime_disable(&pdev->dev); | |
1625 | ||
1626 | return ret; | |
1627 | } | |
1628 | ||
1629 | static int mt2701_afe_pcm_dev_remove(struct platform_device *pdev) | |
1630 | { | |
1631 | struct mtk_base_afe *afe = platform_get_drvdata(pdev); | |
1632 | ||
1633 | pm_runtime_disable(&pdev->dev); | |
1634 | if (!pm_runtime_status_suspended(&pdev->dev)) | |
1635 | mt2701_afe_runtime_suspend(&pdev->dev); | |
1636 | pm_runtime_put_sync(&pdev->dev); | |
1637 | ||
1638 | snd_soc_unregister_component(&pdev->dev); | |
1639 | snd_soc_unregister_platform(&pdev->dev); | |
1640 | /* disable afe clock */ | |
1641 | mt2701_afe_disable_clock(afe); | |
1642 | return 0; | |
1643 | } | |
1644 | ||
1645 | static const struct of_device_id mt2701_afe_pcm_dt_match[] = { | |
1646 | { .compatible = "mediatek,mt2701-audio", }, | |
1647 | {}, | |
1648 | }; | |
1649 | MODULE_DEVICE_TABLE(of, mt2701_afe_pcm_dt_match); | |
1650 | ||
1651 | static const struct dev_pm_ops mt2701_afe_pm_ops = { | |
1652 | SET_RUNTIME_PM_OPS(mt2701_afe_runtime_suspend, | |
1653 | mt2701_afe_runtime_resume, NULL) | |
1654 | }; | |
1655 | ||
1656 | static struct platform_driver mt2701_afe_pcm_driver = { | |
1657 | .driver = { | |
1658 | .name = "mt2701-audio", | |
1659 | .of_match_table = mt2701_afe_pcm_dt_match, | |
1660 | #ifdef CONFIG_PM | |
1661 | .pm = &mt2701_afe_pm_ops, | |
1662 | #endif | |
1663 | }, | |
1664 | .probe = mt2701_afe_pcm_dev_probe, | |
1665 | .remove = mt2701_afe_pcm_dev_remove, | |
1666 | }; | |
1667 | ||
1668 | module_platform_driver(mt2701_afe_pcm_driver); | |
1669 | ||
1670 | MODULE_DESCRIPTION("Mediatek ALSA SoC AFE platform driver for 2701"); | |
1671 | MODULE_AUTHOR("Garlic Tseng <garlic.tseng@mediatek.com>"); | |
1672 | MODULE_LICENSE("GPL v2"); | |
1673 |