Path: blob/master/sound/soc/mediatek/mt8188/mt8188-dai-adda.c
26488 views
// SPDX-License-Identifier: GPL-2.01/*2* MediaTek ALSA SoC Audio DAI ADDA Control3*4* Copyright (c) 2022 MediaTek Inc.5* Author: Bicycle Tsai <[email protected]>6* Trevor Wu <[email protected]>7* Chun-Chia Chiu <[email protected]>8*/910#include <linux/bitfield.h>11#include <linux/delay.h>12#include <linux/regmap.h>13#include "mt8188-afe-clk.h"14#include "mt8188-afe-common.h"15#include "mt8188-reg.h"16#include "../common/mtk-dai-adda-common.h"1718#define ADDA_HIRES_THRES 480001920enum {21SUPPLY_SEQ_ADDA_DL_ON,22SUPPLY_SEQ_ADDA_MTKAIF_CFG,23SUPPLY_SEQ_ADDA_UL_ON,24SUPPLY_SEQ_ADDA_AFE_ON,25};2627struct mtk_dai_adda_priv {28bool hires_required;29};3031static int mt8188_adda_mtkaif_init(struct mtk_base_afe *afe)32{33struct mt8188_afe_private *afe_priv = afe->platform_priv;34struct mtkaif_param *param = &afe_priv->mtkaif_params;35int delay_data;36int delay_cycle;37unsigned int mask = 0;38unsigned int val = 0;3940/* set rx protocol 2 & mtkaif_rxif_clkinv_adc inverse */41regmap_set_bits(afe->regmap, AFE_ADDA_MTKAIF_CFG0,42MTKAIF_RXIF_CLKINV_ADC | MTKAIF_RXIF_PROTOCOL2);4344regmap_set_bits(afe->regmap, AFE_AUD_PAD_TOP, RG_RX_PROTOCOL2);4546if (!param->mtkaif_calibration_ok) {47dev_info(afe->dev, "%s(), calibration fail\n", __func__);48return 0;49}5051/* set delay for ch1, ch2 */52if (param->mtkaif_phase_cycle[MT8188_MTKAIF_MISO_0] >=53param->mtkaif_phase_cycle[MT8188_MTKAIF_MISO_1]) {54delay_data = DELAY_DATA_MISO1;55delay_cycle =56param->mtkaif_phase_cycle[MT8188_MTKAIF_MISO_0] -57param->mtkaif_phase_cycle[MT8188_MTKAIF_MISO_1];58} else {59delay_data = DELAY_DATA_MISO0;60delay_cycle =61param->mtkaif_phase_cycle[MT8188_MTKAIF_MISO_1] -62param->mtkaif_phase_cycle[MT8188_MTKAIF_MISO_0];63}6465mask = (MTKAIF_RXIF_DELAY_DATA | MTKAIF_RXIF_DELAY_CYCLE_MASK);66val |= FIELD_PREP(MTKAIF_RXIF_DELAY_CYCLE_MASK, delay_cycle);67val |= FIELD_PREP(MTKAIF_RXIF_DELAY_DATA, delay_data);68regmap_update_bits(afe->regmap, AFE_ADDA_MTKAIF_RX_CFG2, mask, val);6970return 0;71}7273static int mtk_adda_mtkaif_cfg_event(struct snd_soc_dapm_widget *w,74struct snd_kcontrol *kcontrol,75int event)76{77struct snd_soc_component *cmpnt = snd_soc_dapm_to_component(w->dapm);78struct mtk_base_afe *afe = snd_soc_component_get_drvdata(cmpnt);7980dev_dbg(afe->dev, "%s(), name %s, event 0x%x\n",81__func__, w->name, event);8283switch (event) {84case SND_SOC_DAPM_PRE_PMU:85mt8188_adda_mtkaif_init(afe);86break;87default:88break;89}9091return 0;92}9394static int mtk_adda_dl_event(struct snd_soc_dapm_widget *w,95struct snd_kcontrol *kcontrol,96int event)97{98struct snd_soc_component *cmpnt = snd_soc_dapm_to_component(w->dapm);99struct mtk_base_afe *afe = snd_soc_component_get_drvdata(cmpnt);100101dev_dbg(afe->dev, "%s(), name %s, event 0x%x\n",102__func__, w->name, event);103104switch (event) {105case SND_SOC_DAPM_POST_PMD:106/* should delayed 1/fs(smallest is 8k) = 125us before afe off */107usleep_range(125, 135);108break;109default:110break;111}112113return 0;114}115116static void mtk_adda_ul_mictype(struct mtk_base_afe *afe, bool dmic)117{118unsigned int reg = AFE_ADDA_UL_SRC_CON0;119unsigned int val;120121val = (UL_SDM3_LEVEL_CTL | UL_MODE_3P25M_CH1_CTL |122UL_MODE_3P25M_CH2_CTL);123124/* turn on dmic, ch1, ch2 */125if (dmic)126regmap_set_bits(afe->regmap, reg, val);127else128regmap_clear_bits(afe->regmap, reg, val);129}130131static int mtk_adda_ul_event(struct snd_soc_dapm_widget *w,132struct snd_kcontrol *kcontrol,133int event)134{135struct snd_soc_component *cmpnt = snd_soc_dapm_to_component(w->dapm);136struct mtk_base_afe *afe = snd_soc_component_get_drvdata(cmpnt);137struct mt8188_afe_private *afe_priv = afe->platform_priv;138struct mtkaif_param *param = &afe_priv->mtkaif_params;139140dev_dbg(afe->dev, "%s(), name %s, event 0x%x\n",141__func__, w->name, event);142143switch (event) {144case SND_SOC_DAPM_PRE_PMU:145mtk_adda_ul_mictype(afe, param->mtkaif_dmic_on);146break;147case SND_SOC_DAPM_POST_PMD:148/* should delayed 1/fs(smallest is 8k) = 125us before afe off */149usleep_range(125, 135);150break;151default:152break;153}154155return 0;156}157158static struct mtk_dai_adda_priv *get_adda_priv_by_name(struct mtk_base_afe *afe,159const char *name)160{161struct mt8188_afe_private *afe_priv = afe->platform_priv;162163if (strstr(name, "aud_adc_hires"))164return afe_priv->dai_priv[MT8188_AFE_IO_UL_SRC];165else if (strstr(name, "aud_dac_hires"))166return afe_priv->dai_priv[MT8188_AFE_IO_DL_SRC];167else168return NULL;169}170171static int mtk_afe_adda_hires_connect(struct snd_soc_dapm_widget *source,172struct snd_soc_dapm_widget *sink)173{174struct snd_soc_dapm_widget *w = source;175struct snd_soc_component *cmpnt = snd_soc_dapm_to_component(w->dapm);176struct mtk_base_afe *afe = snd_soc_component_get_drvdata(cmpnt);177struct mtk_dai_adda_priv *adda_priv;178179adda_priv = get_adda_priv_by_name(afe, w->name);180181if (!adda_priv) {182dev_dbg(afe->dev, "adda_priv == NULL");183return 0;184}185186return (adda_priv->hires_required) ? 1 : 0;187}188189static const struct snd_kcontrol_new mtk_dai_adda_o176_mix[] = {190SOC_DAPM_SINGLE_AUTODISABLE("I000 Switch", AFE_CONN176, 0, 1, 0),191SOC_DAPM_SINGLE_AUTODISABLE("I002 Switch", AFE_CONN176, 2, 1, 0),192SOC_DAPM_SINGLE_AUTODISABLE("I020 Switch", AFE_CONN176, 20, 1, 0),193SOC_DAPM_SINGLE_AUTODISABLE("I022 Switch", AFE_CONN176, 22, 1, 0),194SOC_DAPM_SINGLE_AUTODISABLE("I070 Switch", AFE_CONN176_2, 6, 1, 0),195};196197static const struct snd_kcontrol_new mtk_dai_adda_o177_mix[] = {198SOC_DAPM_SINGLE_AUTODISABLE("I001 Switch", AFE_CONN177, 1, 1, 0),199SOC_DAPM_SINGLE_AUTODISABLE("I003 Switch", AFE_CONN177, 3, 1, 0),200SOC_DAPM_SINGLE_AUTODISABLE("I021 Switch", AFE_CONN177, 21, 1, 0),201SOC_DAPM_SINGLE_AUTODISABLE("I023 Switch", AFE_CONN177, 23, 1, 0),202SOC_DAPM_SINGLE_AUTODISABLE("I071 Switch", AFE_CONN177_2, 7, 1, 0),203};204205static const char * const adda_dlgain_mux_map[] = {206"Bypass", "Connect",207};208209static SOC_ENUM_SINGLE_DECL(adda_dlgain_mux_map_enum,210SND_SOC_NOPM, 0,211adda_dlgain_mux_map);212213static const struct snd_kcontrol_new adda_dlgain_mux_control =214SOC_DAPM_ENUM("DL_GAIN_MUX", adda_dlgain_mux_map_enum);215216static const struct snd_soc_dapm_widget mtk_dai_adda_widgets[] = {217SND_SOC_DAPM_MIXER("I168", SND_SOC_NOPM, 0, 0, NULL, 0),218SND_SOC_DAPM_MIXER("I169", SND_SOC_NOPM, 0, 0, NULL, 0),219220SND_SOC_DAPM_MIXER("O176", SND_SOC_NOPM, 0, 0,221mtk_dai_adda_o176_mix,222ARRAY_SIZE(mtk_dai_adda_o176_mix)),223SND_SOC_DAPM_MIXER("O177", SND_SOC_NOPM, 0, 0,224mtk_dai_adda_o177_mix,225ARRAY_SIZE(mtk_dai_adda_o177_mix)),226227SND_SOC_DAPM_SUPPLY_S("ADDA Enable", SUPPLY_SEQ_ADDA_AFE_ON,228AFE_ADDA_UL_DL_CON0,229ADDA_AFE_ON_SHIFT, 0,230NULL,2310),232233SND_SOC_DAPM_SUPPLY_S("ADDA Playback Enable", SUPPLY_SEQ_ADDA_DL_ON,234AFE_ADDA_DL_SRC2_CON0,235DL_2_SRC_ON_TMP_CTRL_PRE_SHIFT, 0,236mtk_adda_dl_event,237SND_SOC_DAPM_POST_PMD),238239SND_SOC_DAPM_SUPPLY_S("ADDA Capture Enable", SUPPLY_SEQ_ADDA_UL_ON,240AFE_ADDA_UL_SRC_CON0,241UL_SRC_ON_TMP_CTL_SHIFT, 0,242mtk_adda_ul_event,243SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),244245SND_SOC_DAPM_SUPPLY_S("ADDA_MTKAIF_CFG", SUPPLY_SEQ_ADDA_MTKAIF_CFG,246SND_SOC_NOPM,2470, 0,248mtk_adda_mtkaif_cfg_event,249SND_SOC_DAPM_PRE_PMU),250251SND_SOC_DAPM_MUX("DL_GAIN_MUX", SND_SOC_NOPM, 0, 0,252&adda_dlgain_mux_control),253254SND_SOC_DAPM_PGA("DL_GAIN", AFE_ADDA_DL_SRC2_CON0,255DL_2_GAIN_ON_CTL_PRE_SHIFT, 0, NULL, 0),256257SND_SOC_DAPM_INPUT("ADDA_INPUT"),258SND_SOC_DAPM_OUTPUT("ADDA_OUTPUT"),259260SND_SOC_DAPM_CLOCK_SUPPLY("aud_dac"),261SND_SOC_DAPM_CLOCK_SUPPLY("aud_adc"),262SND_SOC_DAPM_CLOCK_SUPPLY("aud_dac_hires"),263SND_SOC_DAPM_CLOCK_SUPPLY("aud_adc_hires"),264};265266static const struct snd_soc_dapm_route mtk_dai_adda_routes[] = {267{"ADDA Capture", NULL, "ADDA Enable"},268{"ADDA Capture", NULL, "ADDA Capture Enable"},269{"ADDA Capture", NULL, "ADDA_MTKAIF_CFG"},270{"ADDA Capture", NULL, "aud_adc"},271{"ADDA Capture", NULL, "aud_adc_hires", mtk_afe_adda_hires_connect},272273{"I168", NULL, "ADDA Capture"},274{"I169", NULL, "ADDA Capture"},275276{"ADDA Playback", NULL, "ADDA Enable"},277{"ADDA Playback", NULL, "ADDA Playback Enable"},278{"ADDA Playback", NULL, "aud_dac"},279{"ADDA Playback", NULL, "aud_dac_hires", mtk_afe_adda_hires_connect},280281{"DL_GAIN", NULL, "O176"},282{"DL_GAIN", NULL, "O177"},283284{"DL_GAIN_MUX", "Bypass", "O176"},285{"DL_GAIN_MUX", "Bypass", "O177"},286{"DL_GAIN_MUX", "Connect", "DL_GAIN"},287288{"ADDA Playback", NULL, "DL_GAIN_MUX"},289290{"O176", "I000 Switch", "I000"},291{"O177", "I001 Switch", "I001"},292293{"O176", "I002 Switch", "I002"},294{"O177", "I003 Switch", "I003"},295296{"O176", "I020 Switch", "I020"},297{"O177", "I021 Switch", "I021"},298299{"O176", "I022 Switch", "I022"},300{"O177", "I023 Switch", "I023"},301302{"O176", "I070 Switch", "I070"},303{"O177", "I071 Switch", "I071"},304305{"ADDA Capture", NULL, "ADDA_INPUT"},306{"ADDA_OUTPUT", NULL, "ADDA Playback"},307};308309static int mt8188_adda_dmic_get(struct snd_kcontrol *kcontrol,310struct snd_ctl_elem_value *ucontrol)311{312struct snd_soc_component *cmpnt = snd_soc_kcontrol_component(kcontrol);313struct mtk_base_afe *afe = snd_soc_component_get_drvdata(cmpnt);314struct mt8188_afe_private *afe_priv = afe->platform_priv;315struct mtkaif_param *param = &afe_priv->mtkaif_params;316317ucontrol->value.integer.value[0] = param->mtkaif_dmic_on;318return 0;319}320321static int mt8188_adda_dmic_set(struct snd_kcontrol *kcontrol,322struct snd_ctl_elem_value *ucontrol)323{324struct snd_soc_component *cmpnt = snd_soc_kcontrol_component(kcontrol);325struct mtk_base_afe *afe = snd_soc_component_get_drvdata(cmpnt);326struct mt8188_afe_private *afe_priv = afe->platform_priv;327struct mtkaif_param *param = &afe_priv->mtkaif_params;328int dmic_on;329330dmic_on = !!ucontrol->value.integer.value[0];331332dev_dbg(afe->dev, "%s(), kcontrol name %s, dmic_on %d\n",333__func__, kcontrol->id.name, dmic_on);334335if (param->mtkaif_dmic_on == dmic_on)336return 0;337338param->mtkaif_dmic_on = dmic_on;339return 1;340}341342static const struct snd_kcontrol_new mtk_dai_adda_controls[] = {343SOC_SINGLE("ADDA_DL_GAIN", AFE_ADDA_DL_SRC2_CON1,344DL_2_GAIN_CTL_PRE_SHIFT, 65535, 0),345SOC_SINGLE_BOOL_EXT("MTKAIF_DMIC Switch", 0,346mt8188_adda_dmic_get, mt8188_adda_dmic_set),347};348349static int mtk_dai_da_configure(struct mtk_base_afe *afe,350unsigned int rate, int id)351{352unsigned int val = 0;353unsigned int mask = 0;354355/* set sampling rate */356mask |= DL_2_INPUT_MODE_CTL_MASK;357val |= FIELD_PREP(DL_2_INPUT_MODE_CTL_MASK,358mtk_adda_dl_rate_transform(afe, rate));359360/* turn off saturation */361mask |= DL_2_CH1_SATURATION_EN_CTL;362mask |= DL_2_CH2_SATURATION_EN_CTL;363364/* turn off mute function */365mask |= DL_2_MUTE_CH1_OFF_CTL_PRE;366mask |= DL_2_MUTE_CH2_OFF_CTL_PRE;367val |= DL_2_MUTE_CH1_OFF_CTL_PRE;368val |= DL_2_MUTE_CH2_OFF_CTL_PRE;369370/* set voice input data if input sample rate is 8k or 16k */371mask |= DL_2_VOICE_MODE_CTL_PRE;372if (rate == 8000 || rate == 16000)373val |= DL_2_VOICE_MODE_CTL_PRE;374375regmap_update_bits(afe->regmap, AFE_ADDA_DL_SRC2_CON0, mask, val);376377/* new 2nd sdm */378regmap_set_bits(afe->regmap, AFE_ADDA_DL_SDM_DCCOMP_CON,379DL_USE_NEW_2ND_SDM);380381return 0;382}383384static int mtk_dai_ad_configure(struct mtk_base_afe *afe,385unsigned int rate, int id)386{387unsigned int val;388unsigned int mask;389390mask = UL_VOICE_MODE_CTL_MASK;391val = FIELD_PREP(UL_VOICE_MODE_CTL_MASK,392mtk_adda_ul_rate_transform(afe, rate));393394regmap_update_bits(afe->regmap, AFE_ADDA_UL_SRC_CON0,395mask, val);396return 0;397}398399static int mtk_dai_adda_hw_params(struct snd_pcm_substream *substream,400struct snd_pcm_hw_params *params,401struct snd_soc_dai *dai)402{403struct mtk_base_afe *afe = snd_soc_dai_get_drvdata(dai);404struct mt8188_afe_private *afe_priv = afe->platform_priv;405struct mtk_dai_adda_priv *adda_priv = afe_priv->dai_priv[dai->id];406unsigned int rate = params_rate(params);407int id = dai->id;408int ret = 0;409410dev_dbg(afe->dev, "%s(), id %d, stream %d, rate %u\n",411__func__, id, substream->stream, rate);412413adda_priv->hires_required = (rate > ADDA_HIRES_THRES);414415if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)416ret = mtk_dai_da_configure(afe, rate, id);417else418ret = mtk_dai_ad_configure(afe, rate, id);419420return ret;421}422423static const struct snd_soc_dai_ops mtk_dai_adda_ops = {424.hw_params = mtk_dai_adda_hw_params,425};426427/* dai driver */428#define MTK_ADDA_PLAYBACK_RATES (SNDRV_PCM_RATE_8000_48000 |\429SNDRV_PCM_RATE_96000 |\430SNDRV_PCM_RATE_192000)431432#define MTK_ADDA_CAPTURE_RATES (SNDRV_PCM_RATE_8000 |\433SNDRV_PCM_RATE_16000 |\434SNDRV_PCM_RATE_32000 |\435SNDRV_PCM_RATE_48000 |\436SNDRV_PCM_RATE_96000 |\437SNDRV_PCM_RATE_192000)438439#define MTK_ADDA_FORMATS (SNDRV_PCM_FMTBIT_S16_LE |\440SNDRV_PCM_FMTBIT_S24_LE |\441SNDRV_PCM_FMTBIT_S32_LE)442443static struct snd_soc_dai_driver mtk_dai_adda_driver[] = {444{445.name = "DL_SRC",446.id = MT8188_AFE_IO_DL_SRC,447.playback = {448.stream_name = "ADDA Playback",449.channels_min = 1,450.channels_max = 2,451.rates = MTK_ADDA_PLAYBACK_RATES,452.formats = MTK_ADDA_FORMATS,453},454.ops = &mtk_dai_adda_ops,455},456{457.name = "UL_SRC",458.id = MT8188_AFE_IO_UL_SRC,459.capture = {460.stream_name = "ADDA Capture",461.channels_min = 1,462.channels_max = 2,463.rates = MTK_ADDA_CAPTURE_RATES,464.formats = MTK_ADDA_FORMATS,465},466.ops = &mtk_dai_adda_ops,467},468};469470static int init_adda_priv_data(struct mtk_base_afe *afe)471{472struct mt8188_afe_private *afe_priv = afe->platform_priv;473struct mtk_dai_adda_priv *adda_priv;474int adda_dai_list[] = {MT8188_AFE_IO_DL_SRC, MT8188_AFE_IO_UL_SRC};475int i;476477for (i = 0; i < ARRAY_SIZE(adda_dai_list); i++) {478adda_priv = devm_kzalloc(afe->dev,479sizeof(struct mtk_dai_adda_priv),480GFP_KERNEL);481if (!adda_priv)482return -ENOMEM;483484afe_priv->dai_priv[adda_dai_list[i]] = adda_priv;485}486487return 0;488}489490int mt8188_dai_adda_register(struct mtk_base_afe *afe)491{492struct mtk_base_afe_dai *dai;493494dai = devm_kzalloc(afe->dev, sizeof(*dai), GFP_KERNEL);495if (!dai)496return -ENOMEM;497498list_add(&dai->list, &afe->sub_dais);499500dai->dai_drivers = mtk_dai_adda_driver;501dai->num_dai_drivers = ARRAY_SIZE(mtk_dai_adda_driver);502503dai->dapm_widgets = mtk_dai_adda_widgets;504dai->num_dapm_widgets = ARRAY_SIZE(mtk_dai_adda_widgets);505dai->dapm_routes = mtk_dai_adda_routes;506dai->num_dapm_routes = ARRAY_SIZE(mtk_dai_adda_routes);507dai->controls = mtk_dai_adda_controls;508dai->num_controls = ARRAY_SIZE(mtk_dai_adda_controls);509510return init_adda_priv_data(afe);511}512513514