Path: blob/master/sound/soc/mediatek/mt6797/mt6797-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 "mt6797-afe-common.h"10#include "mt6797-interconnection.h"11#include "mt6797-reg.h"12#include "../common/mtk-dai-adda-common.h"1314/* dai component */15static const struct snd_kcontrol_new mtk_adda_dl_ch1_mix[] = {16SOC_DAPM_SINGLE_AUTODISABLE("DL1_CH1", AFE_CONN3, I_DL1_CH1, 1, 0),17SOC_DAPM_SINGLE_AUTODISABLE("DL2_CH1", AFE_CONN3, I_DL2_CH1, 1, 0),18SOC_DAPM_SINGLE_AUTODISABLE("DL3_CH1", AFE_CONN3, I_DL3_CH1, 1, 0),19SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH2", AFE_CONN3,20I_ADDA_UL_CH2, 1, 0),21SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH1", AFE_CONN3,22I_ADDA_UL_CH1, 1, 0),23SOC_DAPM_SINGLE_AUTODISABLE("PCM_1_CAP_CH1", AFE_CONN3,24I_PCM_1_CAP_CH1, 1, 0),25SOC_DAPM_SINGLE_AUTODISABLE("PCM_2_CAP_CH1", AFE_CONN3,26I_PCM_2_CAP_CH1, 1, 0),27};2829static const struct snd_kcontrol_new mtk_adda_dl_ch2_mix[] = {30SOC_DAPM_SINGLE_AUTODISABLE("DL1_CH1", AFE_CONN4, I_DL1_CH1, 1, 0),31SOC_DAPM_SINGLE_AUTODISABLE("DL1_CH2", AFE_CONN4, I_DL1_CH2, 1, 0),32SOC_DAPM_SINGLE_AUTODISABLE("DL2_CH1", AFE_CONN4, I_DL2_CH1, 1, 0),33SOC_DAPM_SINGLE_AUTODISABLE("DL2_CH2", AFE_CONN4, I_DL2_CH2, 1, 0),34SOC_DAPM_SINGLE_AUTODISABLE("DL3_CH1", AFE_CONN4, I_DL3_CH1, 1, 0),35SOC_DAPM_SINGLE_AUTODISABLE("DL3_CH2", AFE_CONN4, I_DL3_CH2, 1, 0),36SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH2", AFE_CONN4,37I_ADDA_UL_CH2, 1, 0),38SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH1", AFE_CONN4,39I_ADDA_UL_CH1, 1, 0),40SOC_DAPM_SINGLE_AUTODISABLE("PCM_1_CAP_CH1", AFE_CONN4,41I_PCM_1_CAP_CH1, 1, 0),42SOC_DAPM_SINGLE_AUTODISABLE("PCM_2_CAP_CH1", AFE_CONN4,43I_PCM_2_CAP_CH1, 1, 0),44SOC_DAPM_SINGLE_AUTODISABLE("PCM_1_CAP_CH2", AFE_CONN4,45I_PCM_1_CAP_CH2, 1, 0),46SOC_DAPM_SINGLE_AUTODISABLE("PCM_2_CAP_CH2", AFE_CONN4,47I_PCM_2_CAP_CH2, 1, 0),48};4950static int mtk_adda_ul_event(struct snd_soc_dapm_widget *w,51struct snd_kcontrol *kcontrol,52int event)53{54struct snd_soc_component *cmpnt = snd_soc_dapm_to_component(w->dapm);55struct mtk_base_afe *afe = snd_soc_component_get_drvdata(cmpnt);5657dev_dbg(afe->dev, "%s(), name %s, event 0x%x\n",58__func__, w->name, event);5960switch (event) {61case SND_SOC_DAPM_POST_PMD:62/* should delayed 1/fs(smallest is 8k) = 125us before afe off */63usleep_range(125, 135);64break;65default:66break;67}6869return 0;70}7172enum {73SUPPLY_SEQ_AUD_TOP_PDN,74SUPPLY_SEQ_ADDA_AFE_ON,75SUPPLY_SEQ_ADDA_DL_ON,76SUPPLY_SEQ_ADDA_UL_ON,77};7879static const struct snd_soc_dapm_widget mtk_dai_adda_widgets[] = {80/* adda */81SND_SOC_DAPM_MIXER("ADDA_DL_CH1", SND_SOC_NOPM, 0, 0,82mtk_adda_dl_ch1_mix,83ARRAY_SIZE(mtk_adda_dl_ch1_mix)),84SND_SOC_DAPM_MIXER("ADDA_DL_CH2", SND_SOC_NOPM, 0, 0,85mtk_adda_dl_ch2_mix,86ARRAY_SIZE(mtk_adda_dl_ch2_mix)),8788SND_SOC_DAPM_SUPPLY_S("ADDA Enable", SUPPLY_SEQ_ADDA_AFE_ON,89AFE_ADDA_UL_DL_CON0, ADDA_AFE_ON_SFT, 0,90NULL, 0),9192SND_SOC_DAPM_SUPPLY_S("ADDA Playback Enable", SUPPLY_SEQ_ADDA_DL_ON,93AFE_ADDA_DL_SRC2_CON0,94DL_2_SRC_ON_TMP_CTL_PRE_SFT, 0,95NULL, 0),9697SND_SOC_DAPM_SUPPLY_S("ADDA Capture Enable", SUPPLY_SEQ_ADDA_UL_ON,98AFE_ADDA_UL_SRC_CON0,99UL_SRC_ON_TMP_CTL_SFT, 0,100mtk_adda_ul_event,101SND_SOC_DAPM_POST_PMD),102103SND_SOC_DAPM_SUPPLY_S("aud_dac_clk", SUPPLY_SEQ_AUD_TOP_PDN,104AUDIO_TOP_CON0, PDN_DAC_SFT, 1,105NULL, 0),106SND_SOC_DAPM_SUPPLY_S("aud_dac_predis_clk", SUPPLY_SEQ_AUD_TOP_PDN,107AUDIO_TOP_CON0, PDN_DAC_PREDIS_SFT, 1,108NULL, 0),109110SND_SOC_DAPM_SUPPLY_S("aud_adc_clk", SUPPLY_SEQ_AUD_TOP_PDN,111AUDIO_TOP_CON0, PDN_ADC_SFT, 1,112NULL, 0),113114SND_SOC_DAPM_CLOCK_SUPPLY("mtkaif_26m_clk"),115};116117static const struct snd_soc_dapm_route mtk_dai_adda_routes[] = {118/* playback */119{"ADDA_DL_CH1", "DL1_CH1", "DL1"},120{"ADDA_DL_CH2", "DL1_CH1", "DL1"},121{"ADDA_DL_CH2", "DL1_CH2", "DL1"},122123{"ADDA_DL_CH1", "DL2_CH1", "DL2"},124{"ADDA_DL_CH2", "DL2_CH1", "DL2"},125{"ADDA_DL_CH2", "DL2_CH2", "DL2"},126127{"ADDA_DL_CH1", "DL3_CH1", "DL3"},128{"ADDA_DL_CH2", "DL3_CH1", "DL3"},129{"ADDA_DL_CH2", "DL3_CH2", "DL3"},130131{"ADDA Playback", NULL, "ADDA_DL_CH1"},132{"ADDA Playback", NULL, "ADDA_DL_CH2"},133134/* adda enable */135{"ADDA Playback", NULL, "ADDA Enable"},136{"ADDA Playback", NULL, "ADDA Playback Enable"},137{"ADDA Capture", NULL, "ADDA Enable"},138{"ADDA Capture", NULL, "ADDA Capture Enable"},139140/* clk */141{"ADDA Playback", NULL, "mtkaif_26m_clk"},142{"ADDA Playback", NULL, "aud_dac_clk"},143{"ADDA Playback", NULL, "aud_dac_predis_clk"},144145{"ADDA Capture", NULL, "mtkaif_26m_clk"},146{"ADDA Capture", NULL, "aud_adc_clk"},147};148149/* dai ops */150static int mtk_dai_adda_hw_params(struct snd_pcm_substream *substream,151struct snd_pcm_hw_params *params,152struct snd_soc_dai *dai)153{154struct mtk_base_afe *afe = snd_soc_dai_get_drvdata(dai);155unsigned int rate = params_rate(params);156157dev_dbg(afe->dev, "%s(), id %d, stream %d, rate %d\n",158__func__, dai->id, substream->stream, rate);159160if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {161unsigned int dl_src2_con0 = 0;162unsigned int dl_src2_con1 = 0;163164/* clean predistortion */165regmap_write(afe->regmap, AFE_ADDA_PREDIS_CON0, 0);166regmap_write(afe->regmap, AFE_ADDA_PREDIS_CON1, 0);167168/* set input sampling rate */169dl_src2_con0 = mtk_adda_dl_rate_transform(afe, rate) << 28;170171/* set output mode */172switch (rate) {173case 192000:174dl_src2_con0 |= (0x1 << 24); /* UP_SAMPLING_RATE_X2 */175dl_src2_con0 |= 1 << 14;176break;177case 96000:178dl_src2_con0 |= (0x2 << 24); /* UP_SAMPLING_RATE_X4 */179dl_src2_con0 |= 1 << 14;180break;181default:182dl_src2_con0 |= (0x3 << 24); /* UP_SAMPLING_RATE_X8 */183break;184}185186/* turn off mute function */187dl_src2_con0 |= (0x03 << 11);188189/* set voice input data if input sample rate is 8k or 16k */190if (rate == 8000 || rate == 16000)191dl_src2_con0 |= 0x01 << 5;192193if (rate < 96000) {194/* SA suggest apply -0.3db to audio/speech path */195dl_src2_con1 = 0xf74f0000;196} else {197/* SA suggest apply -0.3db to audio/speech path198* with DL gain set to half,199* 0xFFFF = 0dB -> 0x8000 = 0dB when 96k, 192k200*/201dl_src2_con1 = 0x7ba70000;202}203204/* turn on down-link gain */205dl_src2_con0 = dl_src2_con0 | (0x01 << 1);206207regmap_write(afe->regmap, AFE_ADDA_DL_SRC2_CON0, dl_src2_con0);208regmap_write(afe->regmap, AFE_ADDA_DL_SRC2_CON1, dl_src2_con1);209} else {210unsigned int voice_mode = 0;211unsigned int ul_src_con0 = 0; /* default value */212213/* Using Internal ADC */214regmap_update_bits(afe->regmap,215AFE_ADDA_TOP_CON0,2160x1 << 0,2170x0 << 0);218219voice_mode = mtk_adda_ul_rate_transform(afe, rate);220221ul_src_con0 |= (voice_mode << 17) & (0x7 << 17);222223/* up8x txif sat on */224regmap_write(afe->regmap, AFE_ADDA_NEWIF_CFG0, 0x03F87201);225226if (rate >= 96000) { /* hires */227/* use hires format [1 0 23] */228regmap_update_bits(afe->regmap,229AFE_ADDA_NEWIF_CFG0,2300x1 << 5,2310x1 << 5);232233regmap_update_bits(afe->regmap,234AFE_ADDA_NEWIF_CFG2,2350xf << 28,236voice_mode << 28);237} else { /* normal 8~48k */238/* use fixed 260k anc path */239regmap_update_bits(afe->regmap,240AFE_ADDA_NEWIF_CFG2,2410xf << 28,2428 << 28);243244/* ul_use_cic_out */245ul_src_con0 |= 0x1 << 20;246}247248regmap_update_bits(afe->regmap,249AFE_ADDA_NEWIF_CFG2,2500xf << 28,2518 << 28);252253regmap_update_bits(afe->regmap,254AFE_ADDA_UL_SRC_CON0,2550xfffffffe,256ul_src_con0);257}258259return 0;260}261262static const struct snd_soc_dai_ops mtk_dai_adda_ops = {263.hw_params = mtk_dai_adda_hw_params,264};265266/* dai driver */267#define MTK_ADDA_PLAYBACK_RATES (SNDRV_PCM_RATE_8000_48000 |\268SNDRV_PCM_RATE_96000 |\269SNDRV_PCM_RATE_192000)270271#define MTK_ADDA_CAPTURE_RATES (SNDRV_PCM_RATE_8000 |\272SNDRV_PCM_RATE_16000 |\273SNDRV_PCM_RATE_32000 |\274SNDRV_PCM_RATE_48000 |\275SNDRV_PCM_RATE_96000 |\276SNDRV_PCM_RATE_192000)277278#define MTK_ADDA_FORMATS (SNDRV_PCM_FMTBIT_S16_LE |\279SNDRV_PCM_FMTBIT_S24_LE |\280SNDRV_PCM_FMTBIT_S32_LE)281282static struct snd_soc_dai_driver mtk_dai_adda_driver[] = {283{284.name = "ADDA",285.id = MT6797_DAI_ADDA,286.playback = {287.stream_name = "ADDA Playback",288.channels_min = 1,289.channels_max = 2,290.rates = MTK_ADDA_PLAYBACK_RATES,291.formats = MTK_ADDA_FORMATS,292},293.capture = {294.stream_name = "ADDA Capture",295.channels_min = 1,296.channels_max = 2,297.rates = MTK_ADDA_CAPTURE_RATES,298.formats = MTK_ADDA_FORMATS,299},300.ops = &mtk_dai_adda_ops,301},302};303304int mt6797_dai_adda_register(struct mtk_base_afe *afe)305{306struct mtk_base_afe_dai *dai;307308dai = devm_kzalloc(afe->dev, sizeof(*dai), GFP_KERNEL);309if (!dai)310return -ENOMEM;311312list_add(&dai->list, &afe->sub_dais);313314dai->dai_drivers = mtk_dai_adda_driver;315dai->num_dai_drivers = ARRAY_SIZE(mtk_dai_adda_driver);316317dai->dapm_widgets = mtk_dai_adda_widgets;318dai->num_dapm_widgets = ARRAY_SIZE(mtk_dai_adda_widgets);319dai->dapm_routes = mtk_dai_adda_routes;320dai->num_dapm_routes = ARRAY_SIZE(mtk_dai_adda_routes);321return 0;322}323324325