Path: blob/master/sound/soc/mediatek/mt8183/mt8183-dai-adda.c
26488 views
// SPDX-License-Identifier: GPL-2.01//2// MediaTek ALSA SoC Audio DAI ADDA Control3//4// Copyright (c) 2018 MediaTek Inc.5// Author: KaiChieh Chuang <[email protected]>67#include <linux/regmap.h>8#include <linux/delay.h>9#include "mt8183-afe-common.h"10#include "mt8183-interconnection.h"11#include "mt8183-reg.h"12#include "../common/mtk-dai-adda-common.h"1314enum {15AUDIO_SDM_LEVEL_MUTE = 0,16AUDIO_SDM_LEVEL_NORMAL = 0x1d,17/* if you change level normal */18/* you need to change formula of hp impedance and dc trim too */19};2021/* dai component */22static const struct snd_kcontrol_new mtk_adda_dl_ch1_mix[] = {23SOC_DAPM_SINGLE_AUTODISABLE("DL1_CH1", AFE_CONN3, I_DL1_CH1, 1, 0),24SOC_DAPM_SINGLE_AUTODISABLE("DL2_CH1", AFE_CONN3, I_DL2_CH1, 1, 0),25SOC_DAPM_SINGLE_AUTODISABLE("DL3_CH1", AFE_CONN3, I_DL3_CH1, 1, 0),26SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH2", AFE_CONN3,27I_ADDA_UL_CH2, 1, 0),28SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH1", AFE_CONN3,29I_ADDA_UL_CH1, 1, 0),30SOC_DAPM_SINGLE_AUTODISABLE("PCM_1_CAP_CH1", AFE_CONN3,31I_PCM_1_CAP_CH1, 1, 0),32SOC_DAPM_SINGLE_AUTODISABLE("PCM_2_CAP_CH1", AFE_CONN3,33I_PCM_2_CAP_CH1, 1, 0),34};3536static const struct snd_kcontrol_new mtk_adda_dl_ch2_mix[] = {37SOC_DAPM_SINGLE_AUTODISABLE("DL1_CH1", AFE_CONN4, I_DL1_CH1, 1, 0),38SOC_DAPM_SINGLE_AUTODISABLE("DL1_CH2", AFE_CONN4, I_DL1_CH2, 1, 0),39SOC_DAPM_SINGLE_AUTODISABLE("DL2_CH1", AFE_CONN4, I_DL2_CH1, 1, 0),40SOC_DAPM_SINGLE_AUTODISABLE("DL2_CH2", AFE_CONN4, I_DL2_CH2, 1, 0),41SOC_DAPM_SINGLE_AUTODISABLE("DL3_CH1", AFE_CONN4, I_DL3_CH1, 1, 0),42SOC_DAPM_SINGLE_AUTODISABLE("DL3_CH2", AFE_CONN4, I_DL3_CH2, 1, 0),43SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH2", AFE_CONN4,44I_ADDA_UL_CH2, 1, 0),45SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH1", AFE_CONN4,46I_ADDA_UL_CH1, 1, 0),47SOC_DAPM_SINGLE_AUTODISABLE("PCM_1_CAP_CH1", AFE_CONN4,48I_PCM_1_CAP_CH1, 1, 0),49SOC_DAPM_SINGLE_AUTODISABLE("PCM_2_CAP_CH1", AFE_CONN4,50I_PCM_2_CAP_CH1, 1, 0),51SOC_DAPM_SINGLE_AUTODISABLE("PCM_1_CAP_CH2", AFE_CONN4,52I_PCM_1_CAP_CH2, 1, 0),53SOC_DAPM_SINGLE_AUTODISABLE("PCM_2_CAP_CH2", AFE_CONN4,54I_PCM_2_CAP_CH2, 1, 0),55};5657static int mtk_adda_ul_event(struct snd_soc_dapm_widget *w,58struct snd_kcontrol *kcontrol,59int event)60{61struct snd_soc_component *cmpnt = snd_soc_dapm_to_component(w->dapm);62struct mtk_base_afe *afe = snd_soc_component_get_drvdata(cmpnt);63struct mt8183_afe_private *afe_priv = afe->platform_priv;6465dev_dbg(afe->dev, "%s(), name %s, event 0x%x\n",66__func__, w->name, event);6768switch (event) {69case SND_SOC_DAPM_PRE_PMU:70/* update setting to dmic */71if (afe_priv->mtkaif_dmic) {72/* mtkaif_rxif_data_mode = 1, dmic */73regmap_update_bits(afe->regmap, AFE_ADDA_MTKAIF_RX_CFG0,740x1, 0x1);7576/* dmic mode, 3.25M*/77regmap_update_bits(afe->regmap, AFE_ADDA_MTKAIF_RX_CFG0,780x0, 0xf << 20);79regmap_update_bits(afe->regmap, AFE_ADDA_UL_SRC_CON0,800x0, 0x1 << 5);81regmap_update_bits(afe->regmap, AFE_ADDA_UL_SRC_CON0,820x0, 0x3 << 14);8384/* turn on dmic, ch1, ch2 */85regmap_update_bits(afe->regmap, AFE_ADDA_UL_SRC_CON0,860x1 << 1, 0x1 << 1);87regmap_update_bits(afe->regmap, AFE_ADDA_UL_SRC_CON0,880x3 << 21, 0x3 << 21);89}90break;91case SND_SOC_DAPM_POST_PMD:92/* should delayed 1/fs(smallest is 8k) = 125us before afe off */93usleep_range(125, 135);94break;95default:96break;97}9899return 0;100}101102/* mtkaif dmic */103static const char * const mt8183_adda_off_on_str[] = {104"Off", "On"105};106107static const struct soc_enum mt8183_adda_enum[] = {108SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(mt8183_adda_off_on_str),109mt8183_adda_off_on_str),110};111112static int mt8183_adda_dmic_get(struct snd_kcontrol *kcontrol,113struct snd_ctl_elem_value *ucontrol)114{115struct snd_soc_component *cmpnt = snd_soc_kcontrol_component(kcontrol);116struct mtk_base_afe *afe = snd_soc_component_get_drvdata(cmpnt);117struct mt8183_afe_private *afe_priv = afe->platform_priv;118119ucontrol->value.integer.value[0] = afe_priv->mtkaif_dmic;120121return 0;122}123124static int mt8183_adda_dmic_set(struct snd_kcontrol *kcontrol,125struct snd_ctl_elem_value *ucontrol)126{127struct snd_soc_component *cmpnt = snd_soc_kcontrol_component(kcontrol);128struct mtk_base_afe *afe = snd_soc_component_get_drvdata(cmpnt);129struct mt8183_afe_private *afe_priv = afe->platform_priv;130struct soc_enum *e = (struct soc_enum *)kcontrol->private_value;131132if (ucontrol->value.enumerated.item[0] >= e->items)133return -EINVAL;134135afe_priv->mtkaif_dmic = ucontrol->value.integer.value[0];136137dev_info(afe->dev, "%s(), kcontrol name %s, mtkaif_dmic %d\n",138__func__, kcontrol->id.name, afe_priv->mtkaif_dmic);139140return 0;141}142143static const struct snd_kcontrol_new mtk_adda_controls[] = {144SOC_ENUM_EXT("MTKAIF_DMIC", mt8183_adda_enum[0],145mt8183_adda_dmic_get, mt8183_adda_dmic_set),146};147148enum {149SUPPLY_SEQ_ADDA_AFE_ON,150SUPPLY_SEQ_ADDA_DL_ON,151SUPPLY_SEQ_ADDA_UL_ON,152};153154static const struct snd_soc_dapm_widget mtk_dai_adda_widgets[] = {155/* adda */156SND_SOC_DAPM_MIXER("ADDA_DL_CH1", SND_SOC_NOPM, 0, 0,157mtk_adda_dl_ch1_mix,158ARRAY_SIZE(mtk_adda_dl_ch1_mix)),159SND_SOC_DAPM_MIXER("ADDA_DL_CH2", SND_SOC_NOPM, 0, 0,160mtk_adda_dl_ch2_mix,161ARRAY_SIZE(mtk_adda_dl_ch2_mix)),162163SND_SOC_DAPM_SUPPLY_S("ADDA Enable", SUPPLY_SEQ_ADDA_AFE_ON,164AFE_ADDA_UL_DL_CON0, ADDA_AFE_ON_SFT, 0,165NULL, 0),166167SND_SOC_DAPM_SUPPLY_S("ADDA Playback Enable", SUPPLY_SEQ_ADDA_DL_ON,168AFE_ADDA_DL_SRC2_CON0,169DL_2_SRC_ON_TMP_CTL_PRE_SFT, 0,170NULL, 0),171172SND_SOC_DAPM_SUPPLY_S("ADDA Capture Enable", SUPPLY_SEQ_ADDA_UL_ON,173AFE_ADDA_UL_SRC_CON0,174UL_SRC_ON_TMP_CTL_SFT, 0,175mtk_adda_ul_event,176SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),177178SND_SOC_DAPM_CLOCK_SUPPLY("aud_dac_clk"),179SND_SOC_DAPM_CLOCK_SUPPLY("aud_dac_predis_clk"),180SND_SOC_DAPM_CLOCK_SUPPLY("aud_adc_clk"),181SND_SOC_DAPM_CLOCK_SUPPLY("mtkaif_26m_clk"),182};183184static const struct snd_soc_dapm_route mtk_dai_adda_routes[] = {185/* playback */186{"ADDA_DL_CH1", "DL1_CH1", "DL1"},187{"ADDA_DL_CH2", "DL1_CH1", "DL1"},188{"ADDA_DL_CH2", "DL1_CH2", "DL1"},189190{"ADDA_DL_CH1", "DL2_CH1", "DL2"},191{"ADDA_DL_CH2", "DL2_CH1", "DL2"},192{"ADDA_DL_CH2", "DL2_CH2", "DL2"},193194{"ADDA_DL_CH1", "DL3_CH1", "DL3"},195{"ADDA_DL_CH2", "DL3_CH1", "DL3"},196{"ADDA_DL_CH2", "DL3_CH2", "DL3"},197198{"ADDA Playback", NULL, "ADDA_DL_CH1"},199{"ADDA Playback", NULL, "ADDA_DL_CH2"},200201/* adda enable */202{"ADDA Playback", NULL, "ADDA Enable"},203{"ADDA Playback", NULL, "ADDA Playback Enable"},204{"ADDA Capture", NULL, "ADDA Enable"},205{"ADDA Capture", NULL, "ADDA Capture Enable"},206207/* clk */208{"ADDA Playback", NULL, "mtkaif_26m_clk"},209{"ADDA Playback", NULL, "aud_dac_clk"},210{"ADDA Playback", NULL, "aud_dac_predis_clk"},211212{"ADDA Capture", NULL, "mtkaif_26m_clk"},213{"ADDA Capture", NULL, "aud_adc_clk"},214};215216static int set_mtkaif_rx(struct mtk_base_afe *afe)217{218struct mt8183_afe_private *afe_priv = afe->platform_priv;219int delay_data;220int delay_cycle;221222switch (afe_priv->mtkaif_protocol) {223case MT8183_MTKAIF_PROTOCOL_2_CLK_P2:224regmap_write(afe->regmap, AFE_AUD_PAD_TOP, 0x38);225regmap_write(afe->regmap, AFE_AUD_PAD_TOP, 0x39);226/* mtkaif_rxif_clkinv_adc inverse for calibration */227regmap_write(afe->regmap, AFE_ADDA_MTKAIF_CFG0,2280x80010000);229230if (afe_priv->mtkaif_phase_cycle[0] >=231afe_priv->mtkaif_phase_cycle[1]) {232delay_data = DELAY_DATA_MISO1;233delay_cycle = afe_priv->mtkaif_phase_cycle[0] -234afe_priv->mtkaif_phase_cycle[1];235} else {236delay_data = DELAY_DATA_MISO2;237delay_cycle = afe_priv->mtkaif_phase_cycle[1] -238afe_priv->mtkaif_phase_cycle[0];239}240241regmap_update_bits(afe->regmap,242AFE_ADDA_MTKAIF_RX_CFG2,243MTKAIF_RXIF_DELAY_DATA_MASK_SFT,244delay_data << MTKAIF_RXIF_DELAY_DATA_SFT);245246regmap_update_bits(afe->regmap,247AFE_ADDA_MTKAIF_RX_CFG2,248MTKAIF_RXIF_DELAY_CYCLE_MASK_SFT,249delay_cycle << MTKAIF_RXIF_DELAY_CYCLE_SFT);250break;251case MT8183_MTKAIF_PROTOCOL_2:252regmap_write(afe->regmap, AFE_AUD_PAD_TOP, 0x31);253regmap_write(afe->regmap, AFE_ADDA_MTKAIF_CFG0,2540x00010000);255break;256case MT8183_MTKAIF_PROTOCOL_1:257regmap_write(afe->regmap, AFE_AUD_PAD_TOP, 0x31);258regmap_write(afe->regmap, AFE_ADDA_MTKAIF_CFG0, 0x0);259break;260default:261break;262}263264return 0;265}266267/* dai ops */268static int mtk_dai_adda_hw_params(struct snd_pcm_substream *substream,269struct snd_pcm_hw_params *params,270struct snd_soc_dai *dai)271{272struct mtk_base_afe *afe = snd_soc_dai_get_drvdata(dai);273unsigned int rate = params_rate(params);274275dev_dbg(afe->dev, "%s(), id %d, stream %d, rate %d\n",276__func__, dai->id, substream->stream, rate);277278if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {279unsigned int dl_src2_con0 = 0;280unsigned int dl_src2_con1 = 0;281282/* clean predistortion */283regmap_write(afe->regmap, AFE_ADDA_PREDIS_CON0, 0);284regmap_write(afe->regmap, AFE_ADDA_PREDIS_CON1, 0);285286/* set sampling rate */287dl_src2_con0 = mtk_adda_dl_rate_transform(afe, rate) << 28;288289/* set output mode */290switch (rate) {291case 192000:292dl_src2_con0 |= (0x1 << 24); /* UP_SAMPLING_RATE_X2 */293dl_src2_con0 |= 1 << 14;294break;295case 96000:296dl_src2_con0 |= (0x2 << 24); /* UP_SAMPLING_RATE_X4 */297dl_src2_con0 |= 1 << 14;298break;299default:300dl_src2_con0 |= (0x3 << 24); /* UP_SAMPLING_RATE_X8 */301break;302}303304/* turn off mute function */305dl_src2_con0 |= (0x03 << 11);306307/* set voice input data if input sample rate is 8k or 16k */308if (rate == 8000 || rate == 16000)309dl_src2_con0 |= 0x01 << 5;310311/* SA suggest apply -0.3db to audio/speech path */312dl_src2_con1 = 0xf74f0000;313314/* turn on down-link gain */315dl_src2_con0 = dl_src2_con0 | (0x01 << 1);316317regmap_write(afe->regmap, AFE_ADDA_DL_SRC2_CON0, dl_src2_con0);318regmap_write(afe->regmap, AFE_ADDA_DL_SRC2_CON1, dl_src2_con1);319320/* set sdm gain */321regmap_update_bits(afe->regmap,322AFE_ADDA_DL_SDM_DCCOMP_CON,323ATTGAIN_CTL_MASK_SFT,324AUDIO_SDM_LEVEL_NORMAL << ATTGAIN_CTL_SFT);325} else {326unsigned int voice_mode = 0;327unsigned int ul_src_con0 = 0; /* default value */328329/* set mtkaif protocol */330set_mtkaif_rx(afe);331332/* Using Internal ADC */333regmap_update_bits(afe->regmap,334AFE_ADDA_TOP_CON0,3350x1 << 0,3360x0 << 0);337338voice_mode = mtk_adda_ul_rate_transform(afe, rate);339340ul_src_con0 |= (voice_mode << 17) & (0x7 << 17);341342/* enable iir */343ul_src_con0 |= (1 << UL_IIR_ON_TMP_CTL_SFT) &344UL_IIR_ON_TMP_CTL_MASK_SFT;345346/* 35Hz @ 48k */347regmap_write(afe->regmap, AFE_ADDA_IIR_COEF_02_01, 0x00000000);348regmap_write(afe->regmap, AFE_ADDA_IIR_COEF_04_03, 0x00003FB8);349regmap_write(afe->regmap, AFE_ADDA_IIR_COEF_06_05, 0x3FB80000);350regmap_write(afe->regmap, AFE_ADDA_IIR_COEF_08_07, 0x3FB80000);351regmap_write(afe->regmap, AFE_ADDA_IIR_COEF_10_09, 0x0000C048);352353regmap_write(afe->regmap, AFE_ADDA_UL_SRC_CON0, ul_src_con0);354355/* mtkaif_rxif_data_mode = 0, amic */356regmap_update_bits(afe->regmap,357AFE_ADDA_MTKAIF_RX_CFG0,3580x1 << 0,3590x0 << 0);360}361362return 0;363}364365static const struct snd_soc_dai_ops mtk_dai_adda_ops = {366.hw_params = mtk_dai_adda_hw_params,367};368369/* dai driver */370#define MTK_ADDA_PLAYBACK_RATES (SNDRV_PCM_RATE_8000_48000 |\371SNDRV_PCM_RATE_96000 |\372SNDRV_PCM_RATE_192000)373374#define MTK_ADDA_CAPTURE_RATES (SNDRV_PCM_RATE_8000 |\375SNDRV_PCM_RATE_16000 |\376SNDRV_PCM_RATE_32000 |\377SNDRV_PCM_RATE_48000)378379#define MTK_ADDA_FORMATS (SNDRV_PCM_FMTBIT_S16_LE |\380SNDRV_PCM_FMTBIT_S24_LE |\381SNDRV_PCM_FMTBIT_S32_LE)382383static struct snd_soc_dai_driver mtk_dai_adda_driver[] = {384{385.name = "ADDA",386.id = MT8183_DAI_ADDA,387.playback = {388.stream_name = "ADDA Playback",389.channels_min = 1,390.channels_max = 2,391.rates = MTK_ADDA_PLAYBACK_RATES,392.formats = MTK_ADDA_FORMATS,393},394.capture = {395.stream_name = "ADDA Capture",396.channels_min = 1,397.channels_max = 2,398.rates = MTK_ADDA_CAPTURE_RATES,399.formats = MTK_ADDA_FORMATS,400},401.ops = &mtk_dai_adda_ops,402},403};404405int mt8183_dai_adda_register(struct mtk_base_afe *afe)406{407struct mtk_base_afe_dai *dai;408409dai = devm_kzalloc(afe->dev, sizeof(*dai), GFP_KERNEL);410if (!dai)411return -ENOMEM;412413list_add(&dai->list, &afe->sub_dais);414415dai->dai_drivers = mtk_dai_adda_driver;416dai->num_dai_drivers = ARRAY_SIZE(mtk_dai_adda_driver);417418dai->controls = mtk_adda_controls;419dai->num_controls = ARRAY_SIZE(mtk_adda_controls);420dai->dapm_widgets = mtk_dai_adda_widgets;421dai->num_dapm_widgets = ARRAY_SIZE(mtk_dai_adda_widgets);422dai->dapm_routes = mtk_dai_adda_routes;423dai->num_dapm_routes = ARRAY_SIZE(mtk_dai_adda_routes);424return 0;425}426427428