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