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, };