From a40c1bebd94ec3ed4f77ab2ab9db66c73ab597df Mon Sep 17 00:00:00 2001 From: Prasad Kumpatla Date: Thu, 8 Jul 2021 16:22:20 +0530 Subject: [PATCH] asoc: msm_common: clock handling for tdm interface Observed pop noise on TDM SPK AMP in the disable sequence. To resolve the pop noise, TDM clock should be turned OFF after digital mute ,which is done in machine driver for the disable sequence. Change-Id: I9c8b5ef820cd8ec1e9a7d022e1938d53e2f401a1 Signed-off-by: Prasad Kumpatla --- asoc/lahaina.c | 1 + asoc/msm_common.c | 93 +++++++++++++++++++++++++++++++++++++++++++++++ asoc/msm_common.h | 3 ++ asoc/sdx-target.c | 1 + asoc/waipio.c | 1 + 5 files changed, 99 insertions(+) diff --git a/asoc/lahaina.c b/asoc/lahaina.c index b6f47be14c..81d7d30ff4 100644 --- a/asoc/lahaina.c +++ b/asoc/lahaina.c @@ -213,6 +213,7 @@ static bool msm_swap_gnd_mic(struct snd_soc_component *component, bool active) } static struct snd_soc_ops msm_common_be_ops = { + .hw_params = msm_common_snd_hw_params, .startup = msm_common_snd_startup, .shutdown = msm_common_snd_shutdown, }; diff --git a/asoc/msm_common.c b/asoc/msm_common.c index f0efc80662..515bc96e81 100644 --- a/asoc/msm_common.c +++ b/asoc/msm_common.c @@ -18,10 +18,13 @@ #include #include #include +#include #include #include #include #include +#include +#include #include "msm_common.h" @@ -41,6 +44,8 @@ struct snd_card_pdata { #define DIR_SZ 10 #define MAX_CODEC_DAI 8 +#define TDM_SLOT_WIDTH_BITS 32 +#define TDM_MAX_SLOTS 4 static struct attribute device_state_attr = { .name = "state", @@ -239,6 +244,85 @@ static int get_intf_index(const char *stream_name) return -EINVAL; } +static int get_intf_clk_id(int index) +{ + int clk_id; + + switch(index) { + case PRI_MI2S_TDM_AUXPCM: + clk_id = Q6AFE_LPASS_CLK_ID_PRI_TDM_IBIT; + break; + case SEC_MI2S_TDM_AUXPCM: + clk_id = Q6AFE_LPASS_CLK_ID_SEC_TDM_IBIT; + break; + case TER_MI2S_TDM_AUXPCM: + clk_id = Q6AFE_LPASS_CLK_ID_TER_TDM_IBIT; + break; + case QUAT_MI2S_TDM_AUXPCM: + clk_id = Q6AFE_LPASS_CLK_ID_QUAD_TDM_IBIT; + break; + case QUIN_MI2S_TDM_AUXPCM: + clk_id = Q6AFE_LPASS_CLK_ID_QUIN_TDM_IBIT; + break; + case SEN_MI2S_TDM_AUXPCM: + clk_id = Q6AFE_LPASS_CLK_ID_SEN_TDM_IBIT; + break; + default: + pr_err("%s: Invalid interface index: %d\n", __func__, index); + clk_id = -EINVAL; + } + pr_debug("%s: clk id: %d\n", __func__, clk_id); + return clk_id; +} + +int msm_common_snd_hw_params(struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *params) +{ + int ret = 0; + int slot_width = TDM_SLOT_WIDTH_BITS; + int slots = TDM_MAX_SLOTS; + unsigned int rate; + struct snd_soc_pcm_runtime *rtd = substream->private_data; + const char *stream_name = rtd->dai_link->stream_name; + struct snd_soc_card *card = rtd->card; + struct msm_common_pdata *pdata = msm_common_get_pdata(card); + int index = get_intf_index(stream_name); + struct clk_cfg tdm_clk_cfg; + + if (index >= 0) { + mutex_lock(&pdata->lock[index]); + if (pdata->mi2s_gpio_p[index]) { + if ((strnstr(stream_name, "TDM", strlen(stream_name)))) { + rate = params_rate(params); + + tdm_clk_cfg.clk_id = get_intf_clk_id(index); + if (tdm_clk_cfg.clk_id < 0) { + ret = -EINVAL; + pr_err("%s: Invalid clk id %d", __func__, + tdm_clk_cfg.clk_id); + goto done; + } + + tdm_clk_cfg.clk_freq_in_hz = rate * slot_width * slots; + tdm_clk_cfg.clk_attri = Q6AFE_LPASS_CLK_ATTRIBUTE_COUPLE_NO; + tdm_clk_cfg.clk_root = 0; + + pr_debug("%s: clk_id :%d clk freq %d\n", __func__, + tdm_clk_cfg.clk_id, tdm_clk_cfg.clk_freq_in_hz); + ret = audio_prm_set_lpass_clk_cfg(&tdm_clk_cfg, 1); + if (ret < 0) { + pr_err("%s: prm lpass clk cfg set failed ret %d\n", + __func__, ret); + goto done; + } + } + } +done: + mutex_unlock(&pdata->lock[index]); + } + return ret; +} + int msm_common_snd_startup(struct snd_pcm_substream *substream) { int ret = 0; @@ -285,7 +369,9 @@ void msm_common_snd_shutdown(struct snd_pcm_substream *substream) struct msm_common_pdata *pdata = msm_common_get_pdata(card); const char *stream_name = rtd->dai_link->stream_name; int index = get_intf_index(stream_name); + struct clk_cfg tdm_clk_cfg; + memset(&tdm_clk_cfg, 0, sizeof(struct clk_cfg)); pr_debug("%s(): substream = %s stream = %d\n", __func__, substream->name, substream->stream); @@ -301,6 +387,13 @@ void msm_common_snd_shutdown(struct snd_pcm_substream *substream) if (pdata->mi2s_gpio_p[index]) { atomic_dec(&pdata->mi2s_gpio_ref_cnt[index]); if (atomic_read(&pdata->mi2s_gpio_ref_cnt[index]) == 0) { + if ((strnstr(stream_name, "TDM", strlen(stream_name)))) { + tdm_clk_cfg.clk_id = get_intf_clk_id(index); + ret = audio_prm_set_lpass_clk_cfg(&tdm_clk_cfg, 0); + if (ret < 0) + pr_err("%s: prm clk cfg set failed ret %d\n", + __func__, ret); + } ret = msm_cdc_pinctrl_select_sleep_state( pdata->mi2s_gpio_p[index]); if (ret) diff --git a/asoc/msm_common.h b/asoc/msm_common.h index a778a303db..0484c549ac 100644 --- a/asoc/msm_common.h +++ b/asoc/msm_common.h @@ -49,6 +49,9 @@ void msm_common_set_pdata(struct snd_soc_card *card, int snd_card_sysfs_init(void); +int msm_common_snd_hw_params(struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *params); + int msm_common_snd_startup(struct snd_pcm_substream *substream); void msm_common_snd_shutdown(struct snd_pcm_substream *substream); diff --git a/asoc/sdx-target.c b/asoc/sdx-target.c index bcd71c3a8e..f0cfad154e 100644 --- a/asoc/sdx-target.c +++ b/asoc/sdx-target.c @@ -209,6 +209,7 @@ static bool msm_swap_gnd_mic(struct snd_soc_component *component, bool active) } static struct snd_soc_ops msm_common_be_ops = { + .hw_params = msm_common_snd_hw_params, .startup = msm_common_snd_startup, .shutdown = msm_common_snd_shutdown, }; diff --git a/asoc/waipio.c b/asoc/waipio.c index 31bd447fd5..76fe0a67ca 100644 --- a/asoc/waipio.c +++ b/asoc/waipio.c @@ -177,6 +177,7 @@ static bool msm_usbc_swap_gnd_mic(struct snd_soc_component *component, bool acti } static struct snd_soc_ops msm_common_be_ops = { + .hw_params = msm_common_snd_hw_params, .startup = msm_common_snd_startup, .shutdown = msm_common_snd_shutdown, };