Jelajahi Sumber

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 <[email protected]>
Prasad Kumpatla 3 tahun lalu
induk
melakukan
a40c1bebd9
5 mengubah file dengan 99 tambahan dan 0 penghapusan
  1. 1 0
      asoc/lahaina.c
  2. 93 0
      asoc/msm_common.c
  3. 3 0
      asoc/msm_common.h
  4. 1 0
      asoc/sdx-target.c
  5. 1 0
      asoc/waipio.c

+ 1 - 0
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,
 };

+ 93 - 0
asoc/msm_common.c

@@ -18,10 +18,13 @@
 #include <sound/control.h>
 #include <sound/core.h>
 #include <sound/soc.h>
+#include <sound/pcm_params.h>
 #include <asoc/msm-cdc-pinctrl.h>
 #include <dsp/spf-core.h>
 #include <dsp/msm_audio_ion.h>
 #include <sound/info.h>
+#include <dsp/apr_audio-v2.h>
+#include <dsp/audio_prm.h>
 
 #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)

+ 3 - 0
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);

+ 1 - 0
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,
 };

+ 1 - 0
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,
 };