Path: blob/master/sound/soc/mediatek/mt8186/mt8186-dai-src.c
26488 views
// SPDX-License-Identifier: GPL-2.01//2// MediaTek ALSA SoC Audio DAI SRC Control3//4// Copyright (c) 2022 MediaTek Inc.5// Author: Jiaxin Yu <[email protected]>67#include <linux/regmap.h>8#include "mt8186-afe-common.h"9#include "mt8186-interconnection.h"1011struct mtk_afe_src_priv {12int dl_rate;13int ul_rate;14};1516static const unsigned int src_iir_coeff_32_to_16[] = {170x0dbae6, 0xff9b0a, 0x0dbae6, 0x05e488, 0xe072b9, 0x000002,180x0dbae6, 0x000f3b, 0x0dbae6, 0x06a537, 0xe17d79, 0x000002,190x0dbae6, 0x01246a, 0x0dbae6, 0x087261, 0xe306be, 0x000002,200x0dbae6, 0x03437d, 0x0dbae6, 0x0bc16f, 0xe57c87, 0x000002,210x0dbae6, 0x072981, 0x0dbae6, 0x111dd3, 0xe94f2a, 0x000002,220x0dbae6, 0x0dc4a6, 0x0dbae6, 0x188611, 0xee85a0, 0x000002,230x0dbae6, 0x168b9a, 0x0dbae6, 0x200e8f, 0xf3ccf1, 0x000002,240x000000, 0x1b75cb, 0x1b75cb, 0x2374a2, 0x000000, 0x00000125};2627static const unsigned int src_iir_coeff_44_to_16[] = {280x09ae28, 0xf7d97d, 0x09ae28, 0x212a3d, 0xe0ac3a, 0x000002,290x09ae28, 0xf8525a, 0x09ae28, 0x216d72, 0xe234be, 0x000002,300x09ae28, 0xf980f5, 0x09ae28, 0x22a057, 0xe45a81, 0x000002,310x09ae28, 0xfc0a08, 0x09ae28, 0x24d3bd, 0xe7752d, 0x000002,320x09ae28, 0x016162, 0x09ae28, 0x27da01, 0xeb6ea8, 0x000002,330x09ae28, 0x0b67df, 0x09ae28, 0x2aca4a, 0xef34c4, 0x000002,340x000000, 0x135c50, 0x135c50, 0x2c1079, 0x000000, 0x00000135};3637static const unsigned int src_iir_coeff_44_to_32[] = {380x096966, 0x0c4d35, 0x096966, 0xedee81, 0xf05070, 0x000003,390x12d2cc, 0x193910, 0x12d2cc, 0xddbf4f, 0xe21e1d, 0x000002,400x12d2cc, 0x1a9e60, 0x12d2cc, 0xe18916, 0xe470fd, 0x000002,410x12d2cc, 0x1d06e0, 0x12d2cc, 0xe8a4a6, 0xe87b24, 0x000002,420x12d2cc, 0x207578, 0x12d2cc, 0xf4fe62, 0xef5917, 0x000002,430x12d2cc, 0x24055f, 0x12d2cc, 0x05ee2b, 0xf8b502, 0x000002,440x000000, 0x25a599, 0x25a599, 0x0fabe2, 0x000000, 0x00000145};4647static const unsigned int src_iir_coeff_48_to_16[] = {480x0296a4, 0xfd69dd, 0x0296a4, 0x209439, 0xe01ff9, 0x000002,490x0f4ff3, 0xf0d6d4, 0x0f4ff3, 0x209bc9, 0xe076c3, 0x000002,500x0e8490, 0xf1fe63, 0x0e8490, 0x20cfd6, 0xe12124, 0x000002,510x14852f, 0xed794a, 0x14852f, 0x21503d, 0xe28b32, 0x000002,520x136222, 0xf17677, 0x136222, 0x225be1, 0xe56964, 0x000002,530x0a8d85, 0xfc4a97, 0x0a8d85, 0x24310c, 0xea6952, 0x000002,540x05eff5, 0x043455, 0x05eff5, 0x4ced8f, 0xe134d6, 0x000001,550x000000, 0x3aebe6, 0x3aebe6, 0x04f3b0, 0x000000, 0x00000456};5758static const unsigned int src_iir_coeff_48_to_32[] = {590x10c1b8, 0x10a7df, 0x10c1b8, 0xe7514e, 0xe0b41f, 0x000002,600x10c1b8, 0x116257, 0x10c1b8, 0xe9402f, 0xe25aaa, 0x000002,610x10c1b8, 0x130c89, 0x10c1b8, 0xed3cc3, 0xe4dddb, 0x000002,620x10c1b8, 0x1600dd, 0x10c1b8, 0xf48000, 0xe90c55, 0x000002,630x10c1b8, 0x1a672e, 0x10c1b8, 0x00494c, 0xefa807, 0x000002,640x10c1b8, 0x1f38e6, 0x10c1b8, 0x0ee076, 0xf7c5f3, 0x000002,650x000000, 0x218370, 0x218370, 0x168b40, 0x000000, 0x00000166};6768static const unsigned int src_iir_coeff_48_to_44[] = {690x0bf71c, 0x170f3f, 0x0bf71c, 0xe3a4c8, 0xf096cb, 0x000003,700x0bf71c, 0x17395e, 0x0bf71c, 0xe58085, 0xf210c8, 0x000003,710x0bf71c, 0x1782bd, 0x0bf71c, 0xe95ef6, 0xf4c899, 0x000003,720x0bf71c, 0x17cd97, 0x0bf71c, 0xf1608a, 0xfa3b18, 0x000003,730x000000, 0x2fdc6f, 0x2fdc6f, 0xf15663, 0x000000, 0x00000174};7576static const unsigned int src_iir_coeff_96_to_16[] = {770x0805a1, 0xf21ae3, 0x0805a1, 0x3840bb, 0xe02a2e, 0x000002,780x0d5dd8, 0xe8f259, 0x0d5dd8, 0x1c0af6, 0xf04700, 0x000003,790x0bb422, 0xec08d9, 0x0bb422, 0x1bfccc, 0xf09216, 0x000003,800x08fde6, 0xf108be, 0x08fde6, 0x1bf096, 0xf10ae0, 0x000003,810x0ae311, 0xeeeda3, 0x0ae311, 0x37c646, 0xe385f5, 0x000002,820x044089, 0xfa7242, 0x044089, 0x37a785, 0xe56526, 0x000002,830x00c75c, 0xffb947, 0x00c75c, 0x378ba3, 0xe72c5f, 0x000002,840x000000, 0x0ef76e, 0x0ef76e, 0x377fda, 0x000000, 0x000001,85};8687static const unsigned int src_iir_coeff_96_to_44[] = {880x08b543, 0xfd80f4, 0x08b543, 0x0e2332, 0xe06ed0, 0x000002,890x1b6038, 0xf90e7e, 0x1b6038, 0x0ec1ac, 0xe16f66, 0x000002,900x188478, 0xfbb921, 0x188478, 0x105859, 0xe2e596, 0x000002,910x13eff3, 0xffa707, 0x13eff3, 0x13455c, 0xe533b7, 0x000002,920x0dc239, 0x03d458, 0x0dc239, 0x17f120, 0xe8b617, 0x000002,930x0745f1, 0x05d790, 0x0745f1, 0x1e3d75, 0xed5f18, 0x000002,940x05641f, 0x085e2b, 0x05641f, 0x48efd0, 0xe3e9c8, 0x000001,950x000000, 0x28f632, 0x28f632, 0x273905, 0x000000, 0x000001,96};9798static unsigned int mtk_get_src_freq_mode(struct mtk_base_afe *afe, int rate)99{100switch (rate) {101case 8000:102return 0x50000;103case 11025:104return 0x6e400;105case 12000:106return 0x78000;107case 16000:108return 0xa0000;109case 22050:110return 0xdc800;111case 24000:112return 0xf0000;113case 32000:114return 0x140000;115case 44100:116return 0x1b9000;117case 48000:118return 0x1e0000;119case 88200:120return 0x372000;121case 96000:122return 0x3c0000;123case 176400:124return 0x6e4000;125case 192000:126return 0x780000;127default:128dev_err(afe->dev, "%s(), rate %d invalid!!!\n",129__func__, rate);130return 0;131}132}133134static const unsigned int *get_iir_coeff(unsigned int rate_in,135unsigned int rate_out,136unsigned int *param_num)137{138if (rate_in == 32000 && rate_out == 16000) {139*param_num = ARRAY_SIZE(src_iir_coeff_32_to_16);140return src_iir_coeff_32_to_16;141} else if (rate_in == 44100 && rate_out == 16000) {142*param_num = ARRAY_SIZE(src_iir_coeff_44_to_16);143return src_iir_coeff_44_to_16;144} else if (rate_in == 44100 && rate_out == 32000) {145*param_num = ARRAY_SIZE(src_iir_coeff_44_to_32);146return src_iir_coeff_44_to_32;147} else if ((rate_in == 48000 && rate_out == 16000) ||148(rate_in == 96000 && rate_out == 32000)) {149*param_num = ARRAY_SIZE(src_iir_coeff_48_to_16);150return src_iir_coeff_48_to_16;151} else if (rate_in == 48000 && rate_out == 32000) {152*param_num = ARRAY_SIZE(src_iir_coeff_48_to_32);153return src_iir_coeff_48_to_32;154} else if (rate_in == 48000 && rate_out == 44100) {155*param_num = ARRAY_SIZE(src_iir_coeff_48_to_44);156return src_iir_coeff_48_to_44;157} else if (rate_in == 96000 && rate_out == 16000) {158*param_num = ARRAY_SIZE(src_iir_coeff_96_to_16);159return src_iir_coeff_96_to_16;160} else if ((rate_in == 96000 && rate_out == 44100) ||161(rate_in == 48000 && rate_out == 22050)) {162*param_num = ARRAY_SIZE(src_iir_coeff_96_to_44);163return src_iir_coeff_96_to_44;164}165166*param_num = 0;167return NULL;168}169170static int mtk_set_src_1_param(struct mtk_base_afe *afe, int id)171{172struct mt8186_afe_private *afe_priv = afe->platform_priv;173struct mtk_afe_src_priv *src_priv = afe_priv->dai_priv[id];174unsigned int iir_coeff_num;175unsigned int iir_stage;176int rate_in = src_priv->dl_rate;177int rate_out = src_priv->ul_rate;178unsigned int out_freq_mode = mtk_get_src_freq_mode(afe, rate_out);179unsigned int in_freq_mode = mtk_get_src_freq_mode(afe, rate_in);180181/* set out freq mode */182regmap_update_bits(afe->regmap, AFE_GENERAL1_ASRC_2CH_CON3,183G_SRC_ASM_FREQ_4_MASK_SFT,184out_freq_mode << G_SRC_ASM_FREQ_4_SFT);185186/* set in freq mode */187regmap_update_bits(afe->regmap, AFE_GENERAL1_ASRC_2CH_CON4,188G_SRC_ASM_FREQ_5_MASK_SFT,189in_freq_mode << G_SRC_ASM_FREQ_5_SFT);190191regmap_write(afe->regmap, AFE_GENERAL1_ASRC_2CH_CON5, 0x3f5986);192regmap_write(afe->regmap, AFE_GENERAL1_ASRC_2CH_CON5, 0x3f5987);193regmap_write(afe->regmap, AFE_GENERAL1_ASRC_2CH_CON6, 0x1fbd);194regmap_write(afe->regmap, AFE_GENERAL1_ASRC_2CH_CON2, 0);195196/* set iir if in_rate > out_rate */197if (rate_in > rate_out) {198int i;199const unsigned int *iir_coeff = get_iir_coeff(rate_in, rate_out,200&iir_coeff_num);201202if (iir_coeff_num == 0 || !iir_coeff) {203dev_err(afe->dev, "%s(), iir coeff error, num %d, coeff %p\n",204__func__, iir_coeff_num, iir_coeff);205return -EINVAL;206}207208/* COEFF_SRAM_CTRL */209regmap_update_bits(afe->regmap, AFE_GENERAL1_ASRC_2CH_CON0,210G_SRC_COEFF_SRAM_CTRL_MASK_SFT,211BIT(G_SRC_COEFF_SRAM_CTRL_SFT));212/* Clear coeff history to r/w coeff from the first position */213regmap_update_bits(afe->regmap, AFE_GENERAL1_ASRC_2CH_CON13,214G_SRC_COEFF_SRAM_ADR_MASK_SFT, 0);215/* Write SRC coeff, should not read the reg during write */216for (i = 0; i < iir_coeff_num; i++)217regmap_write(afe->regmap, AFE_GENERAL1_ASRC_2CH_CON12,218iir_coeff[i]);219/* disable sram access */220regmap_update_bits(afe->regmap, AFE_GENERAL1_ASRC_2CH_CON0,221G_SRC_COEFF_SRAM_CTRL_MASK_SFT, 0);222/* CHSET_IIR_STAGE */223iir_stage = (iir_coeff_num / 6) - 1;224regmap_update_bits(afe->regmap, AFE_GENERAL1_ASRC_2CH_CON2,225G_SRC_CHSET_IIR_STAGE_MASK_SFT,226iir_stage << G_SRC_CHSET_IIR_STAGE_SFT);227/* CHSET_IIR_EN */228regmap_update_bits(afe->regmap, AFE_GENERAL1_ASRC_2CH_CON2,229G_SRC_CHSET_IIR_EN_MASK_SFT,230BIT(G_SRC_CHSET_IIR_EN_SFT));231} else {232/* CHSET_IIR_EN off */233regmap_update_bits(afe->regmap, AFE_GENERAL1_ASRC_2CH_CON2,234G_SRC_CHSET_IIR_EN_MASK_SFT, 0);235}236237return 0;238}239240static int mtk_set_src_2_param(struct mtk_base_afe *afe, int id)241{242struct mt8186_afe_private *afe_priv = afe->platform_priv;243struct mtk_afe_src_priv *src_priv = afe_priv->dai_priv[id];244unsigned int iir_coeff_num;245unsigned int iir_stage;246int rate_in = src_priv->dl_rate;247int rate_out = src_priv->ul_rate;248unsigned int out_freq_mode = mtk_get_src_freq_mode(afe, rate_out);249unsigned int in_freq_mode = mtk_get_src_freq_mode(afe, rate_in);250251/* set out freq mode */252regmap_update_bits(afe->regmap, AFE_GENERAL2_ASRC_2CH_CON3,253G_SRC_ASM_FREQ_4_MASK_SFT,254out_freq_mode << G_SRC_ASM_FREQ_4_SFT);255256/* set in freq mode */257regmap_update_bits(afe->regmap, AFE_GENERAL2_ASRC_2CH_CON4,258G_SRC_ASM_FREQ_5_MASK_SFT,259in_freq_mode << G_SRC_ASM_FREQ_5_SFT);260261regmap_write(afe->regmap, AFE_GENERAL2_ASRC_2CH_CON5, 0x3f5986);262regmap_write(afe->regmap, AFE_GENERAL2_ASRC_2CH_CON5, 0x3f5987);263regmap_write(afe->regmap, AFE_GENERAL2_ASRC_2CH_CON6, 0x1fbd);264regmap_write(afe->regmap, AFE_GENERAL2_ASRC_2CH_CON2, 0);265266/* set iir if in_rate > out_rate */267if (rate_in > rate_out) {268int i;269const unsigned int *iir_coeff = get_iir_coeff(rate_in, rate_out,270&iir_coeff_num);271272if (iir_coeff_num == 0 || !iir_coeff) {273dev_err(afe->dev, "%s(), iir coeff error, num %d, coeff %p\n",274__func__, iir_coeff_num, iir_coeff);275return -EINVAL;276}277278/* COEFF_SRAM_CTRL */279regmap_update_bits(afe->regmap, AFE_GENERAL2_ASRC_2CH_CON0,280G_SRC_COEFF_SRAM_CTRL_MASK_SFT,281BIT(G_SRC_COEFF_SRAM_CTRL_SFT));282/* Clear coeff history to r/w coeff from the first position */283regmap_update_bits(afe->regmap, AFE_GENERAL2_ASRC_2CH_CON13,284G_SRC_COEFF_SRAM_ADR_MASK_SFT, 0);285/* Write SRC coeff, should not read the reg during write */286for (i = 0; i < iir_coeff_num; i++)287regmap_write(afe->regmap, AFE_GENERAL2_ASRC_2CH_CON12,288iir_coeff[i]);289/* disable sram access */290regmap_update_bits(afe->regmap, AFE_GENERAL2_ASRC_2CH_CON0,291G_SRC_COEFF_SRAM_CTRL_MASK_SFT, 0);292/* CHSET_IIR_STAGE */293iir_stage = (iir_coeff_num / 6) - 1;294regmap_update_bits(afe->regmap, AFE_GENERAL2_ASRC_2CH_CON2,295G_SRC_CHSET_IIR_STAGE_MASK_SFT,296iir_stage << G_SRC_CHSET_IIR_STAGE_SFT);297/* CHSET_IIR_EN */298regmap_update_bits(afe->regmap, AFE_GENERAL2_ASRC_2CH_CON2,299G_SRC_CHSET_IIR_EN_MASK_SFT,300BIT(G_SRC_CHSET_IIR_EN_SFT));301} else {302/* CHSET_IIR_EN off */303regmap_update_bits(afe->regmap, AFE_GENERAL2_ASRC_2CH_CON2,304G_SRC_CHSET_IIR_EN_MASK_SFT, 0);305}306307return 0;308}309310#define HW_SRC_1_EN_W_NAME "HW_SRC_1_Enable"311#define HW_SRC_2_EN_W_NAME "HW_SRC_2_Enable"312313static int mtk_hw_src_event(struct snd_soc_dapm_widget *w,314struct snd_kcontrol *kcontrol,315int event)316{317struct snd_soc_component *cmpnt = snd_soc_dapm_to_component(w->dapm);318struct mtk_base_afe *afe = snd_soc_component_get_drvdata(cmpnt);319struct mt8186_afe_private *afe_priv = afe->platform_priv;320int id;321struct mtk_afe_src_priv *src_priv;322unsigned int reg;323324if (snd_soc_dapm_widget_name_cmp(w, HW_SRC_1_EN_W_NAME) == 0)325id = MT8186_DAI_SRC_1;326else327id = MT8186_DAI_SRC_2;328329src_priv = afe_priv->dai_priv[id];330331dev_dbg(afe->dev,332"%s(), name %s, event 0x%x, id %d, src_priv %p, dl_rate %d, ul_rate %d\n",333__func__, w->name, event, id, src_priv,334src_priv->dl_rate, src_priv->ul_rate);335336switch (event) {337case SND_SOC_DAPM_PRE_PMU:338if (id == MT8186_DAI_SRC_1)339mtk_set_src_1_param(afe, id);340else341mtk_set_src_2_param(afe, id);342break;343case SND_SOC_DAPM_POST_PMU:344reg = (id == MT8186_DAI_SRC_1) ?345AFE_GENERAL1_ASRC_2CH_CON0 : AFE_GENERAL2_ASRC_2CH_CON0;346/* ASM_ON */347regmap_update_bits(afe->regmap, reg,348G_SRC_ASM_ON_MASK_SFT,349BIT(G_SRC_ASM_ON_SFT));350/* CHSET_ON */351regmap_update_bits(afe->regmap, reg,352G_SRC_CHSET_ON_MASK_SFT,353BIT(G_SRC_CHSET_ON_SFT));354/* CHSET_STR_CLR */355regmap_update_bits(afe->regmap, reg,356G_SRC_CHSET_STR_CLR_MASK_SFT,357BIT(G_SRC_CHSET_STR_CLR_SFT));358break;359case SND_SOC_DAPM_PRE_PMD:360reg = (id == MT8186_DAI_SRC_1) ?361AFE_GENERAL1_ASRC_2CH_CON0 : AFE_GENERAL2_ASRC_2CH_CON0;362/* ASM_OFF */363regmap_update_bits(afe->regmap, reg, G_SRC_ASM_ON_MASK_SFT, 0);364/* CHSET_OFF */365regmap_update_bits(afe->regmap, reg, G_SRC_CHSET_ON_MASK_SFT, 0);366/* CHSET_STR_CLR */367regmap_update_bits(afe->regmap, reg, G_SRC_CHSET_STR_CLR_MASK_SFT, 0);368break;369default:370break;371}372373return 0;374}375376/* dai component */377static const struct snd_kcontrol_new mtk_hw_src_1_in_ch1_mix[] = {378SOC_DAPM_SINGLE_AUTODISABLE("DL1_CH1 Switch", AFE_CONN40,379I_DL1_CH1, 1, 0),380SOC_DAPM_SINGLE_AUTODISABLE("DL2_CH1 Switch", AFE_CONN40,381I_DL2_CH1, 1, 0),382SOC_DAPM_SINGLE_AUTODISABLE("DL3_CH1 Switch", AFE_CONN40,383I_DL3_CH1, 1, 0),384SOC_DAPM_SINGLE_AUTODISABLE("DL4_CH1 Switch", AFE_CONN40_1,385I_DL4_CH1, 1, 0),386SOC_DAPM_SINGLE_AUTODISABLE("DL6_CH1 Switch", AFE_CONN40_1,387I_DL6_CH1, 1, 0),388SOC_DAPM_SINGLE_AUTODISABLE("I2S0_CH1 Switch", AFE_CONN40,389I_I2S0_CH1, 1, 0),390SOC_DAPM_SINGLE_AUTODISABLE("DL5_CH1 Switch", AFE_CONN40_1,391I_DL5_CH1, 1, 0),392};393394static const struct snd_kcontrol_new mtk_hw_src_1_in_ch2_mix[] = {395SOC_DAPM_SINGLE_AUTODISABLE("DL1_CH2 Switch", AFE_CONN41,396I_DL1_CH2, 1, 0),397SOC_DAPM_SINGLE_AUTODISABLE("DL2_CH2 Switch", AFE_CONN41,398I_DL2_CH2, 1, 0),399SOC_DAPM_SINGLE_AUTODISABLE("DL3_CH2 Switch", AFE_CONN41,400I_DL3_CH2, 1, 0),401SOC_DAPM_SINGLE_AUTODISABLE("DL4_CH2 Switch", AFE_CONN41_1,402I_DL4_CH2, 1, 0),403SOC_DAPM_SINGLE_AUTODISABLE("DL6_CH2 Switch", AFE_CONN41_1,404I_DL6_CH2, 1, 0),405SOC_DAPM_SINGLE_AUTODISABLE("I2S0_CH2 Switch", AFE_CONN41,406I_I2S0_CH2, 1, 0),407SOC_DAPM_SINGLE_AUTODISABLE("DL5_CH2 Switch", AFE_CONN41_1,408I_DL5_CH2, 1, 0),409};410411static const struct snd_kcontrol_new mtk_hw_src_2_in_ch1_mix[] = {412SOC_DAPM_SINGLE_AUTODISABLE("DL1_CH1 Switch", AFE_CONN42,413I_DL1_CH1, 1, 0),414SOC_DAPM_SINGLE_AUTODISABLE("DL2_CH1 Switch", AFE_CONN42,415I_DL2_CH1, 1, 0),416SOC_DAPM_SINGLE_AUTODISABLE("DL3_CH1 Switch", AFE_CONN42,417I_DL3_CH1, 1, 0),418SOC_DAPM_SINGLE_AUTODISABLE("DL4_CH1 Switch", AFE_CONN42,419I_DL4_CH1, 1, 0),420SOC_DAPM_SINGLE_AUTODISABLE("DL5_CH1 Switch", AFE_CONN42_1,421I_DL5_CH1, 1, 0),422SOC_DAPM_SINGLE_AUTODISABLE("DL6_CH1 Switch", AFE_CONN42_1,423I_DL6_CH1, 1, 0),424SOC_DAPM_SINGLE_AUTODISABLE("HW_GAIN2_OUT_CH1 Switch", AFE_CONN42,425I_GAIN2_OUT_CH1, 1, 0),426};427428static const struct snd_kcontrol_new mtk_hw_src_2_in_ch2_mix[] = {429SOC_DAPM_SINGLE_AUTODISABLE("DL1_CH2 Switch", AFE_CONN43,430I_DL1_CH2, 1, 0),431SOC_DAPM_SINGLE_AUTODISABLE("DL2_CH2 Switch", AFE_CONN43,432I_DL2_CH2, 1, 0),433SOC_DAPM_SINGLE_AUTODISABLE("DL3_CH2 Switch", AFE_CONN43,434I_DL3_CH2, 1, 0),435SOC_DAPM_SINGLE_AUTODISABLE("DL4_CH2 Switch", AFE_CONN43,436I_DL4_CH2, 1, 0),437SOC_DAPM_SINGLE_AUTODISABLE("DL5_CH2 Switch", AFE_CONN43_1,438I_DL5_CH2, 1, 0),439SOC_DAPM_SINGLE_AUTODISABLE("DL6_CH2 Switch", AFE_CONN43_1,440I_DL6_CH2, 1, 0),441SOC_DAPM_SINGLE_AUTODISABLE("HW_GAIN2_OUT_CH2 Switch", AFE_CONN43,442I_GAIN2_OUT_CH2, 1, 0),443};444445static const struct snd_soc_dapm_widget mtk_dai_src_widgets[] = {446/* inter-connections */447SND_SOC_DAPM_MIXER("HW_SRC_1_IN_CH1", SND_SOC_NOPM, 0, 0,448mtk_hw_src_1_in_ch1_mix,449ARRAY_SIZE(mtk_hw_src_1_in_ch1_mix)),450SND_SOC_DAPM_MIXER("HW_SRC_1_IN_CH2", SND_SOC_NOPM, 0, 0,451mtk_hw_src_1_in_ch2_mix,452ARRAY_SIZE(mtk_hw_src_1_in_ch2_mix)),453SND_SOC_DAPM_MIXER("HW_SRC_2_IN_CH1", SND_SOC_NOPM, 0, 0,454mtk_hw_src_2_in_ch1_mix,455ARRAY_SIZE(mtk_hw_src_2_in_ch1_mix)),456SND_SOC_DAPM_MIXER("HW_SRC_2_IN_CH2", SND_SOC_NOPM, 0, 0,457mtk_hw_src_2_in_ch2_mix,458ARRAY_SIZE(mtk_hw_src_2_in_ch2_mix)),459460SND_SOC_DAPM_SUPPLY(HW_SRC_1_EN_W_NAME,461GENERAL_ASRC_EN_ON, GENERAL1_ASRC_EN_ON_SFT, 0,462mtk_hw_src_event,463SND_SOC_DAPM_PRE_PMU |464SND_SOC_DAPM_POST_PMU |465SND_SOC_DAPM_PRE_PMD),466467SND_SOC_DAPM_SUPPLY(HW_SRC_2_EN_W_NAME,468GENERAL_ASRC_EN_ON, GENERAL2_ASRC_EN_ON_SFT, 0,469mtk_hw_src_event,470SND_SOC_DAPM_PRE_PMU |471SND_SOC_DAPM_POST_PMU |472SND_SOC_DAPM_PRE_PMD),473474SND_SOC_DAPM_INPUT("HW SRC 1 Out Endpoint"),475SND_SOC_DAPM_INPUT("HW SRC 2 Out Endpoint"),476SND_SOC_DAPM_OUTPUT("HW SRC 1 In Endpoint"),477SND_SOC_DAPM_OUTPUT("HW SRC 2 In Endpoint"),478};479480static int mtk_afe_src_en_connect(struct snd_soc_dapm_widget *source,481struct snd_soc_dapm_widget *sink)482{483struct snd_soc_dapm_widget *w = source;484struct snd_soc_component *cmpnt = snd_soc_dapm_to_component(w->dapm);485struct mtk_base_afe *afe = snd_soc_component_get_drvdata(cmpnt);486struct mt8186_afe_private *afe_priv = afe->platform_priv;487struct mtk_afe_src_priv *src_priv;488489if (snd_soc_dapm_widget_name_cmp(w, HW_SRC_1_EN_W_NAME) == 0)490src_priv = afe_priv->dai_priv[MT8186_DAI_SRC_1];491else492src_priv = afe_priv->dai_priv[MT8186_DAI_SRC_2];493494dev_dbg(afe->dev,495"%s(), source %s, sink %s, dl_rate %d, ul_rate %d\n",496__func__, source->name, sink->name,497src_priv->dl_rate, src_priv->ul_rate);498499return (src_priv->dl_rate > 0 && src_priv->ul_rate > 0) ? 1 : 0;500}501502static const struct snd_soc_dapm_route mtk_dai_src_routes[] = {503{"HW_SRC_1_IN_CH1", "DL1_CH1 Switch", "DL1"},504{"HW_SRC_1_IN_CH2", "DL1_CH2 Switch", "DL1"},505{"HW_SRC_2_IN_CH1", "DL1_CH1 Switch", "DL1"},506{"HW_SRC_2_IN_CH2", "DL1_CH2 Switch", "DL1"},507{"HW_SRC_1_IN_CH1", "DL2_CH1 Switch", "DL2"},508{"HW_SRC_1_IN_CH2", "DL2_CH2 Switch", "DL2"},509{"HW_SRC_2_IN_CH1", "DL2_CH1 Switch", "DL2"},510{"HW_SRC_2_IN_CH2", "DL2_CH2 Switch", "DL2"},511{"HW_SRC_1_IN_CH1", "DL3_CH1 Switch", "DL3"},512{"HW_SRC_1_IN_CH2", "DL3_CH2 Switch", "DL3"},513{"HW_SRC_2_IN_CH1", "DL3_CH1 Switch", "DL3"},514{"HW_SRC_2_IN_CH2", "DL3_CH2 Switch", "DL3"},515{"HW_SRC_1_IN_CH1", "DL6_CH1 Switch", "DL6"},516{"HW_SRC_1_IN_CH2", "DL6_CH2 Switch", "DL6"},517{"HW_SRC_2_IN_CH1", "DL6_CH1 Switch", "DL6"},518{"HW_SRC_2_IN_CH2", "DL6_CH2 Switch", "DL6"},519{"HW_SRC_1_IN_CH1", "DL5_CH1 Switch", "DL5"},520{"HW_SRC_1_IN_CH2", "DL5_CH2 Switch", "DL5"},521{"HW_SRC_2_IN_CH1", "DL5_CH1 Switch", "DL5"},522{"HW_SRC_2_IN_CH2", "DL5_CH2 Switch", "DL5"},523{"HW_SRC_1_IN_CH1", "DL4_CH1 Switch", "DL4"},524{"HW_SRC_1_IN_CH2", "DL4_CH2 Switch", "DL4"},525{"HW_SRC_2_IN_CH1", "DL4_CH1 Switch", "DL4"},526{"HW_SRC_2_IN_CH2", "DL4_CH2 Switch", "DL4"},527528{"HW_SRC_1_In", NULL, "HW_SRC_1_IN_CH1"},529{"HW_SRC_1_In", NULL, "HW_SRC_1_IN_CH2"},530531{"HW_SRC_2_In", NULL, "HW_SRC_2_IN_CH1"},532{"HW_SRC_2_In", NULL, "HW_SRC_2_IN_CH2"},533534{"HW_SRC_1_In", NULL, HW_SRC_1_EN_W_NAME, mtk_afe_src_en_connect},535{"HW_SRC_1_Out", NULL, HW_SRC_1_EN_W_NAME, mtk_afe_src_en_connect},536{"HW_SRC_2_In", NULL, HW_SRC_2_EN_W_NAME, mtk_afe_src_en_connect},537{"HW_SRC_2_Out", NULL, HW_SRC_2_EN_W_NAME, mtk_afe_src_en_connect},538539{"HW SRC 1 In Endpoint", NULL, "HW_SRC_1_In"},540{"HW SRC 2 In Endpoint", NULL, "HW_SRC_2_In"},541{"HW_SRC_1_Out", NULL, "HW SRC 1 Out Endpoint"},542{"HW_SRC_2_Out", NULL, "HW SRC 2 Out Endpoint"},543};544545/* dai ops */546static int mtk_dai_src_hw_params(struct snd_pcm_substream *substream,547struct snd_pcm_hw_params *params,548struct snd_soc_dai *dai)549{550struct mtk_base_afe *afe = snd_soc_dai_get_drvdata(dai);551struct mt8186_afe_private *afe_priv = afe->platform_priv;552int id = dai->id;553struct mtk_afe_src_priv *src_priv = afe_priv->dai_priv[id];554unsigned int sft, mask;555unsigned int rate = params_rate(params);556unsigned int rate_reg = mt8186_rate_transform(afe->dev, rate, id);557558dev_dbg(afe->dev, "%s(), id %d, stream %d, rate %d\n",559__func__, id, substream->stream, rate);560561/* rate */562if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {563src_priv->dl_rate = rate;564if (id == MT8186_DAI_SRC_1) {565sft = GENERAL1_ASRCIN_MODE_SFT;566mask = GENERAL1_ASRCIN_MODE_MASK;567} else {568sft = GENERAL2_ASRCIN_MODE_SFT;569mask = GENERAL2_ASRCIN_MODE_MASK;570}571} else {572src_priv->ul_rate = rate;573if (id == MT8186_DAI_SRC_1) {574sft = GENERAL1_ASRCOUT_MODE_SFT;575mask = GENERAL1_ASRCOUT_MODE_MASK;576} else {577sft = GENERAL2_ASRCOUT_MODE_SFT;578mask = GENERAL2_ASRCOUT_MODE_MASK;579}580}581582regmap_update_bits(afe->regmap, GENERAL_ASRC_MODE, mask << sft, rate_reg << sft);583584return 0;585}586587static int mtk_dai_src_hw_free(struct snd_pcm_substream *substream,588struct snd_soc_dai *dai)589{590struct mtk_base_afe *afe = snd_soc_dai_get_drvdata(dai);591struct mt8186_afe_private *afe_priv = afe->platform_priv;592int id = dai->id;593struct mtk_afe_src_priv *src_priv = afe_priv->dai_priv[id];594595dev_dbg(afe->dev, "%s(), id %d, stream %d\n",596__func__, id, substream->stream);597598if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)599src_priv->dl_rate = 0;600else601src_priv->ul_rate = 0;602603return 0;604}605606static const struct snd_soc_dai_ops mtk_dai_src_ops = {607.hw_params = mtk_dai_src_hw_params,608.hw_free = mtk_dai_src_hw_free,609};610611/* dai driver */612#define MTK_SRC_RATES (SNDRV_PCM_RATE_8000_48000 |\613SNDRV_PCM_RATE_88200 |\614SNDRV_PCM_RATE_96000 |\615SNDRV_PCM_RATE_176400 |\616SNDRV_PCM_RATE_192000)617618#define MTK_SRC_FORMATS (SNDRV_PCM_FMTBIT_S16_LE |\619SNDRV_PCM_FMTBIT_S24_LE |\620SNDRV_PCM_FMTBIT_S32_LE)621622static struct snd_soc_dai_driver mtk_dai_src_driver[] = {623{624.name = "HW_SRC_1",625.id = MT8186_DAI_SRC_1,626.playback = {627.stream_name = "HW_SRC_1_In",628.channels_min = 1,629.channels_max = 2,630.rates = MTK_SRC_RATES,631.formats = MTK_SRC_FORMATS,632},633.capture = {634.stream_name = "HW_SRC_1_Out",635.channels_min = 1,636.channels_max = 2,637.rates = MTK_SRC_RATES,638.formats = MTK_SRC_FORMATS,639},640.ops = &mtk_dai_src_ops,641},642{643.name = "HW_SRC_2",644.id = MT8186_DAI_SRC_2,645.playback = {646.stream_name = "HW_SRC_2_In",647.channels_min = 1,648.channels_max = 2,649.rates = MTK_SRC_RATES,650.formats = MTK_SRC_FORMATS,651},652.capture = {653.stream_name = "HW_SRC_2_Out",654.channels_min = 1,655.channels_max = 2,656.rates = MTK_SRC_RATES,657.formats = MTK_SRC_FORMATS,658},659.ops = &mtk_dai_src_ops,660},661};662663int mt8186_dai_src_register(struct mtk_base_afe *afe)664{665struct mtk_base_afe_dai *dai;666int ret;667668dai = devm_kzalloc(afe->dev, sizeof(*dai), GFP_KERNEL);669if (!dai)670return -ENOMEM;671672list_add(&dai->list, &afe->sub_dais);673674dai->dai_drivers = mtk_dai_src_driver;675dai->num_dai_drivers = ARRAY_SIZE(mtk_dai_src_driver);676677dai->dapm_widgets = mtk_dai_src_widgets;678dai->num_dapm_widgets = ARRAY_SIZE(mtk_dai_src_widgets);679dai->dapm_routes = mtk_dai_src_routes;680dai->num_dapm_routes = ARRAY_SIZE(mtk_dai_src_routes);681682/* set dai priv */683ret = mt8186_dai_set_priv(afe, MT8186_DAI_SRC_1,684sizeof(struct mtk_afe_src_priv), NULL);685if (ret)686return ret;687688ret = mt8186_dai_set_priv(afe, MT8186_DAI_SRC_2,689sizeof(struct mtk_afe_src_priv), NULL);690if (ret)691return ret;692693return 0;694}695696697