162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0
262306a36Sopenharmony_ci//
362306a36Sopenharmony_ci//  MediaTek ALSA SoC Audio DAI SRC Control
462306a36Sopenharmony_ci//
562306a36Sopenharmony_ci// Copyright (c) 2022 MediaTek Inc.
662306a36Sopenharmony_ci// Author: Jiaxin Yu <jiaxin.yu@mediatek.com>
762306a36Sopenharmony_ci
862306a36Sopenharmony_ci#include <linux/regmap.h>
962306a36Sopenharmony_ci#include "mt8186-afe-common.h"
1062306a36Sopenharmony_ci#include "mt8186-interconnection.h"
1162306a36Sopenharmony_ci
1262306a36Sopenharmony_cistruct mtk_afe_src_priv {
1362306a36Sopenharmony_ci	int dl_rate;
1462306a36Sopenharmony_ci	int ul_rate;
1562306a36Sopenharmony_ci};
1662306a36Sopenharmony_ci
1762306a36Sopenharmony_cistatic const unsigned int src_iir_coeff_32_to_16[] = {
1862306a36Sopenharmony_ci	0x0dbae6, 0xff9b0a, 0x0dbae6, 0x05e488, 0xe072b9, 0x000002,
1962306a36Sopenharmony_ci	0x0dbae6, 0x000f3b, 0x0dbae6, 0x06a537, 0xe17d79, 0x000002,
2062306a36Sopenharmony_ci	0x0dbae6, 0x01246a, 0x0dbae6, 0x087261, 0xe306be, 0x000002,
2162306a36Sopenharmony_ci	0x0dbae6, 0x03437d, 0x0dbae6, 0x0bc16f, 0xe57c87, 0x000002,
2262306a36Sopenharmony_ci	0x0dbae6, 0x072981, 0x0dbae6, 0x111dd3, 0xe94f2a, 0x000002,
2362306a36Sopenharmony_ci	0x0dbae6, 0x0dc4a6, 0x0dbae6, 0x188611, 0xee85a0, 0x000002,
2462306a36Sopenharmony_ci	0x0dbae6, 0x168b9a, 0x0dbae6, 0x200e8f, 0xf3ccf1, 0x000002,
2562306a36Sopenharmony_ci	0x000000, 0x1b75cb, 0x1b75cb, 0x2374a2, 0x000000, 0x000001
2662306a36Sopenharmony_ci};
2762306a36Sopenharmony_ci
2862306a36Sopenharmony_cistatic const unsigned int src_iir_coeff_44_to_16[] = {
2962306a36Sopenharmony_ci	0x09ae28, 0xf7d97d, 0x09ae28, 0x212a3d, 0xe0ac3a, 0x000002,
3062306a36Sopenharmony_ci	0x09ae28, 0xf8525a, 0x09ae28, 0x216d72, 0xe234be, 0x000002,
3162306a36Sopenharmony_ci	0x09ae28, 0xf980f5, 0x09ae28, 0x22a057, 0xe45a81, 0x000002,
3262306a36Sopenharmony_ci	0x09ae28, 0xfc0a08, 0x09ae28, 0x24d3bd, 0xe7752d, 0x000002,
3362306a36Sopenharmony_ci	0x09ae28, 0x016162, 0x09ae28, 0x27da01, 0xeb6ea8, 0x000002,
3462306a36Sopenharmony_ci	0x09ae28, 0x0b67df, 0x09ae28, 0x2aca4a, 0xef34c4, 0x000002,
3562306a36Sopenharmony_ci	0x000000, 0x135c50, 0x135c50, 0x2c1079, 0x000000, 0x000001
3662306a36Sopenharmony_ci};
3762306a36Sopenharmony_ci
3862306a36Sopenharmony_cistatic const unsigned int src_iir_coeff_44_to_32[] = {
3962306a36Sopenharmony_ci	0x096966, 0x0c4d35, 0x096966, 0xedee81, 0xf05070, 0x000003,
4062306a36Sopenharmony_ci	0x12d2cc, 0x193910, 0x12d2cc, 0xddbf4f, 0xe21e1d, 0x000002,
4162306a36Sopenharmony_ci	0x12d2cc, 0x1a9e60, 0x12d2cc, 0xe18916, 0xe470fd, 0x000002,
4262306a36Sopenharmony_ci	0x12d2cc, 0x1d06e0, 0x12d2cc, 0xe8a4a6, 0xe87b24, 0x000002,
4362306a36Sopenharmony_ci	0x12d2cc, 0x207578, 0x12d2cc, 0xf4fe62, 0xef5917, 0x000002,
4462306a36Sopenharmony_ci	0x12d2cc, 0x24055f, 0x12d2cc, 0x05ee2b, 0xf8b502, 0x000002,
4562306a36Sopenharmony_ci	0x000000, 0x25a599, 0x25a599, 0x0fabe2, 0x000000, 0x000001
4662306a36Sopenharmony_ci};
4762306a36Sopenharmony_ci
4862306a36Sopenharmony_cistatic const unsigned int src_iir_coeff_48_to_16[] = {
4962306a36Sopenharmony_ci	0x0296a4, 0xfd69dd, 0x0296a4, 0x209439, 0xe01ff9, 0x000002,
5062306a36Sopenharmony_ci	0x0f4ff3, 0xf0d6d4, 0x0f4ff3, 0x209bc9, 0xe076c3, 0x000002,
5162306a36Sopenharmony_ci	0x0e8490, 0xf1fe63, 0x0e8490, 0x20cfd6, 0xe12124, 0x000002,
5262306a36Sopenharmony_ci	0x14852f, 0xed794a, 0x14852f, 0x21503d, 0xe28b32, 0x000002,
5362306a36Sopenharmony_ci	0x136222, 0xf17677, 0x136222, 0x225be1, 0xe56964, 0x000002,
5462306a36Sopenharmony_ci	0x0a8d85, 0xfc4a97, 0x0a8d85, 0x24310c, 0xea6952, 0x000002,
5562306a36Sopenharmony_ci	0x05eff5, 0x043455, 0x05eff5, 0x4ced8f, 0xe134d6, 0x000001,
5662306a36Sopenharmony_ci	0x000000, 0x3aebe6, 0x3aebe6, 0x04f3b0, 0x000000, 0x000004
5762306a36Sopenharmony_ci};
5862306a36Sopenharmony_ci
5962306a36Sopenharmony_cistatic const unsigned int src_iir_coeff_48_to_32[] = {
6062306a36Sopenharmony_ci	0x10c1b8, 0x10a7df, 0x10c1b8, 0xe7514e, 0xe0b41f, 0x000002,
6162306a36Sopenharmony_ci	0x10c1b8, 0x116257, 0x10c1b8, 0xe9402f, 0xe25aaa, 0x000002,
6262306a36Sopenharmony_ci	0x10c1b8, 0x130c89, 0x10c1b8, 0xed3cc3, 0xe4dddb, 0x000002,
6362306a36Sopenharmony_ci	0x10c1b8, 0x1600dd, 0x10c1b8, 0xf48000, 0xe90c55, 0x000002,
6462306a36Sopenharmony_ci	0x10c1b8, 0x1a672e, 0x10c1b8, 0x00494c, 0xefa807, 0x000002,
6562306a36Sopenharmony_ci	0x10c1b8, 0x1f38e6, 0x10c1b8, 0x0ee076, 0xf7c5f3, 0x000002,
6662306a36Sopenharmony_ci	0x000000, 0x218370, 0x218370, 0x168b40, 0x000000, 0x000001
6762306a36Sopenharmony_ci};
6862306a36Sopenharmony_ci
6962306a36Sopenharmony_cistatic const unsigned int src_iir_coeff_48_to_44[] = {
7062306a36Sopenharmony_ci	0x0bf71c, 0x170f3f, 0x0bf71c, 0xe3a4c8, 0xf096cb, 0x000003,
7162306a36Sopenharmony_ci	0x0bf71c, 0x17395e, 0x0bf71c, 0xe58085, 0xf210c8, 0x000003,
7262306a36Sopenharmony_ci	0x0bf71c, 0x1782bd, 0x0bf71c, 0xe95ef6, 0xf4c899, 0x000003,
7362306a36Sopenharmony_ci	0x0bf71c, 0x17cd97, 0x0bf71c, 0xf1608a, 0xfa3b18, 0x000003,
7462306a36Sopenharmony_ci	0x000000, 0x2fdc6f, 0x2fdc6f, 0xf15663, 0x000000, 0x000001
7562306a36Sopenharmony_ci};
7662306a36Sopenharmony_ci
7762306a36Sopenharmony_cistatic const unsigned int src_iir_coeff_96_to_16[] = {
7862306a36Sopenharmony_ci	0x0805a1, 0xf21ae3, 0x0805a1, 0x3840bb, 0xe02a2e, 0x000002,
7962306a36Sopenharmony_ci	0x0d5dd8, 0xe8f259, 0x0d5dd8, 0x1c0af6, 0xf04700, 0x000003,
8062306a36Sopenharmony_ci	0x0bb422, 0xec08d9, 0x0bb422, 0x1bfccc, 0xf09216, 0x000003,
8162306a36Sopenharmony_ci	0x08fde6, 0xf108be, 0x08fde6, 0x1bf096, 0xf10ae0, 0x000003,
8262306a36Sopenharmony_ci	0x0ae311, 0xeeeda3, 0x0ae311, 0x37c646, 0xe385f5, 0x000002,
8362306a36Sopenharmony_ci	0x044089, 0xfa7242, 0x044089, 0x37a785, 0xe56526, 0x000002,
8462306a36Sopenharmony_ci	0x00c75c, 0xffb947, 0x00c75c, 0x378ba3, 0xe72c5f, 0x000002,
8562306a36Sopenharmony_ci	0x000000, 0x0ef76e, 0x0ef76e, 0x377fda, 0x000000, 0x000001,
8662306a36Sopenharmony_ci};
8762306a36Sopenharmony_ci
8862306a36Sopenharmony_cistatic const unsigned int src_iir_coeff_96_to_44[] = {
8962306a36Sopenharmony_ci	0x08b543, 0xfd80f4, 0x08b543, 0x0e2332, 0xe06ed0, 0x000002,
9062306a36Sopenharmony_ci	0x1b6038, 0xf90e7e, 0x1b6038, 0x0ec1ac, 0xe16f66, 0x000002,
9162306a36Sopenharmony_ci	0x188478, 0xfbb921, 0x188478, 0x105859, 0xe2e596, 0x000002,
9262306a36Sopenharmony_ci	0x13eff3, 0xffa707, 0x13eff3, 0x13455c, 0xe533b7, 0x000002,
9362306a36Sopenharmony_ci	0x0dc239, 0x03d458, 0x0dc239, 0x17f120, 0xe8b617, 0x000002,
9462306a36Sopenharmony_ci	0x0745f1, 0x05d790, 0x0745f1, 0x1e3d75, 0xed5f18, 0x000002,
9562306a36Sopenharmony_ci	0x05641f, 0x085e2b, 0x05641f, 0x48efd0, 0xe3e9c8, 0x000001,
9662306a36Sopenharmony_ci	0x000000, 0x28f632, 0x28f632, 0x273905, 0x000000, 0x000001,
9762306a36Sopenharmony_ci};
9862306a36Sopenharmony_ci
9962306a36Sopenharmony_cistatic unsigned int mtk_get_src_freq_mode(struct mtk_base_afe *afe, int rate)
10062306a36Sopenharmony_ci{
10162306a36Sopenharmony_ci	switch (rate) {
10262306a36Sopenharmony_ci	case 8000:
10362306a36Sopenharmony_ci		return 0x50000;
10462306a36Sopenharmony_ci	case 11025:
10562306a36Sopenharmony_ci		return 0x6e400;
10662306a36Sopenharmony_ci	case 12000:
10762306a36Sopenharmony_ci		return 0x78000;
10862306a36Sopenharmony_ci	case 16000:
10962306a36Sopenharmony_ci		return 0xa0000;
11062306a36Sopenharmony_ci	case 22050:
11162306a36Sopenharmony_ci		return 0xdc800;
11262306a36Sopenharmony_ci	case 24000:
11362306a36Sopenharmony_ci		return 0xf0000;
11462306a36Sopenharmony_ci	case 32000:
11562306a36Sopenharmony_ci		return 0x140000;
11662306a36Sopenharmony_ci	case 44100:
11762306a36Sopenharmony_ci		return 0x1b9000;
11862306a36Sopenharmony_ci	case 48000:
11962306a36Sopenharmony_ci		return 0x1e0000;
12062306a36Sopenharmony_ci	case 88200:
12162306a36Sopenharmony_ci		return 0x372000;
12262306a36Sopenharmony_ci	case 96000:
12362306a36Sopenharmony_ci		return 0x3c0000;
12462306a36Sopenharmony_ci	case 176400:
12562306a36Sopenharmony_ci		return 0x6e4000;
12662306a36Sopenharmony_ci	case 192000:
12762306a36Sopenharmony_ci		return 0x780000;
12862306a36Sopenharmony_ci	default:
12962306a36Sopenharmony_ci		dev_err(afe->dev, "%s(), rate %d invalid!!!\n",
13062306a36Sopenharmony_ci			__func__, rate);
13162306a36Sopenharmony_ci		return 0;
13262306a36Sopenharmony_ci	}
13362306a36Sopenharmony_ci}
13462306a36Sopenharmony_ci
13562306a36Sopenharmony_cistatic const unsigned int *get_iir_coeff(unsigned int rate_in,
13662306a36Sopenharmony_ci					 unsigned int rate_out,
13762306a36Sopenharmony_ci					 unsigned int *param_num)
13862306a36Sopenharmony_ci{
13962306a36Sopenharmony_ci	if (rate_in == 32000 && rate_out == 16000) {
14062306a36Sopenharmony_ci		*param_num = ARRAY_SIZE(src_iir_coeff_32_to_16);
14162306a36Sopenharmony_ci		return src_iir_coeff_32_to_16;
14262306a36Sopenharmony_ci	} else if (rate_in == 44100 && rate_out == 16000) {
14362306a36Sopenharmony_ci		*param_num = ARRAY_SIZE(src_iir_coeff_44_to_16);
14462306a36Sopenharmony_ci		return src_iir_coeff_44_to_16;
14562306a36Sopenharmony_ci	} else if (rate_in == 44100 && rate_out == 32000) {
14662306a36Sopenharmony_ci		*param_num = ARRAY_SIZE(src_iir_coeff_44_to_32);
14762306a36Sopenharmony_ci		return src_iir_coeff_44_to_32;
14862306a36Sopenharmony_ci	} else if ((rate_in == 48000 && rate_out == 16000) ||
14962306a36Sopenharmony_ci		   (rate_in == 96000 && rate_out == 32000)) {
15062306a36Sopenharmony_ci		*param_num = ARRAY_SIZE(src_iir_coeff_48_to_16);
15162306a36Sopenharmony_ci		return src_iir_coeff_48_to_16;
15262306a36Sopenharmony_ci	} else if (rate_in == 48000 && rate_out == 32000) {
15362306a36Sopenharmony_ci		*param_num = ARRAY_SIZE(src_iir_coeff_48_to_32);
15462306a36Sopenharmony_ci		return src_iir_coeff_48_to_32;
15562306a36Sopenharmony_ci	} else if (rate_in == 48000 && rate_out == 44100) {
15662306a36Sopenharmony_ci		*param_num = ARRAY_SIZE(src_iir_coeff_48_to_44);
15762306a36Sopenharmony_ci		return src_iir_coeff_48_to_44;
15862306a36Sopenharmony_ci	} else if (rate_in == 96000 && rate_out == 16000) {
15962306a36Sopenharmony_ci		*param_num = ARRAY_SIZE(src_iir_coeff_96_to_16);
16062306a36Sopenharmony_ci		return src_iir_coeff_96_to_16;
16162306a36Sopenharmony_ci	} else if ((rate_in == 96000 && rate_out == 44100) ||
16262306a36Sopenharmony_ci		   (rate_in == 48000 && rate_out == 22050)) {
16362306a36Sopenharmony_ci		*param_num = ARRAY_SIZE(src_iir_coeff_96_to_44);
16462306a36Sopenharmony_ci		return src_iir_coeff_96_to_44;
16562306a36Sopenharmony_ci	}
16662306a36Sopenharmony_ci
16762306a36Sopenharmony_ci	*param_num = 0;
16862306a36Sopenharmony_ci	return NULL;
16962306a36Sopenharmony_ci}
17062306a36Sopenharmony_ci
17162306a36Sopenharmony_cistatic int mtk_set_src_1_param(struct mtk_base_afe *afe, int id)
17262306a36Sopenharmony_ci{
17362306a36Sopenharmony_ci	struct mt8186_afe_private *afe_priv = afe->platform_priv;
17462306a36Sopenharmony_ci	struct mtk_afe_src_priv *src_priv = afe_priv->dai_priv[id];
17562306a36Sopenharmony_ci	unsigned int iir_coeff_num;
17662306a36Sopenharmony_ci	unsigned int iir_stage;
17762306a36Sopenharmony_ci	int rate_in = src_priv->dl_rate;
17862306a36Sopenharmony_ci	int rate_out = src_priv->ul_rate;
17962306a36Sopenharmony_ci	unsigned int out_freq_mode = mtk_get_src_freq_mode(afe, rate_out);
18062306a36Sopenharmony_ci	unsigned int in_freq_mode = mtk_get_src_freq_mode(afe, rate_in);
18162306a36Sopenharmony_ci
18262306a36Sopenharmony_ci	/* set out freq mode */
18362306a36Sopenharmony_ci	regmap_update_bits(afe->regmap, AFE_GENERAL1_ASRC_2CH_CON3,
18462306a36Sopenharmony_ci			   G_SRC_ASM_FREQ_4_MASK_SFT,
18562306a36Sopenharmony_ci			   out_freq_mode << G_SRC_ASM_FREQ_4_SFT);
18662306a36Sopenharmony_ci
18762306a36Sopenharmony_ci	/* set in freq mode */
18862306a36Sopenharmony_ci	regmap_update_bits(afe->regmap, AFE_GENERAL1_ASRC_2CH_CON4,
18962306a36Sopenharmony_ci			   G_SRC_ASM_FREQ_5_MASK_SFT,
19062306a36Sopenharmony_ci			   in_freq_mode << G_SRC_ASM_FREQ_5_SFT);
19162306a36Sopenharmony_ci
19262306a36Sopenharmony_ci	regmap_write(afe->regmap, AFE_GENERAL1_ASRC_2CH_CON5, 0x3f5986);
19362306a36Sopenharmony_ci	regmap_write(afe->regmap, AFE_GENERAL1_ASRC_2CH_CON5, 0x3f5987);
19462306a36Sopenharmony_ci	regmap_write(afe->regmap, AFE_GENERAL1_ASRC_2CH_CON6, 0x1fbd);
19562306a36Sopenharmony_ci	regmap_write(afe->regmap, AFE_GENERAL1_ASRC_2CH_CON2, 0);
19662306a36Sopenharmony_ci
19762306a36Sopenharmony_ci	/* set iir if in_rate > out_rate */
19862306a36Sopenharmony_ci	if (rate_in > rate_out) {
19962306a36Sopenharmony_ci		int i;
20062306a36Sopenharmony_ci		const unsigned int *iir_coeff = get_iir_coeff(rate_in, rate_out,
20162306a36Sopenharmony_ci							      &iir_coeff_num);
20262306a36Sopenharmony_ci
20362306a36Sopenharmony_ci		if (iir_coeff_num == 0 || !iir_coeff) {
20462306a36Sopenharmony_ci			dev_err(afe->dev, "%s(), iir coeff error, num %d, coeff %p\n",
20562306a36Sopenharmony_ci				__func__, iir_coeff_num, iir_coeff);
20662306a36Sopenharmony_ci			return -EINVAL;
20762306a36Sopenharmony_ci		}
20862306a36Sopenharmony_ci
20962306a36Sopenharmony_ci		/* COEFF_SRAM_CTRL */
21062306a36Sopenharmony_ci		regmap_update_bits(afe->regmap, AFE_GENERAL1_ASRC_2CH_CON0,
21162306a36Sopenharmony_ci				   G_SRC_COEFF_SRAM_CTRL_MASK_SFT,
21262306a36Sopenharmony_ci				   BIT(G_SRC_COEFF_SRAM_CTRL_SFT));
21362306a36Sopenharmony_ci		/* Clear coeff history to r/w coeff from the first position */
21462306a36Sopenharmony_ci		regmap_update_bits(afe->regmap, AFE_GENERAL1_ASRC_2CH_CON13,
21562306a36Sopenharmony_ci				   G_SRC_COEFF_SRAM_ADR_MASK_SFT, 0);
21662306a36Sopenharmony_ci		/* Write SRC coeff, should not read the reg during write */
21762306a36Sopenharmony_ci		for (i = 0; i < iir_coeff_num; i++)
21862306a36Sopenharmony_ci			regmap_write(afe->regmap, AFE_GENERAL1_ASRC_2CH_CON12,
21962306a36Sopenharmony_ci				     iir_coeff[i]);
22062306a36Sopenharmony_ci		/* disable sram access */
22162306a36Sopenharmony_ci		regmap_update_bits(afe->regmap, AFE_GENERAL1_ASRC_2CH_CON0,
22262306a36Sopenharmony_ci				   G_SRC_COEFF_SRAM_CTRL_MASK_SFT, 0);
22362306a36Sopenharmony_ci		/* CHSET_IIR_STAGE */
22462306a36Sopenharmony_ci		iir_stage = (iir_coeff_num / 6) - 1;
22562306a36Sopenharmony_ci		regmap_update_bits(afe->regmap, AFE_GENERAL1_ASRC_2CH_CON2,
22662306a36Sopenharmony_ci				   G_SRC_CHSET_IIR_STAGE_MASK_SFT,
22762306a36Sopenharmony_ci				   iir_stage << G_SRC_CHSET_IIR_STAGE_SFT);
22862306a36Sopenharmony_ci		/* CHSET_IIR_EN */
22962306a36Sopenharmony_ci		regmap_update_bits(afe->regmap, AFE_GENERAL1_ASRC_2CH_CON2,
23062306a36Sopenharmony_ci				   G_SRC_CHSET_IIR_EN_MASK_SFT,
23162306a36Sopenharmony_ci				   BIT(G_SRC_CHSET_IIR_EN_SFT));
23262306a36Sopenharmony_ci	} else {
23362306a36Sopenharmony_ci		/* CHSET_IIR_EN off */
23462306a36Sopenharmony_ci		regmap_update_bits(afe->regmap, AFE_GENERAL1_ASRC_2CH_CON2,
23562306a36Sopenharmony_ci				   G_SRC_CHSET_IIR_EN_MASK_SFT, 0);
23662306a36Sopenharmony_ci	}
23762306a36Sopenharmony_ci
23862306a36Sopenharmony_ci	return 0;
23962306a36Sopenharmony_ci}
24062306a36Sopenharmony_ci
24162306a36Sopenharmony_cistatic int mtk_set_src_2_param(struct mtk_base_afe *afe, int id)
24262306a36Sopenharmony_ci{
24362306a36Sopenharmony_ci	struct mt8186_afe_private *afe_priv = afe->platform_priv;
24462306a36Sopenharmony_ci	struct mtk_afe_src_priv *src_priv = afe_priv->dai_priv[id];
24562306a36Sopenharmony_ci	unsigned int iir_coeff_num;
24662306a36Sopenharmony_ci	unsigned int iir_stage;
24762306a36Sopenharmony_ci	int rate_in = src_priv->dl_rate;
24862306a36Sopenharmony_ci	int rate_out = src_priv->ul_rate;
24962306a36Sopenharmony_ci	unsigned int out_freq_mode = mtk_get_src_freq_mode(afe, rate_out);
25062306a36Sopenharmony_ci	unsigned int in_freq_mode = mtk_get_src_freq_mode(afe, rate_in);
25162306a36Sopenharmony_ci
25262306a36Sopenharmony_ci	/* set out freq mode */
25362306a36Sopenharmony_ci	regmap_update_bits(afe->regmap, AFE_GENERAL2_ASRC_2CH_CON3,
25462306a36Sopenharmony_ci			   G_SRC_ASM_FREQ_4_MASK_SFT,
25562306a36Sopenharmony_ci			   out_freq_mode << G_SRC_ASM_FREQ_4_SFT);
25662306a36Sopenharmony_ci
25762306a36Sopenharmony_ci	/* set in freq mode */
25862306a36Sopenharmony_ci	regmap_update_bits(afe->regmap, AFE_GENERAL2_ASRC_2CH_CON4,
25962306a36Sopenharmony_ci			   G_SRC_ASM_FREQ_5_MASK_SFT,
26062306a36Sopenharmony_ci			   in_freq_mode << G_SRC_ASM_FREQ_5_SFT);
26162306a36Sopenharmony_ci
26262306a36Sopenharmony_ci	regmap_write(afe->regmap, AFE_GENERAL2_ASRC_2CH_CON5, 0x3f5986);
26362306a36Sopenharmony_ci	regmap_write(afe->regmap, AFE_GENERAL2_ASRC_2CH_CON5, 0x3f5987);
26462306a36Sopenharmony_ci	regmap_write(afe->regmap, AFE_GENERAL2_ASRC_2CH_CON6, 0x1fbd);
26562306a36Sopenharmony_ci	regmap_write(afe->regmap, AFE_GENERAL2_ASRC_2CH_CON2, 0);
26662306a36Sopenharmony_ci
26762306a36Sopenharmony_ci	/* set iir if in_rate > out_rate */
26862306a36Sopenharmony_ci	if (rate_in > rate_out) {
26962306a36Sopenharmony_ci		int i;
27062306a36Sopenharmony_ci		const unsigned int *iir_coeff = get_iir_coeff(rate_in, rate_out,
27162306a36Sopenharmony_ci							      &iir_coeff_num);
27262306a36Sopenharmony_ci
27362306a36Sopenharmony_ci		if (iir_coeff_num == 0 || !iir_coeff) {
27462306a36Sopenharmony_ci			dev_err(afe->dev, "%s(), iir coeff error, num %d, coeff %p\n",
27562306a36Sopenharmony_ci				 __func__, iir_coeff_num, iir_coeff);
27662306a36Sopenharmony_ci			return -EINVAL;
27762306a36Sopenharmony_ci		}
27862306a36Sopenharmony_ci
27962306a36Sopenharmony_ci		/* COEFF_SRAM_CTRL */
28062306a36Sopenharmony_ci		regmap_update_bits(afe->regmap, AFE_GENERAL2_ASRC_2CH_CON0,
28162306a36Sopenharmony_ci				   G_SRC_COEFF_SRAM_CTRL_MASK_SFT,
28262306a36Sopenharmony_ci				   BIT(G_SRC_COEFF_SRAM_CTRL_SFT));
28362306a36Sopenharmony_ci		/* Clear coeff history to r/w coeff from the first position */
28462306a36Sopenharmony_ci		regmap_update_bits(afe->regmap, AFE_GENERAL2_ASRC_2CH_CON13,
28562306a36Sopenharmony_ci				   G_SRC_COEFF_SRAM_ADR_MASK_SFT, 0);
28662306a36Sopenharmony_ci		/* Write SRC coeff, should not read the reg during write */
28762306a36Sopenharmony_ci		for (i = 0; i < iir_coeff_num; i++)
28862306a36Sopenharmony_ci			regmap_write(afe->regmap, AFE_GENERAL2_ASRC_2CH_CON12,
28962306a36Sopenharmony_ci				     iir_coeff[i]);
29062306a36Sopenharmony_ci		/* disable sram access */
29162306a36Sopenharmony_ci		regmap_update_bits(afe->regmap, AFE_GENERAL2_ASRC_2CH_CON0,
29262306a36Sopenharmony_ci				   G_SRC_COEFF_SRAM_CTRL_MASK_SFT, 0);
29362306a36Sopenharmony_ci		/* CHSET_IIR_STAGE */
29462306a36Sopenharmony_ci		iir_stage = (iir_coeff_num / 6) - 1;
29562306a36Sopenharmony_ci		regmap_update_bits(afe->regmap, AFE_GENERAL2_ASRC_2CH_CON2,
29662306a36Sopenharmony_ci				   G_SRC_CHSET_IIR_STAGE_MASK_SFT,
29762306a36Sopenharmony_ci				   iir_stage << G_SRC_CHSET_IIR_STAGE_SFT);
29862306a36Sopenharmony_ci		/* CHSET_IIR_EN */
29962306a36Sopenharmony_ci		regmap_update_bits(afe->regmap, AFE_GENERAL2_ASRC_2CH_CON2,
30062306a36Sopenharmony_ci				   G_SRC_CHSET_IIR_EN_MASK_SFT,
30162306a36Sopenharmony_ci				   BIT(G_SRC_CHSET_IIR_EN_SFT));
30262306a36Sopenharmony_ci	} else {
30362306a36Sopenharmony_ci		/* CHSET_IIR_EN off */
30462306a36Sopenharmony_ci		regmap_update_bits(afe->regmap, AFE_GENERAL2_ASRC_2CH_CON2,
30562306a36Sopenharmony_ci				   G_SRC_CHSET_IIR_EN_MASK_SFT, 0);
30662306a36Sopenharmony_ci	}
30762306a36Sopenharmony_ci
30862306a36Sopenharmony_ci	return 0;
30962306a36Sopenharmony_ci}
31062306a36Sopenharmony_ci
31162306a36Sopenharmony_ci#define HW_SRC_1_EN_W_NAME "HW_SRC_1_Enable"
31262306a36Sopenharmony_ci#define HW_SRC_2_EN_W_NAME "HW_SRC_2_Enable"
31362306a36Sopenharmony_ci
31462306a36Sopenharmony_cistatic int mtk_hw_src_event(struct snd_soc_dapm_widget *w,
31562306a36Sopenharmony_ci			    struct snd_kcontrol *kcontrol,
31662306a36Sopenharmony_ci			    int event)
31762306a36Sopenharmony_ci{
31862306a36Sopenharmony_ci	struct snd_soc_component *cmpnt = snd_soc_dapm_to_component(w->dapm);
31962306a36Sopenharmony_ci	struct mtk_base_afe *afe = snd_soc_component_get_drvdata(cmpnt);
32062306a36Sopenharmony_ci	struct mt8186_afe_private *afe_priv = afe->platform_priv;
32162306a36Sopenharmony_ci	int id;
32262306a36Sopenharmony_ci	struct mtk_afe_src_priv *src_priv;
32362306a36Sopenharmony_ci	unsigned int reg;
32462306a36Sopenharmony_ci
32562306a36Sopenharmony_ci	if (strcmp(w->name, HW_SRC_1_EN_W_NAME) == 0)
32662306a36Sopenharmony_ci		id = MT8186_DAI_SRC_1;
32762306a36Sopenharmony_ci	else
32862306a36Sopenharmony_ci		id = MT8186_DAI_SRC_2;
32962306a36Sopenharmony_ci
33062306a36Sopenharmony_ci	src_priv = afe_priv->dai_priv[id];
33162306a36Sopenharmony_ci
33262306a36Sopenharmony_ci	dev_dbg(afe->dev,
33362306a36Sopenharmony_ci		"%s(), name %s, event 0x%x, id %d, src_priv %p, dl_rate %d, ul_rate %d\n",
33462306a36Sopenharmony_ci		__func__, w->name, event, id, src_priv,
33562306a36Sopenharmony_ci		src_priv->dl_rate, src_priv->ul_rate);
33662306a36Sopenharmony_ci
33762306a36Sopenharmony_ci	switch (event) {
33862306a36Sopenharmony_ci	case SND_SOC_DAPM_PRE_PMU:
33962306a36Sopenharmony_ci		if (id == MT8186_DAI_SRC_1)
34062306a36Sopenharmony_ci			mtk_set_src_1_param(afe, id);
34162306a36Sopenharmony_ci		else
34262306a36Sopenharmony_ci			mtk_set_src_2_param(afe, id);
34362306a36Sopenharmony_ci		break;
34462306a36Sopenharmony_ci	case SND_SOC_DAPM_POST_PMU:
34562306a36Sopenharmony_ci		reg = (id == MT8186_DAI_SRC_1) ?
34662306a36Sopenharmony_ci		      AFE_GENERAL1_ASRC_2CH_CON0 : AFE_GENERAL2_ASRC_2CH_CON0;
34762306a36Sopenharmony_ci		/* ASM_ON */
34862306a36Sopenharmony_ci		regmap_update_bits(afe->regmap, reg,
34962306a36Sopenharmony_ci				   G_SRC_ASM_ON_MASK_SFT,
35062306a36Sopenharmony_ci				   BIT(G_SRC_ASM_ON_SFT));
35162306a36Sopenharmony_ci		/* CHSET_ON */
35262306a36Sopenharmony_ci		regmap_update_bits(afe->regmap, reg,
35362306a36Sopenharmony_ci				   G_SRC_CHSET_ON_MASK_SFT,
35462306a36Sopenharmony_ci				   BIT(G_SRC_CHSET_ON_SFT));
35562306a36Sopenharmony_ci		/* CHSET_STR_CLR */
35662306a36Sopenharmony_ci		regmap_update_bits(afe->regmap, reg,
35762306a36Sopenharmony_ci				   G_SRC_CHSET_STR_CLR_MASK_SFT,
35862306a36Sopenharmony_ci				   BIT(G_SRC_CHSET_STR_CLR_SFT));
35962306a36Sopenharmony_ci		break;
36062306a36Sopenharmony_ci	case SND_SOC_DAPM_PRE_PMD:
36162306a36Sopenharmony_ci		reg = (id == MT8186_DAI_SRC_1) ?
36262306a36Sopenharmony_ci		      AFE_GENERAL1_ASRC_2CH_CON0 : AFE_GENERAL2_ASRC_2CH_CON0;
36362306a36Sopenharmony_ci		/* ASM_OFF */
36462306a36Sopenharmony_ci		regmap_update_bits(afe->regmap, reg, G_SRC_ASM_ON_MASK_SFT, 0);
36562306a36Sopenharmony_ci		/* CHSET_OFF */
36662306a36Sopenharmony_ci		regmap_update_bits(afe->regmap, reg, G_SRC_CHSET_ON_MASK_SFT, 0);
36762306a36Sopenharmony_ci		/* CHSET_STR_CLR */
36862306a36Sopenharmony_ci		regmap_update_bits(afe->regmap, reg, G_SRC_CHSET_STR_CLR_MASK_SFT, 0);
36962306a36Sopenharmony_ci		break;
37062306a36Sopenharmony_ci	default:
37162306a36Sopenharmony_ci		break;
37262306a36Sopenharmony_ci	}
37362306a36Sopenharmony_ci
37462306a36Sopenharmony_ci	return 0;
37562306a36Sopenharmony_ci}
37662306a36Sopenharmony_ci
37762306a36Sopenharmony_ci/* dai component */
37862306a36Sopenharmony_cistatic const struct snd_kcontrol_new mtk_hw_src_1_in_ch1_mix[] = {
37962306a36Sopenharmony_ci	SOC_DAPM_SINGLE_AUTODISABLE("DL1_CH1 Switch", AFE_CONN40,
38062306a36Sopenharmony_ci				    I_DL1_CH1, 1, 0),
38162306a36Sopenharmony_ci	SOC_DAPM_SINGLE_AUTODISABLE("DL2_CH1 Switch", AFE_CONN40,
38262306a36Sopenharmony_ci				    I_DL2_CH1, 1, 0),
38362306a36Sopenharmony_ci	SOC_DAPM_SINGLE_AUTODISABLE("DL3_CH1 Switch", AFE_CONN40,
38462306a36Sopenharmony_ci				    I_DL3_CH1, 1, 0),
38562306a36Sopenharmony_ci	SOC_DAPM_SINGLE_AUTODISABLE("DL4_CH1 Switch", AFE_CONN40_1,
38662306a36Sopenharmony_ci				    I_DL4_CH1, 1, 0),
38762306a36Sopenharmony_ci	SOC_DAPM_SINGLE_AUTODISABLE("DL6_CH1 Switch", AFE_CONN40_1,
38862306a36Sopenharmony_ci				    I_DL6_CH1, 1, 0),
38962306a36Sopenharmony_ci	SOC_DAPM_SINGLE_AUTODISABLE("I2S0_CH1 Switch", AFE_CONN40,
39062306a36Sopenharmony_ci				    I_I2S0_CH1, 1, 0),
39162306a36Sopenharmony_ci	SOC_DAPM_SINGLE_AUTODISABLE("DL5_CH1 Switch", AFE_CONN40_1,
39262306a36Sopenharmony_ci				    I_DL5_CH1, 1, 0),
39362306a36Sopenharmony_ci};
39462306a36Sopenharmony_ci
39562306a36Sopenharmony_cistatic const struct snd_kcontrol_new mtk_hw_src_1_in_ch2_mix[] = {
39662306a36Sopenharmony_ci	SOC_DAPM_SINGLE_AUTODISABLE("DL1_CH2 Switch", AFE_CONN41,
39762306a36Sopenharmony_ci				    I_DL1_CH2, 1, 0),
39862306a36Sopenharmony_ci	SOC_DAPM_SINGLE_AUTODISABLE("DL2_CH2 Switch", AFE_CONN41,
39962306a36Sopenharmony_ci				    I_DL2_CH2, 1, 0),
40062306a36Sopenharmony_ci	SOC_DAPM_SINGLE_AUTODISABLE("DL3_CH2 Switch", AFE_CONN41,
40162306a36Sopenharmony_ci				    I_DL3_CH2, 1, 0),
40262306a36Sopenharmony_ci	SOC_DAPM_SINGLE_AUTODISABLE("DL4_CH2 Switch", AFE_CONN41_1,
40362306a36Sopenharmony_ci				    I_DL4_CH2, 1, 0),
40462306a36Sopenharmony_ci	SOC_DAPM_SINGLE_AUTODISABLE("DL6_CH2 Switch", AFE_CONN41_1,
40562306a36Sopenharmony_ci				    I_DL6_CH2, 1, 0),
40662306a36Sopenharmony_ci	SOC_DAPM_SINGLE_AUTODISABLE("I2S0_CH2 Switch", AFE_CONN41,
40762306a36Sopenharmony_ci				    I_I2S0_CH2, 1, 0),
40862306a36Sopenharmony_ci	SOC_DAPM_SINGLE_AUTODISABLE("DL5_CH2 Switch", AFE_CONN41_1,
40962306a36Sopenharmony_ci				    I_DL5_CH2, 1, 0),
41062306a36Sopenharmony_ci};
41162306a36Sopenharmony_ci
41262306a36Sopenharmony_cistatic const struct snd_kcontrol_new mtk_hw_src_2_in_ch1_mix[] = {
41362306a36Sopenharmony_ci	SOC_DAPM_SINGLE_AUTODISABLE("DL1_CH1 Switch", AFE_CONN42,
41462306a36Sopenharmony_ci				    I_DL1_CH1, 1, 0),
41562306a36Sopenharmony_ci	SOC_DAPM_SINGLE_AUTODISABLE("DL2_CH1 Switch", AFE_CONN42,
41662306a36Sopenharmony_ci				    I_DL2_CH1, 1, 0),
41762306a36Sopenharmony_ci	SOC_DAPM_SINGLE_AUTODISABLE("DL3_CH1 Switch", AFE_CONN42,
41862306a36Sopenharmony_ci				    I_DL3_CH1, 1, 0),
41962306a36Sopenharmony_ci	SOC_DAPM_SINGLE_AUTODISABLE("DL4_CH1 Switch", AFE_CONN42,
42062306a36Sopenharmony_ci				    I_DL4_CH1, 1, 0),
42162306a36Sopenharmony_ci	SOC_DAPM_SINGLE_AUTODISABLE("DL5_CH1 Switch", AFE_CONN42_1,
42262306a36Sopenharmony_ci				    I_DL5_CH1, 1, 0),
42362306a36Sopenharmony_ci	SOC_DAPM_SINGLE_AUTODISABLE("DL6_CH1 Switch", AFE_CONN42_1,
42462306a36Sopenharmony_ci				    I_DL6_CH1, 1, 0),
42562306a36Sopenharmony_ci	SOC_DAPM_SINGLE_AUTODISABLE("HW_GAIN2_OUT_CH1 Switch", AFE_CONN42,
42662306a36Sopenharmony_ci				    I_GAIN2_OUT_CH1, 1, 0),
42762306a36Sopenharmony_ci};
42862306a36Sopenharmony_ci
42962306a36Sopenharmony_cistatic const struct snd_kcontrol_new mtk_hw_src_2_in_ch2_mix[] = {
43062306a36Sopenharmony_ci	SOC_DAPM_SINGLE_AUTODISABLE("DL1_CH2 Switch", AFE_CONN43,
43162306a36Sopenharmony_ci				    I_DL1_CH2, 1, 0),
43262306a36Sopenharmony_ci	SOC_DAPM_SINGLE_AUTODISABLE("DL2_CH2 Switch", AFE_CONN43,
43362306a36Sopenharmony_ci				    I_DL2_CH2, 1, 0),
43462306a36Sopenharmony_ci	SOC_DAPM_SINGLE_AUTODISABLE("DL3_CH2 Switch", AFE_CONN43,
43562306a36Sopenharmony_ci				    I_DL3_CH2, 1, 0),
43662306a36Sopenharmony_ci	SOC_DAPM_SINGLE_AUTODISABLE("DL4_CH2 Switch", AFE_CONN43,
43762306a36Sopenharmony_ci				    I_DL4_CH2, 1, 0),
43862306a36Sopenharmony_ci	SOC_DAPM_SINGLE_AUTODISABLE("DL5_CH2 Switch", AFE_CONN43_1,
43962306a36Sopenharmony_ci				    I_DL5_CH2, 1, 0),
44062306a36Sopenharmony_ci	SOC_DAPM_SINGLE_AUTODISABLE("DL6_CH2 Switch", AFE_CONN43_1,
44162306a36Sopenharmony_ci				    I_DL6_CH2, 1, 0),
44262306a36Sopenharmony_ci	SOC_DAPM_SINGLE_AUTODISABLE("HW_GAIN2_OUT_CH2 Switch", AFE_CONN43,
44362306a36Sopenharmony_ci				    I_GAIN2_OUT_CH2, 1, 0),
44462306a36Sopenharmony_ci};
44562306a36Sopenharmony_ci
44662306a36Sopenharmony_cistatic const struct snd_soc_dapm_widget mtk_dai_src_widgets[] = {
44762306a36Sopenharmony_ci	/* inter-connections */
44862306a36Sopenharmony_ci	SND_SOC_DAPM_MIXER("HW_SRC_1_IN_CH1", SND_SOC_NOPM, 0, 0,
44962306a36Sopenharmony_ci			   mtk_hw_src_1_in_ch1_mix,
45062306a36Sopenharmony_ci			   ARRAY_SIZE(mtk_hw_src_1_in_ch1_mix)),
45162306a36Sopenharmony_ci	SND_SOC_DAPM_MIXER("HW_SRC_1_IN_CH2", SND_SOC_NOPM, 0, 0,
45262306a36Sopenharmony_ci			   mtk_hw_src_1_in_ch2_mix,
45362306a36Sopenharmony_ci			   ARRAY_SIZE(mtk_hw_src_1_in_ch2_mix)),
45462306a36Sopenharmony_ci	SND_SOC_DAPM_MIXER("HW_SRC_2_IN_CH1", SND_SOC_NOPM, 0, 0,
45562306a36Sopenharmony_ci			   mtk_hw_src_2_in_ch1_mix,
45662306a36Sopenharmony_ci			   ARRAY_SIZE(mtk_hw_src_2_in_ch1_mix)),
45762306a36Sopenharmony_ci	SND_SOC_DAPM_MIXER("HW_SRC_2_IN_CH2", SND_SOC_NOPM, 0, 0,
45862306a36Sopenharmony_ci			   mtk_hw_src_2_in_ch2_mix,
45962306a36Sopenharmony_ci			   ARRAY_SIZE(mtk_hw_src_2_in_ch2_mix)),
46062306a36Sopenharmony_ci
46162306a36Sopenharmony_ci	SND_SOC_DAPM_SUPPLY(HW_SRC_1_EN_W_NAME,
46262306a36Sopenharmony_ci			    GENERAL_ASRC_EN_ON, GENERAL1_ASRC_EN_ON_SFT, 0,
46362306a36Sopenharmony_ci			    mtk_hw_src_event,
46462306a36Sopenharmony_ci			    SND_SOC_DAPM_PRE_PMU |
46562306a36Sopenharmony_ci			    SND_SOC_DAPM_POST_PMU |
46662306a36Sopenharmony_ci			    SND_SOC_DAPM_PRE_PMD),
46762306a36Sopenharmony_ci
46862306a36Sopenharmony_ci	SND_SOC_DAPM_SUPPLY(HW_SRC_2_EN_W_NAME,
46962306a36Sopenharmony_ci			    GENERAL_ASRC_EN_ON, GENERAL2_ASRC_EN_ON_SFT, 0,
47062306a36Sopenharmony_ci			    mtk_hw_src_event,
47162306a36Sopenharmony_ci			    SND_SOC_DAPM_PRE_PMU |
47262306a36Sopenharmony_ci			    SND_SOC_DAPM_POST_PMU |
47362306a36Sopenharmony_ci			    SND_SOC_DAPM_PRE_PMD),
47462306a36Sopenharmony_ci
47562306a36Sopenharmony_ci	SND_SOC_DAPM_INPUT("HW SRC 1 Out Endpoint"),
47662306a36Sopenharmony_ci	SND_SOC_DAPM_INPUT("HW SRC 2 Out Endpoint"),
47762306a36Sopenharmony_ci	SND_SOC_DAPM_OUTPUT("HW SRC 1 In Endpoint"),
47862306a36Sopenharmony_ci	SND_SOC_DAPM_OUTPUT("HW SRC 2 In Endpoint"),
47962306a36Sopenharmony_ci};
48062306a36Sopenharmony_ci
48162306a36Sopenharmony_cistatic int mtk_afe_src_en_connect(struct snd_soc_dapm_widget *source,
48262306a36Sopenharmony_ci				  struct snd_soc_dapm_widget *sink)
48362306a36Sopenharmony_ci{
48462306a36Sopenharmony_ci	struct snd_soc_dapm_widget *w = source;
48562306a36Sopenharmony_ci	struct snd_soc_component *cmpnt = snd_soc_dapm_to_component(w->dapm);
48662306a36Sopenharmony_ci	struct mtk_base_afe *afe = snd_soc_component_get_drvdata(cmpnt);
48762306a36Sopenharmony_ci	struct mt8186_afe_private *afe_priv = afe->platform_priv;
48862306a36Sopenharmony_ci	struct mtk_afe_src_priv *src_priv;
48962306a36Sopenharmony_ci
49062306a36Sopenharmony_ci	if (strcmp(w->name, HW_SRC_1_EN_W_NAME) == 0)
49162306a36Sopenharmony_ci		src_priv = afe_priv->dai_priv[MT8186_DAI_SRC_1];
49262306a36Sopenharmony_ci	else
49362306a36Sopenharmony_ci		src_priv = afe_priv->dai_priv[MT8186_DAI_SRC_2];
49462306a36Sopenharmony_ci
49562306a36Sopenharmony_ci	dev_dbg(afe->dev,
49662306a36Sopenharmony_ci		"%s(), source %s, sink %s, dl_rate %d, ul_rate %d\n",
49762306a36Sopenharmony_ci		__func__, source->name, sink->name,
49862306a36Sopenharmony_ci		src_priv->dl_rate, src_priv->ul_rate);
49962306a36Sopenharmony_ci
50062306a36Sopenharmony_ci	return (src_priv->dl_rate > 0 && src_priv->ul_rate > 0) ? 1 : 0;
50162306a36Sopenharmony_ci}
50262306a36Sopenharmony_ci
50362306a36Sopenharmony_cistatic const struct snd_soc_dapm_route mtk_dai_src_routes[] = {
50462306a36Sopenharmony_ci	{"HW_SRC_1_IN_CH1", "DL1_CH1 Switch", "DL1"},
50562306a36Sopenharmony_ci	{"HW_SRC_1_IN_CH2", "DL1_CH2 Switch", "DL1"},
50662306a36Sopenharmony_ci	{"HW_SRC_2_IN_CH1", "DL1_CH1 Switch", "DL1"},
50762306a36Sopenharmony_ci	{"HW_SRC_2_IN_CH2", "DL1_CH2 Switch", "DL1"},
50862306a36Sopenharmony_ci	{"HW_SRC_1_IN_CH1", "DL2_CH1 Switch", "DL2"},
50962306a36Sopenharmony_ci	{"HW_SRC_1_IN_CH2", "DL2_CH2 Switch", "DL2"},
51062306a36Sopenharmony_ci	{"HW_SRC_2_IN_CH1", "DL2_CH1 Switch", "DL2"},
51162306a36Sopenharmony_ci	{"HW_SRC_2_IN_CH2", "DL2_CH2 Switch", "DL2"},
51262306a36Sopenharmony_ci	{"HW_SRC_1_IN_CH1", "DL3_CH1 Switch", "DL3"},
51362306a36Sopenharmony_ci	{"HW_SRC_1_IN_CH2", "DL3_CH2 Switch", "DL3"},
51462306a36Sopenharmony_ci	{"HW_SRC_2_IN_CH1", "DL3_CH1 Switch", "DL3"},
51562306a36Sopenharmony_ci	{"HW_SRC_2_IN_CH2", "DL3_CH2 Switch", "DL3"},
51662306a36Sopenharmony_ci	{"HW_SRC_1_IN_CH1", "DL6_CH1 Switch", "DL6"},
51762306a36Sopenharmony_ci	{"HW_SRC_1_IN_CH2", "DL6_CH2 Switch", "DL6"},
51862306a36Sopenharmony_ci	{"HW_SRC_2_IN_CH1", "DL6_CH1 Switch", "DL6"},
51962306a36Sopenharmony_ci	{"HW_SRC_2_IN_CH2", "DL6_CH2 Switch", "DL6"},
52062306a36Sopenharmony_ci	{"HW_SRC_1_IN_CH1", "DL5_CH1 Switch", "DL5"},
52162306a36Sopenharmony_ci	{"HW_SRC_1_IN_CH2", "DL5_CH2 Switch", "DL5"},
52262306a36Sopenharmony_ci	{"HW_SRC_2_IN_CH1", "DL5_CH1 Switch", "DL5"},
52362306a36Sopenharmony_ci	{"HW_SRC_2_IN_CH2", "DL5_CH2 Switch", "DL5"},
52462306a36Sopenharmony_ci	{"HW_SRC_1_IN_CH1", "DL4_CH1 Switch", "DL4"},
52562306a36Sopenharmony_ci	{"HW_SRC_1_IN_CH2", "DL4_CH2 Switch", "DL4"},
52662306a36Sopenharmony_ci	{"HW_SRC_2_IN_CH1", "DL4_CH1 Switch", "DL4"},
52762306a36Sopenharmony_ci	{"HW_SRC_2_IN_CH2", "DL4_CH2 Switch", "DL4"},
52862306a36Sopenharmony_ci
52962306a36Sopenharmony_ci	{"HW_SRC_1_In", NULL, "HW_SRC_1_IN_CH1"},
53062306a36Sopenharmony_ci	{"HW_SRC_1_In", NULL, "HW_SRC_1_IN_CH2"},
53162306a36Sopenharmony_ci
53262306a36Sopenharmony_ci	{"HW_SRC_2_In", NULL, "HW_SRC_2_IN_CH1"},
53362306a36Sopenharmony_ci	{"HW_SRC_2_In", NULL, "HW_SRC_2_IN_CH2"},
53462306a36Sopenharmony_ci
53562306a36Sopenharmony_ci	{"HW_SRC_1_In", NULL, HW_SRC_1_EN_W_NAME, mtk_afe_src_en_connect},
53662306a36Sopenharmony_ci	{"HW_SRC_1_Out", NULL, HW_SRC_1_EN_W_NAME, mtk_afe_src_en_connect},
53762306a36Sopenharmony_ci	{"HW_SRC_2_In", NULL, HW_SRC_2_EN_W_NAME, mtk_afe_src_en_connect},
53862306a36Sopenharmony_ci	{"HW_SRC_2_Out", NULL, HW_SRC_2_EN_W_NAME, mtk_afe_src_en_connect},
53962306a36Sopenharmony_ci
54062306a36Sopenharmony_ci	{"HW SRC 1 In Endpoint", NULL, "HW_SRC_1_In"},
54162306a36Sopenharmony_ci	{"HW SRC 2 In Endpoint", NULL, "HW_SRC_2_In"},
54262306a36Sopenharmony_ci	{"HW_SRC_1_Out", NULL, "HW SRC 1 Out Endpoint"},
54362306a36Sopenharmony_ci	{"HW_SRC_2_Out", NULL, "HW SRC 2 Out Endpoint"},
54462306a36Sopenharmony_ci};
54562306a36Sopenharmony_ci
54662306a36Sopenharmony_ci/* dai ops */
54762306a36Sopenharmony_cistatic int mtk_dai_src_hw_params(struct snd_pcm_substream *substream,
54862306a36Sopenharmony_ci				 struct snd_pcm_hw_params *params,
54962306a36Sopenharmony_ci				 struct snd_soc_dai *dai)
55062306a36Sopenharmony_ci{
55162306a36Sopenharmony_ci	struct mtk_base_afe *afe = snd_soc_dai_get_drvdata(dai);
55262306a36Sopenharmony_ci	struct mt8186_afe_private *afe_priv = afe->platform_priv;
55362306a36Sopenharmony_ci	int id = dai->id;
55462306a36Sopenharmony_ci	struct mtk_afe_src_priv *src_priv = afe_priv->dai_priv[id];
55562306a36Sopenharmony_ci	unsigned int sft, mask;
55662306a36Sopenharmony_ci	unsigned int rate = params_rate(params);
55762306a36Sopenharmony_ci	unsigned int rate_reg = mt8186_rate_transform(afe->dev, rate, id);
55862306a36Sopenharmony_ci
55962306a36Sopenharmony_ci	dev_dbg(afe->dev, "%s(), id %d, stream %d, rate %d\n",
56062306a36Sopenharmony_ci		__func__, id, substream->stream, rate);
56162306a36Sopenharmony_ci
56262306a36Sopenharmony_ci	/* rate */
56362306a36Sopenharmony_ci	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
56462306a36Sopenharmony_ci		src_priv->dl_rate = rate;
56562306a36Sopenharmony_ci		if (id == MT8186_DAI_SRC_1) {
56662306a36Sopenharmony_ci			sft = GENERAL1_ASRCIN_MODE_SFT;
56762306a36Sopenharmony_ci			mask = GENERAL1_ASRCIN_MODE_MASK;
56862306a36Sopenharmony_ci		} else {
56962306a36Sopenharmony_ci			sft = GENERAL2_ASRCIN_MODE_SFT;
57062306a36Sopenharmony_ci			mask = GENERAL2_ASRCIN_MODE_MASK;
57162306a36Sopenharmony_ci		}
57262306a36Sopenharmony_ci	} else {
57362306a36Sopenharmony_ci		src_priv->ul_rate = rate;
57462306a36Sopenharmony_ci		if (id == MT8186_DAI_SRC_1) {
57562306a36Sopenharmony_ci			sft = GENERAL1_ASRCOUT_MODE_SFT;
57662306a36Sopenharmony_ci			mask = GENERAL1_ASRCOUT_MODE_MASK;
57762306a36Sopenharmony_ci		} else {
57862306a36Sopenharmony_ci			sft = GENERAL2_ASRCOUT_MODE_SFT;
57962306a36Sopenharmony_ci			mask = GENERAL2_ASRCOUT_MODE_MASK;
58062306a36Sopenharmony_ci		}
58162306a36Sopenharmony_ci	}
58262306a36Sopenharmony_ci
58362306a36Sopenharmony_ci	regmap_update_bits(afe->regmap, GENERAL_ASRC_MODE, mask << sft, rate_reg << sft);
58462306a36Sopenharmony_ci
58562306a36Sopenharmony_ci	return 0;
58662306a36Sopenharmony_ci}
58762306a36Sopenharmony_ci
58862306a36Sopenharmony_cistatic int mtk_dai_src_hw_free(struct snd_pcm_substream *substream,
58962306a36Sopenharmony_ci			       struct snd_soc_dai *dai)
59062306a36Sopenharmony_ci{
59162306a36Sopenharmony_ci	struct mtk_base_afe *afe = snd_soc_dai_get_drvdata(dai);
59262306a36Sopenharmony_ci	struct mt8186_afe_private *afe_priv = afe->platform_priv;
59362306a36Sopenharmony_ci	int id = dai->id;
59462306a36Sopenharmony_ci	struct mtk_afe_src_priv *src_priv = afe_priv->dai_priv[id];
59562306a36Sopenharmony_ci
59662306a36Sopenharmony_ci	dev_dbg(afe->dev, "%s(), id %d, stream %d\n",
59762306a36Sopenharmony_ci		__func__, id, substream->stream);
59862306a36Sopenharmony_ci
59962306a36Sopenharmony_ci	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
60062306a36Sopenharmony_ci		src_priv->dl_rate = 0;
60162306a36Sopenharmony_ci	else
60262306a36Sopenharmony_ci		src_priv->ul_rate = 0;
60362306a36Sopenharmony_ci
60462306a36Sopenharmony_ci	return 0;
60562306a36Sopenharmony_ci}
60662306a36Sopenharmony_ci
60762306a36Sopenharmony_cistatic const struct snd_soc_dai_ops mtk_dai_src_ops = {
60862306a36Sopenharmony_ci	.hw_params = mtk_dai_src_hw_params,
60962306a36Sopenharmony_ci	.hw_free = mtk_dai_src_hw_free,
61062306a36Sopenharmony_ci};
61162306a36Sopenharmony_ci
61262306a36Sopenharmony_ci/* dai driver */
61362306a36Sopenharmony_ci#define MTK_SRC_RATES (SNDRV_PCM_RATE_8000_48000 |\
61462306a36Sopenharmony_ci		       SNDRV_PCM_RATE_88200 |\
61562306a36Sopenharmony_ci		       SNDRV_PCM_RATE_96000 |\
61662306a36Sopenharmony_ci		       SNDRV_PCM_RATE_176400 |\
61762306a36Sopenharmony_ci		       SNDRV_PCM_RATE_192000)
61862306a36Sopenharmony_ci
61962306a36Sopenharmony_ci#define MTK_SRC_FORMATS (SNDRV_PCM_FMTBIT_S16_LE |\
62062306a36Sopenharmony_ci			 SNDRV_PCM_FMTBIT_S24_LE |\
62162306a36Sopenharmony_ci			 SNDRV_PCM_FMTBIT_S32_LE)
62262306a36Sopenharmony_ci
62362306a36Sopenharmony_cistatic struct snd_soc_dai_driver mtk_dai_src_driver[] = {
62462306a36Sopenharmony_ci	{
62562306a36Sopenharmony_ci		.name = "HW_SRC_1",
62662306a36Sopenharmony_ci		.id = MT8186_DAI_SRC_1,
62762306a36Sopenharmony_ci		.playback = {
62862306a36Sopenharmony_ci			.stream_name = "HW_SRC_1_In",
62962306a36Sopenharmony_ci			.channels_min = 1,
63062306a36Sopenharmony_ci			.channels_max = 2,
63162306a36Sopenharmony_ci			.rates = MTK_SRC_RATES,
63262306a36Sopenharmony_ci			.formats = MTK_SRC_FORMATS,
63362306a36Sopenharmony_ci		},
63462306a36Sopenharmony_ci		.capture = {
63562306a36Sopenharmony_ci			.stream_name = "HW_SRC_1_Out",
63662306a36Sopenharmony_ci			.channels_min = 1,
63762306a36Sopenharmony_ci			.channels_max = 2,
63862306a36Sopenharmony_ci			.rates = MTK_SRC_RATES,
63962306a36Sopenharmony_ci			.formats = MTK_SRC_FORMATS,
64062306a36Sopenharmony_ci		},
64162306a36Sopenharmony_ci		.ops = &mtk_dai_src_ops,
64262306a36Sopenharmony_ci	},
64362306a36Sopenharmony_ci	{
64462306a36Sopenharmony_ci		.name = "HW_SRC_2",
64562306a36Sopenharmony_ci		.id = MT8186_DAI_SRC_2,
64662306a36Sopenharmony_ci		.playback = {
64762306a36Sopenharmony_ci			.stream_name = "HW_SRC_2_In",
64862306a36Sopenharmony_ci			.channels_min = 1,
64962306a36Sopenharmony_ci			.channels_max = 2,
65062306a36Sopenharmony_ci			.rates = MTK_SRC_RATES,
65162306a36Sopenharmony_ci			.formats = MTK_SRC_FORMATS,
65262306a36Sopenharmony_ci		},
65362306a36Sopenharmony_ci		.capture = {
65462306a36Sopenharmony_ci			.stream_name = "HW_SRC_2_Out",
65562306a36Sopenharmony_ci			.channels_min = 1,
65662306a36Sopenharmony_ci			.channels_max = 2,
65762306a36Sopenharmony_ci			.rates = MTK_SRC_RATES,
65862306a36Sopenharmony_ci			.formats = MTK_SRC_FORMATS,
65962306a36Sopenharmony_ci		},
66062306a36Sopenharmony_ci		.ops = &mtk_dai_src_ops,
66162306a36Sopenharmony_ci	},
66262306a36Sopenharmony_ci};
66362306a36Sopenharmony_ci
66462306a36Sopenharmony_ciint mt8186_dai_src_register(struct mtk_base_afe *afe)
66562306a36Sopenharmony_ci{
66662306a36Sopenharmony_ci	struct mtk_base_afe_dai *dai;
66762306a36Sopenharmony_ci	int ret;
66862306a36Sopenharmony_ci
66962306a36Sopenharmony_ci	dai = devm_kzalloc(afe->dev, sizeof(*dai), GFP_KERNEL);
67062306a36Sopenharmony_ci	if (!dai)
67162306a36Sopenharmony_ci		return -ENOMEM;
67262306a36Sopenharmony_ci
67362306a36Sopenharmony_ci	list_add(&dai->list, &afe->sub_dais);
67462306a36Sopenharmony_ci
67562306a36Sopenharmony_ci	dai->dai_drivers = mtk_dai_src_driver;
67662306a36Sopenharmony_ci	dai->num_dai_drivers = ARRAY_SIZE(mtk_dai_src_driver);
67762306a36Sopenharmony_ci
67862306a36Sopenharmony_ci	dai->dapm_widgets = mtk_dai_src_widgets;
67962306a36Sopenharmony_ci	dai->num_dapm_widgets = ARRAY_SIZE(mtk_dai_src_widgets);
68062306a36Sopenharmony_ci	dai->dapm_routes = mtk_dai_src_routes;
68162306a36Sopenharmony_ci	dai->num_dapm_routes = ARRAY_SIZE(mtk_dai_src_routes);
68262306a36Sopenharmony_ci
68362306a36Sopenharmony_ci	/* set dai priv */
68462306a36Sopenharmony_ci	ret = mt8186_dai_set_priv(afe, MT8186_DAI_SRC_1,
68562306a36Sopenharmony_ci				  sizeof(struct mtk_afe_src_priv), NULL);
68662306a36Sopenharmony_ci	if (ret)
68762306a36Sopenharmony_ci		return ret;
68862306a36Sopenharmony_ci
68962306a36Sopenharmony_ci	ret = mt8186_dai_set_priv(afe, MT8186_DAI_SRC_2,
69062306a36Sopenharmony_ci				  sizeof(struct mtk_afe_src_priv), NULL);
69162306a36Sopenharmony_ci	if (ret)
69262306a36Sopenharmony_ci		return ret;
69362306a36Sopenharmony_ci
69462306a36Sopenharmony_ci	return 0;
69562306a36Sopenharmony_ci}
696