File Index
Files and directories
Sign in
FILE

mt8188-dai-dmic.c

File preview with syntax highlighting.

linux-6.19.14/sound/soc/mediatek/mt8188/mt8188-dai-dmic.c C
  1// SPDX-License-Identifier: GPL-2.0
  2/*
  3 * MediaTek ALSA SoC Audio DAI DMIC I/F Control
  4 *
  5 * Copyright (c) 2020 MediaTek Inc.
  6 * Author: Bicycle Tsai <bicycle.tsai@mediatek.com>
  7 *         Trevor Wu <trevor.wu@mediatek.com>
  8 *         Parker Yang <parker.yang@mediatek.com>
  9 */
 10
 11#include <linux/delay.h>
 12#include <linux/pm_runtime.h>
 13#include <linux/regmap.h>
 14#include <sound/pcm_params.h>
 15#include "mt8188-afe-clk.h"
 16#include "mt8188-afe-common.h"
 17#include "mt8188-reg.h"
 18
 19/* DMIC HW Gain configuration maximum value. */
 20#define DMIC_GAIN_MAX_STEP	GENMASK(19, 0)
 21#define DMIC_GAIN_MAX_PER_STEP	GENMASK(7, 0)
 22#define DMIC_GAIN_MAX_TARGET	GENMASK(27, 0)
 23#define DMIC_GAIN_MAX_CURRENT	GENMASK(27, 0)
 24
 25#define CLK_PHASE_SEL_CH1 0
 26#define CLK_PHASE_SEL_CH2 ((CLK_PHASE_SEL_CH1) + 4)
 27
 28#define DMIC1_SRC_SEL 0
 29#define DMIC2_SRC_SEL 0
 30#define DMIC3_SRC_SEL 2
 31#define DMIC4_SRC_SEL 0
 32#define DMIC5_SRC_SEL 4
 33#define DMIC6_SRC_SEL 0
 34#define DMIC7_SRC_SEL 6
 35#define DMIC8_SRC_SEL 0
 36
 37enum {
 38	SUPPLY_SEQ_DMIC_GAIN,
 39	SUPPLY_SEQ_DMIC_CK,
 40};
 41
 42enum {
 43	DMIC0,
 44	DMIC1,
 45	DMIC2,
 46	DMIC3,
 47	DMIC_NUM,
 48};
 49
 50struct mtk_dai_dmic_ctrl_reg {
 51	unsigned int con0;
 52};
 53
 54struct mtk_dai_dmic_hw_gain_ctrl_reg {
 55	unsigned int bypass;
 56	unsigned int con0;
 57};
 58
 59struct mtk_dai_dmic_priv {
 60	unsigned int gain_on[DMIC_NUM];
 61	unsigned int channels;
 62	bool hires_required;
 63};
 64
 65static const struct mtk_dai_dmic_ctrl_reg dmic_ctrl_regs[DMIC_NUM] = {
 66	[DMIC0] = {
 67		.con0 = AFE_DMIC0_UL_SRC_CON0,
 68	},
 69	[DMIC1] = {
 70		.con0 = AFE_DMIC1_UL_SRC_CON0,
 71	},
 72	[DMIC2] = {
 73		.con0 = AFE_DMIC2_UL_SRC_CON0,
 74	},
 75	[DMIC3] = {
 76		.con0 = AFE_DMIC3_UL_SRC_CON0,
 77	},
 78};
 79
 80static const struct mtk_dai_dmic_ctrl_reg *get_dmic_ctrl_reg(int id)
 81{
 82	if (id < 0 || id >= DMIC_NUM)
 83		return NULL;
 84
 85	return &dmic_ctrl_regs[id];
 86}
 87
 88static const struct mtk_dai_dmic_hw_gain_ctrl_reg
 89	dmic_hw_gain_ctrl_regs[DMIC_NUM] = {
 90	[DMIC0] = {
 91		.bypass = DMIC_BYPASS_HW_GAIN,
 92		.con0 = DMIC_GAIN1_CON0,
 93	},
 94	[DMIC1] = {
 95		.bypass = DMIC_BYPASS_HW_GAIN,
 96		.con0 = DMIC_GAIN2_CON0,
 97	},
 98	[DMIC2] = {
 99		.bypass = DMIC_BYPASS_HW_GAIN,
100		.con0 = DMIC_GAIN3_CON0,
101	},
102	[DMIC3] = {
103		.bypass = DMIC_BYPASS_HW_GAIN,
104		.con0 = DMIC_GAIN4_CON0,
105	},
106};
107
108static const struct mtk_dai_dmic_hw_gain_ctrl_reg
109	*get_dmic_hw_gain_ctrl_reg(struct mtk_base_afe *afe, int id)
110{
111	if ((id < 0) || (id >= DMIC_NUM)) {
112		dev_dbg(afe->dev, "%s invalid id\n", __func__);
113		return NULL;
114	}
115
116	return &dmic_hw_gain_ctrl_regs[id];
117}
118
119static void mtk_dai_dmic_hw_gain_bypass(struct mtk_base_afe *afe,
120					unsigned int id, bool bypass)
121{
122	const struct mtk_dai_dmic_hw_gain_ctrl_reg *reg;
123	unsigned int msk;
124
125	reg = get_dmic_hw_gain_ctrl_reg(afe, id);
126	if (!reg)
127		return;
128
129	switch (id) {
130	case DMIC0:
131		msk = DMIC_BYPASS_HW_GAIN_DMIC1_BYPASS;
132		break;
133	case DMIC1:
134		msk = DMIC_BYPASS_HW_GAIN_DMIC2_BYPASS;
135		break;
136	case DMIC2:
137		msk = DMIC_BYPASS_HW_GAIN_DMIC3_BYPASS;
138		break;
139	case DMIC3:
140		msk = DMIC_BYPASS_HW_GAIN_DMIC4_BYPASS;
141		break;
142	default:
143		return;
144	}
145
146	if (bypass)
147		regmap_set_bits(afe->regmap, reg->bypass, msk);
148	else
149		regmap_clear_bits(afe->regmap, reg->bypass, msk);
150}
151
152static void mtk_dai_dmic_hw_gain_on(struct mtk_base_afe *afe, unsigned int id,
153				    bool on)
154{
155	const struct mtk_dai_dmic_hw_gain_ctrl_reg *reg = get_dmic_hw_gain_ctrl_reg(afe, id);
156
157	if (!reg)
158		return;
159
160	if (on)
161		regmap_set_bits(afe->regmap, reg->con0, DMIC_GAIN_CON0_GAIN_ON);
162	else
163		regmap_clear_bits(afe->regmap, reg->con0, DMIC_GAIN_CON0_GAIN_ON);
164}
165
166static const struct reg_sequence mtk_dai_dmic_iir_coeff_reg_defaults[] = {
167	{ AFE_DMIC0_IIR_COEF_02_01, 0x00000000 },
168	{ AFE_DMIC0_IIR_COEF_04_03, 0x00003FB8 },
169	{ AFE_DMIC0_IIR_COEF_06_05, 0x3FB80000 },
170	{ AFE_DMIC0_IIR_COEF_08_07, 0x3FB80000 },
171	{ AFE_DMIC0_IIR_COEF_10_09, 0x0000C048 },
172	{ AFE_DMIC1_IIR_COEF_02_01, 0x00000000 },
173	{ AFE_DMIC1_IIR_COEF_04_03, 0x00003FB8 },
174	{ AFE_DMIC1_IIR_COEF_06_05, 0x3FB80000 },
175	{ AFE_DMIC1_IIR_COEF_08_07, 0x3FB80000 },
176	{ AFE_DMIC1_IIR_COEF_10_09, 0x0000C048 },
177	{ AFE_DMIC2_IIR_COEF_02_01, 0x00000000 },
178	{ AFE_DMIC2_IIR_COEF_04_03, 0x00003FB8 },
179	{ AFE_DMIC2_IIR_COEF_06_05, 0x3FB80000 },
180	{ AFE_DMIC2_IIR_COEF_08_07, 0x3FB80000 },
181	{ AFE_DMIC2_IIR_COEF_10_09, 0x0000C048 },
182	{ AFE_DMIC3_IIR_COEF_02_01, 0x00000000 },
183	{ AFE_DMIC3_IIR_COEF_04_03, 0x00003FB8 },
184	{ AFE_DMIC3_IIR_COEF_06_05, 0x3FB80000 },
185	{ AFE_DMIC3_IIR_COEF_08_07, 0x3FB80000 },
186	{ AFE_DMIC3_IIR_COEF_10_09, 0x0000C048 },
187};
188
189static int mtk_dai_dmic_load_iir_coeff_table(struct mtk_base_afe *afe)
190{
191	return regmap_multi_reg_write(afe->regmap,
192				      mtk_dai_dmic_iir_coeff_reg_defaults,
193				      ARRAY_SIZE(mtk_dai_dmic_iir_coeff_reg_defaults));
194}
195
196static int mtk_dai_dmic_configure_array(struct snd_soc_dai *dai)
197{
198	struct mtk_base_afe *afe = snd_soc_dai_get_drvdata(dai);
199	const u32 mask = PWR2_TOP_CON_DMIC8_SRC_SEL_MASK |
200			 PWR2_TOP_CON_DMIC7_SRC_SEL_MASK |
201			 PWR2_TOP_CON_DMIC6_SRC_SEL_MASK |
202			 PWR2_TOP_CON_DMIC5_SRC_SEL_MASK |
203			 PWR2_TOP_CON_DMIC4_SRC_SEL_MASK |
204			 PWR2_TOP_CON_DMIC3_SRC_SEL_MASK |
205			 PWR2_TOP_CON_DMIC2_SRC_SEL_MASK |
206			 PWR2_TOP_CON_DMIC1_SRC_SEL_MASK;
207	const u32 val = PWR2_TOP_CON_DMIC8_SRC_SEL_VAL(DMIC8_SRC_SEL) |
208			PWR2_TOP_CON_DMIC7_SRC_SEL_VAL(DMIC7_SRC_SEL) |
209			PWR2_TOP_CON_DMIC6_SRC_SEL_VAL(DMIC6_SRC_SEL) |
210			PWR2_TOP_CON_DMIC5_SRC_SEL_VAL(DMIC5_SRC_SEL) |
211			PWR2_TOP_CON_DMIC4_SRC_SEL_VAL(DMIC4_SRC_SEL) |
212			PWR2_TOP_CON_DMIC3_SRC_SEL_VAL(DMIC3_SRC_SEL) |
213			PWR2_TOP_CON_DMIC2_SRC_SEL_VAL(DMIC2_SRC_SEL) |
214			PWR2_TOP_CON_DMIC1_SRC_SEL_VAL(DMIC1_SRC_SEL);
215
216	return regmap_update_bits(afe->regmap, PWR2_TOP_CON0, mask, val);
217}
218
219/* This function assumes that the caller checked that channels is valid */
220static u8 mtk_dmic_channels_to_dmic_number(unsigned int channels)
221{
222	switch (channels) {
223	case 1:
224		return DMIC0;
225	case 2:
226		return DMIC1;
227	case 3:
228		return DMIC2;
229	case 4:
230	default:
231		return DMIC3;
232	}
233}
234
235static void mtk_dai_dmic_hw_gain_enable(struct mtk_base_afe *afe,
236					unsigned int channels, bool enable)
237{
238	struct mt8188_afe_private *afe_priv = afe->platform_priv;
239	struct mtk_dai_dmic_priv *dmic_priv = afe_priv->dai_priv[MT8188_AFE_IO_DMIC_IN];
240	u8 dmic_num;
241	int i;
242
243	dmic_num = mtk_dmic_channels_to_dmic_number(channels);
244	for (i = dmic_num; i >= DMIC0; i--) {
245		if (enable && dmic_priv->gain_on[i]) {
246			mtk_dai_dmic_hw_gain_bypass(afe, i, false);
247			mtk_dai_dmic_hw_gain_on(afe, i, true);
248		} else {
249			mtk_dai_dmic_hw_gain_on(afe, i, false);
250			mtk_dai_dmic_hw_gain_bypass(afe, i, true);
251		}
252	}
253}
254
255static int mtk_dmic_gain_event(struct snd_soc_dapm_widget *w,
256			       struct snd_kcontrol *kcontrol,
257			       int event)
258{
259	struct snd_soc_component *cmpnt = snd_soc_dapm_to_component(w->dapm);
260	struct mtk_base_afe *afe = snd_soc_component_get_drvdata(cmpnt);
261	struct mt8188_afe_private *afe_priv = afe->platform_priv;
262	struct mtk_dai_dmic_priv *dmic_priv = afe_priv->dai_priv[MT8188_AFE_IO_DMIC_IN];
263	unsigned int channels = dmic_priv->channels;
264
265	dev_dbg(afe->dev, "%s(), name %s, event 0x%x\n",
266		__func__, w->name, event);
267
268	if (!channels)
269		return -EINVAL;
270
271	switch (event) {
272	case SND_SOC_DAPM_PRE_PMU:
273		mtk_dai_dmic_hw_gain_enable(afe, channels, true);
274		break;
275	case SND_SOC_DAPM_POST_PMD:
276		mtk_dai_dmic_hw_gain_enable(afe, channels, false);
277		break;
278	default:
279		break;
280	}
281
282	return 0;
283}
284
285static int mtk_dmic_event(struct snd_soc_dapm_widget *w,
286			  struct snd_kcontrol *kcontrol,
287			  int event)
288{
289	struct snd_soc_component *cmpnt = snd_soc_dapm_to_component(w->dapm);
290	struct mtk_base_afe *afe = snd_soc_component_get_drvdata(cmpnt);
291	struct mt8188_afe_private *afe_priv = afe->platform_priv;
292	struct mtk_dai_dmic_priv *dmic_priv = afe_priv->dai_priv[MT8188_AFE_IO_DMIC_IN];
293	const struct mtk_dai_dmic_ctrl_reg *reg = NULL;
294	unsigned int channels = dmic_priv->channels;
295	unsigned int msk;
296	u8 dmic_num;
297	int i;
298
299	dev_dbg(afe->dev, "%s(), name %s, event 0x%x\n",
300		__func__, w->name, event);
301
302	if (!channels)
303		return -EINVAL;
304
305	dmic_num = mtk_dmic_channels_to_dmic_number(channels);
306
307	switch (event) {
308	case SND_SOC_DAPM_PRE_PMU:
309		/* request fifo soft rst */
310		msk = 0;
311		for (i = dmic_num; i >= DMIC0; i--)
312			msk |= PWR2_TOP_CON1_DMIC_FIFO_SOFT_RST_EN(i);
313
314		regmap_set_bits(afe->regmap, PWR2_TOP_CON1, msk);
315
316		msk = AFE_DMIC_UL_SRC_CON0_UL_MODE_3P25M_CH1_CTL |
317		      AFE_DMIC_UL_SRC_CON0_UL_MODE_3P25M_CH2_CTL |
318		      AFE_DMIC_UL_SRC_CON0_UL_SDM_3_LEVEL_CTL |
319		      AFE_DMIC_UL_SRC_CON0_UL_IIR_ON_TMP_CTL;
320
321		for (i = dmic_num; i >= DMIC0; i--) {
322			reg = get_dmic_ctrl_reg(i);
323			if (reg)
324				regmap_set_bits(afe->regmap, reg->con0, msk);
325		}
326		break;
327	case SND_SOC_DAPM_POST_PMU:
328		msk = AFE_DMIC_UL_SRC_CON0_UL_SRC_ON_TMP_CTL;
329
330		for (i = dmic_num; i >= DMIC0; i--) {
331			reg = get_dmic_ctrl_reg(i);
332			if (reg)
333				regmap_set_bits(afe->regmap, reg->con0, msk);
334		}
335
336		if (dmic_priv->hires_required) {
337			mt8188_afe_enable_clk(afe, afe_priv->clk[MT8188_CLK_AUD_DMIC_HIRES1]);
338			mt8188_afe_enable_clk(afe, afe_priv->clk[MT8188_CLK_AUD_DMIC_HIRES2]);
339			mt8188_afe_enable_clk(afe, afe_priv->clk[MT8188_CLK_AUD_DMIC_HIRES3]);
340			mt8188_afe_enable_clk(afe, afe_priv->clk[MT8188_CLK_AUD_DMIC_HIRES4]);
341		}
342
343		mt8188_afe_enable_clk(afe, afe_priv->clk[MT8188_CLK_AUD_AFE_DMIC1]);
344		mt8188_afe_enable_clk(afe, afe_priv->clk[MT8188_CLK_AUD_AFE_DMIC2]);
345		mt8188_afe_enable_clk(afe, afe_priv->clk[MT8188_CLK_AUD_AFE_DMIC3]);
346		mt8188_afe_enable_clk(afe, afe_priv->clk[MT8188_CLK_AUD_AFE_DMIC4]);
347
348		/* release fifo soft rst */
349		msk = 0;
350		for (i = dmic_num; i >= DMIC0; i--)
351			msk |= PWR2_TOP_CON1_DMIC_FIFO_SOFT_RST_EN(i);
352
353		regmap_clear_bits(afe->regmap, PWR2_TOP_CON1, msk);
354		break;
355	case SND_SOC_DAPM_PRE_PMD:
356		msk = AFE_DMIC_UL_SRC_CON0_UL_MODE_3P25M_CH1_CTL |
357		      AFE_DMIC_UL_SRC_CON0_UL_MODE_3P25M_CH2_CTL |
358		      AFE_DMIC_UL_SRC_CON0_UL_SRC_ON_TMP_CTL |
359		      AFE_DMIC_UL_SRC_CON0_UL_IIR_ON_TMP_CTL |
360		      AFE_DMIC_UL_SRC_CON0_UL_SDM_3_LEVEL_CTL;
361
362		for (i = dmic_num; i >= DMIC0; i--) {
363			reg = get_dmic_ctrl_reg(i);
364			if (reg)
365				regmap_set_bits(afe->regmap, reg->con0, msk);
366		}
367		break;
368	case SND_SOC_DAPM_POST_PMD:
369		/* should delayed 1/fs(smallest is 8k) = 125us before afe off */
370		usleep_range(125, 126);
371
372		mt8188_afe_disable_clk(afe, afe_priv->clk[MT8188_CLK_AUD_AFE_DMIC1]);
373		mt8188_afe_disable_clk(afe, afe_priv->clk[MT8188_CLK_AUD_AFE_DMIC2]);
374		mt8188_afe_disable_clk(afe, afe_priv->clk[MT8188_CLK_AUD_AFE_DMIC3]);
375		mt8188_afe_disable_clk(afe, afe_priv->clk[MT8188_CLK_AUD_AFE_DMIC4]);
376
377		if (dmic_priv->hires_required) {
378			mt8188_afe_disable_clk(afe, afe_priv->clk[MT8188_CLK_AUD_DMIC_HIRES1]);
379			mt8188_afe_disable_clk(afe, afe_priv->clk[MT8188_CLK_AUD_DMIC_HIRES2]);
380			mt8188_afe_disable_clk(afe, afe_priv->clk[MT8188_CLK_AUD_DMIC_HIRES3]);
381			mt8188_afe_disable_clk(afe, afe_priv->clk[MT8188_CLK_AUD_DMIC_HIRES4]);
382		}
383		break;
384	default:
385		break;
386	}
387
388	return 0;
389}
390
391static int mtk_dai_dmic_hw_params(struct snd_pcm_substream *substream,
392				  struct snd_pcm_hw_params *params,
393				  struct snd_soc_dai *dai)
394{
395	struct mtk_base_afe *afe = snd_soc_dai_get_drvdata(dai);
396	struct mt8188_afe_private *afe_priv = afe->platform_priv;
397	struct mtk_dai_dmic_priv *dmic_priv = afe_priv->dai_priv[MT8188_AFE_IO_DMIC_IN];
398	unsigned int rate = params_rate(params);
399	unsigned int channels = params_channels(params);
400	const struct mtk_dai_dmic_ctrl_reg *reg = NULL;
401	u32 val = AFE_DMIC_UL_SRC_CON0_UL_PHASE_SEL_CH1(CLK_PHASE_SEL_CH1) |
402		  AFE_DMIC_UL_SRC_CON0_UL_PHASE_SEL_CH2(CLK_PHASE_SEL_CH2) |
403		  AFE_DMIC_UL_SRC_CON0_UL_IIR_MODE_CTL(0);
404	const u32 msk = AFE_DMIC_UL_SRC_CON0_UL_TWO_WIRE_MODE_CTL |
405			AFE_DMIC_UL_SRC_CON0_UL_PHASE_SEL_MASK |
406			AFE_DMIC_UL_SRC_CON0_UL_IIR_MODE_CTL_MASK |
407			AFE_DMIC_UL_VOICE_MODE_MASK;
408	u8 dmic_num;
409	int ret;
410	int i;
411
412	if (!channels || channels > 8)
413		return -EINVAL;
414
415	ret = mtk_dai_dmic_configure_array(dai);
416	if (ret < 0)
417		return ret;
418
419	ret = mtk_dai_dmic_load_iir_coeff_table(afe);
420	if (ret < 0)
421		return ret;
422
423	switch (rate) {
424	case 96000:
425		val |= AFE_DMIC_UL_CON0_VOCIE_MODE_96K;
426		dmic_priv->hires_required = 1;
427		break;
428	case 48000:
429		val |= AFE_DMIC_UL_CON0_VOCIE_MODE_48K;
430		dmic_priv->hires_required = 0;
431		break;
432	case 32000:
433		val |= AFE_DMIC_UL_CON0_VOCIE_MODE_32K;
434		dmic_priv->hires_required = 0;
435		break;
436	case 16000:
437		val |= AFE_DMIC_UL_CON0_VOCIE_MODE_16K;
438		dmic_priv->hires_required = 0;
439		break;
440	case 8000:
441		val |= AFE_DMIC_UL_CON0_VOCIE_MODE_8K;
442		dmic_priv->hires_required = 0;
443		break;
444	default:
445		dev_dbg(afe->dev, "%s invalid rate %u, use 48000Hz\n", __func__, rate);
446		val |= AFE_DMIC_UL_CON0_VOCIE_MODE_48K;
447		dmic_priv->hires_required = 0;
448		break;
449	}
450
451	dmic_num = mtk_dmic_channels_to_dmic_number(channels);
452	for (i = dmic_num; i >= DMIC0; i--) {
453		reg = get_dmic_ctrl_reg(i);
454		if (reg) {
455			ret = regmap_update_bits(afe->regmap, reg->con0, msk, val);
456			if (ret < 0)
457				return ret;
458		}
459	}
460
461	dmic_priv->channels = channels;
462
463	return 0;
464}
465
466static const struct snd_soc_dai_ops mtk_dai_dmic_ops = {
467	.hw_params	= mtk_dai_dmic_hw_params,
468};
469
470#define MTK_DMIC_RATES (SNDRV_PCM_RATE_8000 |\
471		       SNDRV_PCM_RATE_16000 |\
472		       SNDRV_PCM_RATE_32000 |\
473		       SNDRV_PCM_RATE_48000 |\
474		       SNDRV_PCM_RATE_96000)
475
476#define MTK_DMIC_FORMATS (SNDRV_PCM_FMTBIT_S16_LE |\
477			 SNDRV_PCM_FMTBIT_S32_LE)
478
479static struct snd_soc_dai_driver mtk_dai_dmic_driver[] = {
480	{
481		.name = "DMIC",
482		.id = MT8188_AFE_IO_DMIC_IN,
483		.capture = {
484			.stream_name = "DMIC Capture",
485			.channels_min = 1,
486			.channels_max = 8,
487			.rates = MTK_DMIC_RATES,
488			.formats = MTK_DMIC_FORMATS,
489		},
490		.ops = &mtk_dai_dmic_ops,
491	},
492};
493
494static const struct snd_soc_dapm_widget mtk_dai_dmic_widgets[] = {
495	SND_SOC_DAPM_MIXER("I004", SND_SOC_NOPM, 0, 0, NULL, 0),
496	SND_SOC_DAPM_MIXER("I005", SND_SOC_NOPM, 0, 0, NULL, 0),
497	SND_SOC_DAPM_MIXER("I006", SND_SOC_NOPM, 0, 0, NULL, 0),
498	SND_SOC_DAPM_MIXER("I007", SND_SOC_NOPM, 0, 0, NULL, 0),
499	SND_SOC_DAPM_MIXER("I008", SND_SOC_NOPM, 0, 0, NULL, 0),
500	SND_SOC_DAPM_MIXER("I009", SND_SOC_NOPM, 0, 0, NULL, 0),
501	SND_SOC_DAPM_MIXER("I010", SND_SOC_NOPM, 0, 0, NULL, 0),
502	SND_SOC_DAPM_MIXER("I011", SND_SOC_NOPM, 0, 0, NULL, 0),
503
504	SND_SOC_DAPM_SUPPLY_S("DMIC_GAIN_ON", SUPPLY_SEQ_DMIC_GAIN,
505			      SND_SOC_NOPM, 0, 0,
506			      mtk_dmic_gain_event,
507			      SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
508	SND_SOC_DAPM_SUPPLY_S("DMIC_CK_ON", SUPPLY_SEQ_DMIC_CK,
509			      PWR2_TOP_CON1,
510			      PWR2_TOP_CON1_DMIC_CKDIV_ON_SHIFT, 0,
511			      mtk_dmic_event,
512			      SND_SOC_DAPM_PRE_POST_PMU |
513			      SND_SOC_DAPM_PRE_POST_PMD),
514	SND_SOC_DAPM_INPUT("DMIC_INPUT"),
515};
516
517static const struct snd_soc_dapm_route mtk_dai_dmic_routes[] = {
518	{"I004", NULL, "DMIC Capture"},
519	{"I005", NULL, "DMIC Capture"},
520	{"I006", NULL, "DMIC Capture"},
521	{"I007", NULL, "DMIC Capture"},
522	{"I008", NULL, "DMIC Capture"},
523	{"I009", NULL, "DMIC Capture"},
524	{"I010", NULL, "DMIC Capture"},
525	{"I011", NULL, "DMIC Capture"},
526	{"DMIC Capture", NULL, "DMIC_CK_ON"},
527	{"DMIC Capture", NULL, "DMIC_GAIN_ON"},
528	{"DMIC Capture", NULL, "DMIC_INPUT"},
529};
530
531static const char * const mt8188_dmic_gain_enable_text[] = {
532	"Bypass", "Connect",
533};
534
535static SOC_ENUM_SINGLE_EXT_DECL(dmic_gain_on_enum,
536				mt8188_dmic_gain_enable_text);
537
538static int mtk_dai_dmic_hw_gain_ctrl_put(struct snd_kcontrol *kcontrol,
539					 struct snd_ctl_elem_value *ucontrol)
540{
541	struct snd_soc_component *component = snd_kcontrol_chip(kcontrol);
542	struct soc_enum *e = (struct soc_enum *)kcontrol->private_value;
543	struct mtk_base_afe *afe = snd_soc_component_get_drvdata(component);
544	struct mt8188_afe_private *afe_priv = afe->platform_priv;
545	struct mtk_dai_dmic_priv *dmic_priv = afe_priv->dai_priv[MT8188_AFE_IO_DMIC_IN];
546	unsigned int source = ucontrol->value.enumerated.item[0];
547	unsigned int *cached;
548
549	if (source >= e->items)
550		return -EINVAL;
551
552	if (!strcmp(kcontrol->id.name, "DMIC1_HW_GAIN_EN"))
553		cached = &dmic_priv->gain_on[0];
554	else if (!strcmp(kcontrol->id.name, "DMIC2_HW_GAIN_EN"))
555		cached = &dmic_priv->gain_on[1];
556	else if (!strcmp(kcontrol->id.name, "DMIC3_HW_GAIN_EN"))
557		cached = &dmic_priv->gain_on[2];
558	else if (!strcmp(kcontrol->id.name, "DMIC4_HW_GAIN_EN"))
559		cached = &dmic_priv->gain_on[3];
560	else
561		return -EINVAL;
562
563	if (source == *cached)
564		return 0;
565
566	*cached = source;
567	return 1;
568}
569
570static int mtk_dai_dmic_hw_gain_ctrl_get(struct snd_kcontrol *kcontrol,
571					 struct snd_ctl_elem_value *ucontrol)
572{
573	struct snd_soc_component *component = snd_kcontrol_chip(kcontrol);
574	struct mtk_base_afe *afe = snd_soc_component_get_drvdata(component);
575	struct mt8188_afe_private *afe_priv = afe->platform_priv;
576	struct mtk_dai_dmic_priv *dmic_priv = afe_priv->dai_priv[MT8188_AFE_IO_DMIC_IN];
577	unsigned int val;
578
579	if (!strcmp(kcontrol->id.name, "DMIC1_HW_GAIN_EN"))
580		val = dmic_priv->gain_on[0];
581	else if (!strcmp(kcontrol->id.name, "DMIC2_HW_GAIN_EN"))
582		val = dmic_priv->gain_on[1];
583	else if (!strcmp(kcontrol->id.name, "DMIC3_HW_GAIN_EN"))
584		val = dmic_priv->gain_on[2];
585	else if (!strcmp(kcontrol->id.name, "DMIC4_HW_GAIN_EN"))
586		val = dmic_priv->gain_on[3];
587	else
588		return -EINVAL;
589
590	ucontrol->value.enumerated.item[0] = val;
591	return 0;
592}
593
594static const struct snd_kcontrol_new mtk_dai_dmic_controls[] = {
595	SOC_ENUM_EXT("DMIC1_HW_GAIN_EN", dmic_gain_on_enum,
596		     mtk_dai_dmic_hw_gain_ctrl_get,
597		     mtk_dai_dmic_hw_gain_ctrl_put),
598	SOC_ENUM_EXT("DMIC2_HW_GAIN_EN", dmic_gain_on_enum,
599		     mtk_dai_dmic_hw_gain_ctrl_get,
600		     mtk_dai_dmic_hw_gain_ctrl_put),
601	SOC_ENUM_EXT("DMIC3_HW_GAIN_EN", dmic_gain_on_enum,
602		     mtk_dai_dmic_hw_gain_ctrl_get,
603		     mtk_dai_dmic_hw_gain_ctrl_put),
604	SOC_ENUM_EXT("DMIC4_HW_GAIN_EN", dmic_gain_on_enum,
605		     mtk_dai_dmic_hw_gain_ctrl_get,
606		     mtk_dai_dmic_hw_gain_ctrl_put),
607	SOC_SINGLE("DMIC1_HW_GAIN_TARGET", DMIC_GAIN1_CON1,
608		   0, DMIC_GAIN_MAX_TARGET, 0),
609	SOC_SINGLE("DMIC2_HW_GAIN_TARGET", DMIC_GAIN2_CON1,
610		   0, DMIC_GAIN_MAX_TARGET, 0),
611	SOC_SINGLE("DMIC3_HW_GAIN_TARGET", DMIC_GAIN3_CON1,
612		   0, DMIC_GAIN_MAX_TARGET, 0),
613	SOC_SINGLE("DMIC4_HW_GAIN_TARGET", DMIC_GAIN4_CON1,
614		   0, DMIC_GAIN_MAX_TARGET, 0),
615	SOC_SINGLE("DMIC1_HW_GAIN_CURRENT", DMIC_GAIN1_CUR,
616		       0, DMIC_GAIN_MAX_CURRENT, 0),
617	SOC_SINGLE("DMIC2_HW_GAIN_CURRENT", DMIC_GAIN2_CUR,
618		       0, DMIC_GAIN_MAX_CURRENT, 0),
619	SOC_SINGLE("DMIC3_HW_GAIN_CURRENT", DMIC_GAIN3_CUR,
620		       0, DMIC_GAIN_MAX_CURRENT, 0),
621	SOC_SINGLE("DMIC4_HW_GAIN_CURRENT", DMIC_GAIN4_CUR,
622		       0, DMIC_GAIN_MAX_CURRENT, 0),
623	SOC_SINGLE("DMIC1_HW_GAIN_UP_STEP", DMIC_GAIN1_CON3,
624		   0, DMIC_GAIN_MAX_STEP, 0),
625	SOC_SINGLE("DMIC2_HW_GAIN_UP_STEP", DMIC_GAIN2_CON3,
626		   0, DMIC_GAIN_MAX_STEP, 0),
627	SOC_SINGLE("DMIC3_HW_GAIN_UP_STEP", DMIC_GAIN3_CON3,
628		   0, DMIC_GAIN_MAX_STEP, 0),
629	SOC_SINGLE("DMIC4_HW_GAIN_UP_STEP", DMIC_GAIN4_CON3,
630		   0, DMIC_GAIN_MAX_STEP, 0),
631	SOC_SINGLE("DMIC1_HW_GAIN_DOWN_STEP", DMIC_GAIN1_CON2,
632		   0, DMIC_GAIN_MAX_STEP, 0),
633	SOC_SINGLE("DMIC2_HW_GAIN_DOWN_STEP", DMIC_GAIN2_CON2,
634		   0, DMIC_GAIN_MAX_STEP, 0),
635	SOC_SINGLE("DMIC3_HW_GAIN_DOWN_STEP", DMIC_GAIN3_CON2,
636		   0, DMIC_GAIN_MAX_STEP, 0),
637	SOC_SINGLE("DMIC4_HW_GAIN_DOWN_STEP", DMIC_GAIN4_CON2,
638		   0, DMIC_GAIN_MAX_STEP, 0),
639	SOC_SINGLE("DMIC1_HW_GAIN_SAMPLE_PER_STEP", DMIC_GAIN1_CON0,
640		   DMIC_GAIN_CON0_SAMPLE_PER_STEP_SHIFT, DMIC_GAIN_MAX_PER_STEP, 0),
641	SOC_SINGLE("DMIC2_HW_GAIN_SAMPLE_PER_STEP", DMIC_GAIN2_CON0,
642		   DMIC_GAIN_CON0_SAMPLE_PER_STEP_SHIFT, DMIC_GAIN_MAX_PER_STEP, 0),
643	SOC_SINGLE("DMIC3_HW_GAIN_SAMPLE_PER_STEP", DMIC_GAIN3_CON0,
644		   DMIC_GAIN_CON0_SAMPLE_PER_STEP_SHIFT, DMIC_GAIN_MAX_PER_STEP, 0),
645	SOC_SINGLE("DMIC4_HW_GAIN_SAMPLE_PER_STEP", DMIC_GAIN4_CON0,
646		   DMIC_GAIN_CON0_SAMPLE_PER_STEP_SHIFT, DMIC_GAIN_MAX_PER_STEP, 0),
647};
648
649static int init_dmic_priv_data(struct mtk_base_afe *afe)
650{
651	struct mt8188_afe_private *afe_priv = afe->platform_priv;
652	struct mtk_dai_dmic_priv *dmic_priv;
653
654	dmic_priv = devm_kzalloc(afe->dev, sizeof(struct mtk_dai_dmic_priv),
655				 GFP_KERNEL);
656	if (!dmic_priv)
657		return -ENOMEM;
658
659	afe_priv->dai_priv[MT8188_AFE_IO_DMIC_IN] = dmic_priv;
660	return 0;
661}
662
663int mt8188_dai_dmic_register(struct mtk_base_afe *afe)
664{
665	struct mtk_base_afe_dai *dai;
666
667	dai = devm_kzalloc(afe->dev, sizeof(*dai), GFP_KERNEL);
668	if (!dai)
669		return -ENOMEM;
670
671	list_add(&dai->list, &afe->sub_dais);
672
673	dai->dai_drivers = mtk_dai_dmic_driver;
674	dai->num_dai_drivers = ARRAY_SIZE(mtk_dai_dmic_driver);
675	dai->dapm_widgets = mtk_dai_dmic_widgets;
676	dai->num_dapm_widgets = ARRAY_SIZE(mtk_dai_dmic_widgets);
677	dai->dapm_routes = mtk_dai_dmic_routes;
678	dai->num_dapm_routes = ARRAY_SIZE(mtk_dai_dmic_routes);
679	dai->controls = mtk_dai_dmic_controls;
680	dai->num_controls = ARRAY_SIZE(mtk_dai_dmic_controls);
681
682	return init_dmic_priv_data(afe);
683}
~/ Read-only file preview.