Messages in this thread | | | Date | Fri, 18 Feb 2022 15:54:16 +0100 | From | AngeloGioacchino Del Regno <> | Subject | Re: [v2 03/17] ASoC: mediatek: mt8186: support adda in platform driver |
| |
Il 17/02/22 14:41, Jiaxin Yu ha scritto: > This patch adds mt8186 adda dai driver > > Signed-off-by: Jiaxin Yu <jiaxin.yu@mediatek.com> > --- > sound/soc/mediatek/mt8186/mt8186-dai-adda.c | 891 ++++++++++++++++++++ > 1 file changed, 891 insertions(+) > create mode 100644 sound/soc/mediatek/mt8186/mt8186-dai-adda.c > > diff --git a/sound/soc/mediatek/mt8186/mt8186-dai-adda.c b/sound/soc/mediatek/mt8186/mt8186-dai-adda.c > new file mode 100644 > index 000000000000..6d7dd1533da0 > --- /dev/null > +++ b/sound/soc/mediatek/mt8186/mt8186-dai-adda.c > @@ -0,0 +1,891 @@ > +// SPDX-License-Identifier: GPL-2.0 > +// > +// MediaTek ALSA SoC Audio DAI ADDA Control > +// > +// Copyright (c) 2022 MediaTek Inc. > +// Author: Jiaxin Yu <jiaxin.yu@mediatek.com> > + > +#include <linux/regmap.h> > +#include <linux/delay.h> > +#include "mt8186-afe-clk.h" > +#include "mt8186-afe-common.h" > +#include "mt8186-afe-gpio.h" > +#include "mt8186-interconnection.h" > +
..snip..
> + > +static int mtk_adda_mtkaif_cfg_event(struct snd_soc_dapm_widget *w, > + struct snd_kcontrol *kcontrol, > + int event) > +{ > + struct snd_soc_component *cmpnt = snd_soc_dapm_to_component(w->dapm); > + struct mtk_base_afe *afe = snd_soc_component_get_drvdata(cmpnt); > + struct mt8186_afe_private *afe_priv = afe->platform_priv; > + int delay_data; > + int delay_cycle; > + > + switch (event) { > + case SND_SOC_DAPM_PRE_PMU: > + if (afe_priv->mtkaif_protocol == MTKAIF_PROTOCOL_2_CLK_P2) { > + /* set protocol 2 */ > + regmap_write(afe->regmap, AFE_ADDA_MTKAIF_CFG0, > + 0x00010000);
No leading zeros, please (also, it fits in one line): regmap_write(afe->regmap, AFE_ADDA_MTKAIF_CFG0, 0x10000);
> + /* mtkaif_rxif_clkinv_adc inverse */ > + regmap_update_bits(afe->regmap, AFE_ADDA_MTKAIF_CFG0, > + MTKAIF_RXIF_CLKINV_ADC_MASK_SFT, > + 0x1 << MTKAIF_RXIF_CLKINV_ADC_SFT);
Please use the BIT() macro: BIT(MTKAIF_RXIF_CLKINV_ADC_SFT)
> + > + if (strcmp(w->name, "ADDA_MTKAIF_CFG") == 0) { > + if (afe_priv->mtkaif_chosen_phase[0] < 0 && > + afe_priv->mtkaif_chosen_phase[1] < 0) { > + dev_err(afe->dev, > + "%s(), calib fail mtkaif_chosen_phase[0/1]:%d/%d\n", > + __func__, > + afe_priv->mtkaif_chosen_phase[0], > + afe_priv->mtkaif_chosen_phase[1]); > + break; > + } > + > + if (afe_priv->mtkaif_chosen_phase[0] < 0 || > + afe_priv->mtkaif_chosen_phase[1] < 0) { > + dev_err(afe->dev, > + "%s(), skip dealy setting mtkaif_chosen_phase[0/1]:%d/%d\n", > + __func__, > + afe_priv->mtkaif_chosen_phase[0], > + afe_priv->mtkaif_chosen_phase[1]); > + break; > + } > + } > + > + /* set delay for ch12 */ > + if (afe_priv->mtkaif_phase_cycle[0] >= > + afe_priv->mtkaif_phase_cycle[1]) { > + delay_data = DELAY_DATA_MISO1; > + delay_cycle = afe_priv->mtkaif_phase_cycle[0] - > + afe_priv->mtkaif_phase_cycle[1]; > + } else { > + delay_data = DELAY_DATA_MISO2; > + delay_cycle = afe_priv->mtkaif_phase_cycle[1] - > + afe_priv->mtkaif_phase_cycle[0]; > + } > + > + regmap_update_bits(afe->regmap, > + AFE_ADDA_MTKAIF_RX_CFG2, > + MTKAIF_RXIF_DELAY_DATA_MASK_SFT, > + delay_data << > + MTKAIF_RXIF_DELAY_DATA_SFT); > + > + regmap_update_bits(afe->regmap, > + AFE_ADDA_MTKAIF_RX_CFG2, > + MTKAIF_RXIF_DELAY_CYCLE_MASK_SFT, > + delay_cycle << > + MTKAIF_RXIF_DELAY_CYCLE_SFT); > + > + } else if (afe_priv->mtkaif_protocol == MTKAIF_PROTOCOL_2) { > + regmap_write(afe->regmap, AFE_ADDA_MTKAIF_CFG0, > + 0x00010000);
No leading zeroes, please.
> + } else { > + regmap_write(afe->regmap, AFE_ADDA_MTKAIF_CFG0, 0x0);
0x0 -> 0
> + } > + > + break; > + default: > + break; > + } > + > + return 0; > +} > + > +static int mtk_adda_dl_event(struct snd_soc_dapm_widget *w, > + struct snd_kcontrol *kcontrol, > + int event) > +{ > + struct snd_soc_component *cmpnt = snd_soc_dapm_to_component(w->dapm); > + struct mtk_base_afe *afe = snd_soc_component_get_drvdata(cmpnt); > + > + dev_dbg(afe->dev, "%s(), name %s, event 0x%x\n", > + __func__, w->name, event); > + > + switch (event) { > + case SND_SOC_DAPM_PRE_PMU: > + mt8186_afe_gpio_request(afe->dev, true, MT8186_DAI_ADDA, 0); > + break; > + case SND_SOC_DAPM_POST_PMD: > + /* should delayed 1/fs(smallest is 8k) = 125us before afe off */ > + usleep_range(125, 135); > + mt8186_afe_gpio_request(afe->dev, false, MT8186_DAI_ADDA, 0); > + break; > + default: > + break; > + } > + > + return 0; > +} > + > +static int mt8186_adda_dmic_get(struct snd_kcontrol *kcontrol, > + struct snd_ctl_elem_value *ucontrol) > +{ > + struct snd_soc_component *cmpnt = snd_soc_kcontrol_component(kcontrol); > + struct mtk_base_afe *afe = snd_soc_component_get_drvdata(cmpnt); > + struct mt8186_afe_private *afe_priv = afe->platform_priv; > + > + ucontrol->value.integer.value[0] = afe_priv->mtkaif_dmic; > + > + return 0; > +} > + > +static int mt8186_adda_dmic_set(struct snd_kcontrol *kcontrol, > + struct snd_ctl_elem_value *ucontrol) > +{ > + struct snd_soc_component *cmpnt = snd_soc_kcontrol_component(kcontrol); > + struct mtk_base_afe *afe = snd_soc_component_get_drvdata(cmpnt); > + struct mt8186_afe_private *afe_priv = afe->platform_priv; > + struct soc_enum *e = (struct soc_enum *)kcontrol->private_value; > + int dmic_on; > + > + if (ucontrol->value.enumerated.item[0] >= e->items) > + return -EINVAL; > + > + dmic_on = ucontrol->value.integer.value[0]; > + > + dev_info(afe->dev, "%s(), kcontrol name %s, dmic_on %d\n", > + __func__, kcontrol->id.name, dmic_on);
Shouldn't this be a dev_dbg() instead?
> + > + if (afe_priv->mtkaif_dmic == dmic_on) > + return 0; > + > + afe_priv->mtkaif_dmic = dmic_on; > + > + return 1; > +} > +
...snip...
> + > +#define HIRES_THRESHOLD 48000 > +static int mtk_afe_dac_hires_connect(struct snd_soc_dapm_widget *source, > + struct snd_soc_dapm_widget *sink) > +{ > + struct snd_soc_dapm_widget *w = source; > + struct snd_soc_component *cmpnt = snd_soc_dapm_to_component(w->dapm); > + struct mtk_base_afe *afe = snd_soc_component_get_drvdata(cmpnt); > + struct mtk_afe_adda_priv *adda_priv; > + > + adda_priv = get_adda_priv_by_name(afe, w->name); > + > + if (!adda_priv) { > + dev_info(afe->dev, "%s(), adda_priv == NULL", __func__);
dev_err()
> + return 0; > + } > + > + return (adda_priv->dl_rate > HIRES_THRESHOLD) ? 1 : 0; > +} > + > +static int mtk_afe_adc_hires_connect(struct snd_soc_dapm_widget *source, > + struct snd_soc_dapm_widget *sink) > +{ > + struct snd_soc_dapm_widget *w = source; > + struct snd_soc_component *cmpnt = snd_soc_dapm_to_component(w->dapm); > + struct mtk_base_afe *afe = snd_soc_component_get_drvdata(cmpnt); > + struct mtk_afe_adda_priv *adda_priv; > + > + adda_priv = get_adda_priv_by_name(afe, w->name); > + > + if (!adda_priv) { > + dev_info(afe->dev, "%s(), adda_priv == NULL", __func__);
dev_err()
> + return 0; > + } > + > + return (adda_priv->ul_rate > HIRES_THRESHOLD) ? 1 : 0; > +} > +
..snip..
> +}; > + > +/* dai ops */ > +static int mtk_dai_adda_hw_params(struct snd_pcm_substream *substream, > + struct snd_pcm_hw_params *params, > + struct snd_soc_dai *dai) > +{ > + struct mtk_base_afe *afe = snd_soc_dai_get_drvdata(dai); > + struct mt8186_afe_private *afe_priv = afe->platform_priv; > + unsigned int rate = params_rate(params); > + int id = dai->id; > + struct mtk_afe_adda_priv *adda_priv = afe_priv->dai_priv[id]; > + > + dev_info(afe->dev, "%s(), id %d, stream %d, rate %d\n", > + __func__, > + id, > + substream->stream, > + rate); > + > + if (!adda_priv) { > + dev_info(afe->dev, "%s(), adda_priv == NULL", __func__); > + return -EINVAL; > + } > + > + if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { > + unsigned int dl_src2_con0 = 0; > + unsigned int dl_src2_con1 = 0;
This initialization is redundant: you're never using these variables before initializing them later, so initializing them to zero is not needed here.
> + > + adda_priv->dl_rate = rate; > + > + /* set sampling rate */ > + dl_src2_con0 = adda_dl_rate_transform(afe, rate) << > + DL_2_INPUT_MODE_CTL_SFT; > + > + /* set output mode, UP_SAMPLING_RATE_X8 */ > + dl_src2_con0 |= (0x3 << DL_2_OUTPUT_SEL_CTL_SFT); > + > + /* turn off mute function */ > + dl_src2_con0 |= (0x01 << DL_2_MUTE_CH2_OFF_CTL_PRE_SFT);
BIT() macro, please
> + dl_src2_con0 |= (0x01 << DL_2_MUTE_CH1_OFF_CTL_PRE_SFT); > + > + /* set voice input data if input sample rate is 8k or 16k */ > + if (rate == 8000 || rate == 16000) > + dl_src2_con0 |= 0x01 << DL_2_VOICE_MODE_CTL_PRE_SFT; > + > + /* SA suggest apply -0.3db to audio/speech path */ > + dl_src2_con1 = MTK_AFE_ADDA_DL_GAIN_NORMAL << > + DL_2_GAIN_CTL_PRE_SFT; > + > + /* turn on down-link gain */ > + dl_src2_con0 |= (0x01 << DL_2_GAIN_ON_CTL_PRE_SFT); > + > + if (id == MT8186_DAI_ADDA) { > + /* clean predistortion */ > + regmap_write(afe->regmap, AFE_ADDA_PREDIS_CON0, 0); > + regmap_write(afe->regmap, AFE_ADDA_PREDIS_CON1, 0); > + > + regmap_write(afe->regmap, > + AFE_ADDA_DL_SRC2_CON0, dl_src2_con0); > + regmap_write(afe->regmap, > + AFE_ADDA_DL_SRC2_CON1, dl_src2_con1); > + > + /* set sdm gain */ > + regmap_update_bits(afe->regmap, > + AFE_ADDA_DL_SDM_DCCOMP_CON, > + ATTGAIN_CTL_MASK_SFT, > + AUDIO_SDM_LEVEL_NORMAL << > + ATTGAIN_CTL_SFT); > + > + /* Use new 2nd sdm */ > + regmap_update_bits(afe->regmap, > + AFE_ADDA_DL_SDM_DITHER_CON, > + AFE_DL_SDM_DITHER_64TAP_EN_MASK_SFT, > + 0x1 << AFE_DL_SDM_DITHER_64TAP_EN_SFT);
BIT(AFE_DL_SDM_DITHER_64TAP_EN_SFT)
> + regmap_update_bits(afe->regmap, > + AFE_ADDA_DL_SDM_AUTO_RESET_CON, > + AFE_DL_USE_NEW_2ND_SDM_MASK_SFT, > + 0x1 << AFE_DL_USE_NEW_2ND_SDM_SFT);
BIT(AFE_DL_USE_NEW_2ND_SDM_SFT)
> + regmap_update_bits(afe->regmap, > + AFE_ADDA_DL_SDM_DCCOMP_CON, > + USE_3RD_SDM_MASK_SFT, > + AUDIO_SDM_2ND << USE_3RD_SDM_SFT); > + > + /* sdm auto reset */ > + regmap_write(afe->regmap, > + AFE_ADDA_DL_SDM_AUTO_RESET_CON, > + SDM_AUTO_RESET_THRESHOLD); > + regmap_update_bits(afe->regmap, > + AFE_ADDA_DL_SDM_AUTO_RESET_CON, > + SDM_AUTO_RESET_TEST_ON_MASK_SFT, > + 0x1 << SDM_AUTO_RESET_TEST_ON_SFT);
BIT(SDM_AUTO_RESET_TEST_ON_SFT)
> + } > + } else { > + unsigned int voice_mode = 0;
what about... unsigned int ul_src_con0 = 0; /* default value */ unsigned int voice_mode = adda_ul_rate_transform(afe, rate);
> + unsigned int ul_src_con0 = 0; /* default value */ > + > + adda_priv->ul_rate = rate; > + > + voice_mode = adda_ul_rate_transform(afe, rate); > + > + ul_src_con0 |= (voice_mode << 17) & (0x7 << 17); > + > + /* enable iir */ > + ul_src_con0 |= (1 << UL_IIR_ON_TMP_CTL_SFT) & > + UL_IIR_ON_TMP_CTL_MASK_SFT; > + ul_src_con0 |= (UL_IIR_SW << UL_IIRMODE_CTL_SFT) & > + UL_IIRMODE_CTL_MASK_SFT; > + switch (id) { > + case MT8186_DAI_ADDA: > + case MT8186_DAI_AP_DMIC: > + /* 35Hz @ 48k */ > + regmap_write(afe->regmap, > + AFE_ADDA_IIR_COEF_02_01, 0x00000000);
Please drop leading zeroes:
regmap_write(afe->regmap, AFE_ADDA_IIR_COEF_02_01, 0);
> + regmap_write(afe->regmap, > + AFE_ADDA_IIR_COEF_04_03, 0x00003FB8);
... and also please write hex in lower-case:
regmap_write(afe->regmap, AFE_ADDA_IIR_COEF_04_03, 0x03fb8);
> + regmap_write(afe->regmap, > + AFE_ADDA_IIR_COEF_06_05, 0x3FB80000); > + regmap_write(afe->regmap, > + AFE_ADDA_IIR_COEF_08_07, 0x3FB80000); > + regmap_write(afe->regmap, > + AFE_ADDA_IIR_COEF_10_09, 0x0000C048); > + > + regmap_write(afe->regmap, > + AFE_ADDA_UL_SRC_CON0, ul_src_con0); > + > + /* Using Internal ADC */ > + regmap_update_bits(afe->regmap, > + AFE_ADDA_TOP_CON0, > + 0x1 << 0, > + 0x0 << 0);
Please use the BIT() macro:
regmap_update_bits(afe->regmap, AFE_ADDA_TOP_CON0, BIT(0), 0);
P.S.: 87 columns is ok
> + > + /* mtkaif_rxif_data_mode = 0, amic */ > + regmap_update_bits(afe->regmap, > + AFE_ADDA_MTKAIF_RX_CFG0, > + 0x1 << 0, > + 0x0 << 0);
same here.
> + break; > + default: > + break; > + } > + > + /* ap dmic */ > + switch (id) { > + case MT8186_DAI_AP_DMIC: > + mtk_adda_ul_src_dmic(afe, id); > + break; > + default: > + break; > + } > + } > + > + return 0; > +} > +
Regards, Angelo
| |