ASoC: msm: enable tdm pinctrl config on 6155 machine

Enable dynamic TDM pinctrl configuration based
on CPU DAI activity on auto 6155 machine drv.

Change-Id: I4550b0e098d450d3ac29c162630c2450d42ac384
Signed-off-by: Derek Chen <chenche@codeaurora.org>
diff --git a/asoc/sa6155.c b/asoc/sa6155.c
index 2e243e8..ab4e842 100644
--- a/asoc/sa6155.c
+++ b/asoc/sa6155.c
@@ -128,26 +128,24 @@
 };
 
 enum pinctrl_pin_state {
-	STATE_DISABLE = 0, /* All pins are in sleep state */
-	STATE_MI2S_ACTIVE,  /* I2S = active, TDM = sleep */
-	STATE_TDM_ACTIVE,  /* I2S = sleep, TDM = active */
+	STATE_SLEEP = 0, /* All pins are in sleep state */
+	STATE_ACTIVE,  /* TDM = active */
 };
 
 struct msm_pinctrl_info {
 	struct pinctrl *pinctrl;
-	struct pinctrl_state *mi2s_disable;
-	struct pinctrl_state *tdm_disable;
-	struct pinctrl_state *mi2s_active;
-	struct pinctrl_state *tdm_active;
+	struct pinctrl_state *sleep;
+	struct pinctrl_state *active;
 	enum pinctrl_pin_state curr_state;
 };
 
-struct msm_asoc_mach_data {
-	struct msm_pinctrl_info pinctrl_info;
-};
+static const char *const pin_states[] = {"sleep", "active"};
 
-static const char *const pin_states[] = {"sleep", "i2s-active",
-					 "tdm-active"};
+static const char *const tdm_gpio_phandle[] = {"qcom,pri-tdm-gpios",
+						"qcom,sec-tdm-gpios",
+						"qcom,tert-tdm-gpios",
+						"qcom,quat-tdm-gpios",
+						"qcom,quin-tdm-gpios"};
 
 enum {
 	TDM_0 = 0,
@@ -175,6 +173,11 @@
 	u32 channel;
 };
 
+struct tdm_conf {
+	struct mutex lock;
+	u32 ref_cnt;
+};
+
 /* TDM default config */
 static struct dev_config tdm_rx_cfg[TDM_INTERFACE_MAX][TDM_PORT_MAX] = {
 	{ /* PRI TDM */
@@ -743,7 +746,11 @@
 
 };
 
-static struct mi2s_conf mi2s_intf_conf[MI2S_MAX];
+struct msm_asoc_mach_data {
+	struct msm_pinctrl_info pinctrl_info[TDM_INTERFACE_MAX];
+	struct mi2s_conf mi2s_intf_conf[MI2S_MAX];
+	struct tdm_conf tdm_intf_conf[TDM_INTERFACE_MAX];
+};
 
 static int usb_audio_rx_ch_get(struct snd_kcontrol *kcontrol,
 			       struct snd_ctl_elem_value *ucontrol)
@@ -3735,7 +3742,6 @@
 	return ret;
 }
 
-#ifdef ENABLE_PINCTRL
 static int msm_set_pinctrl(struct msm_pinctrl_info *pinctrl_info,
 				enum pinctrl_pin_state new_state)
 {
@@ -3743,13 +3749,13 @@
 	int curr_state = 0;
 
 	if (pinctrl_info == NULL) {
-		pr_err("%s: pinctrl_info is NULL\n", __func__);
+		pr_err("%s: pinctrl info is NULL\n", __func__);
 		ret = -EINVAL;
 		goto err;
 	}
 
 	if (pinctrl_info->pinctrl == NULL) {
-		pr_err("%s: pinctrl_info->pinctrl is NULL\n", __func__);
+		pr_err("%s: pinctrl handle is NULL\n", __func__);
 		ret = -EINVAL;
 		goto err;
 	}
@@ -3760,55 +3766,40 @@
 		 pin_states[curr_state], pin_states[pinctrl_info->curr_state]);
 
 	if (curr_state == pinctrl_info->curr_state) {
-		pr_debug("%s: Already in same state\n", __func__);
+		pr_debug("%s: pin already in same state\n", __func__);
 		goto err;
 	}
 
-	if (curr_state != STATE_DISABLE &&
-		pinctrl_info->curr_state != STATE_DISABLE) {
-		pr_debug("%s: state already active cannot switch\n", __func__);
+	if (curr_state != STATE_SLEEP &&
+		pinctrl_info->curr_state != STATE_SLEEP) {
+		pr_debug("%s: pin state is already active, cannot switch\n", __func__);
 		ret = -EIO;
 		goto err;
 	}
 
 	switch (pinctrl_info->curr_state) {
-	case STATE_MI2S_ACTIVE:
+	case STATE_ACTIVE:
 		ret = pinctrl_select_state(pinctrl_info->pinctrl,
-					pinctrl_info->mi2s_active);
+					pinctrl_info->active);
 		if (ret) {
-			pr_err("%s: MI2S state select failed with %d\n",
+			pr_err("%s: state select to active failed with %d\n",
 				__func__, ret);
 			ret = -EIO;
 			goto err;
 		}
 		break;
-	case STATE_TDM_ACTIVE:
+	case STATE_SLEEP:
 		ret = pinctrl_select_state(pinctrl_info->pinctrl,
-					pinctrl_info->tdm_active);
+					pinctrl_info->sleep);
 		if (ret) {
-			pr_err("%s: TDM state select failed with %d\n",
-				__func__, ret);
-			ret = -EIO;
-			goto err;
-		}
-		break;
-	case STATE_DISABLE:
-		if (curr_state == STATE_MI2S_ACTIVE) {
-			ret = pinctrl_select_state(pinctrl_info->pinctrl,
-					pinctrl_info->mi2s_disable);
-		} else {
-			ret = pinctrl_select_state(pinctrl_info->pinctrl,
-					pinctrl_info->tdm_disable);
-		}
-		if (ret) {
-			pr_err("%s:  state disable failed with %d\n",
+			pr_err("%s: state select to sleep failed with %d\n",
 				__func__, ret);
 			ret = -EIO;
 			goto err;
 		}
 		break;
 	default:
-		pr_err("%s: TLMM pin state is invalid\n", __func__);
+		pr_err("%s: pin state is invalid\n", __func__);
 		return -EINVAL;
 	}
 
@@ -3820,11 +3811,17 @@
 {
 	struct snd_soc_card *card = platform_get_drvdata(pdev);
 	struct msm_asoc_mach_data *pdata = snd_soc_card_get_drvdata(card);
-	struct msm_pinctrl_info *pinctrl_info = &pdata->pinctrl_info;
+	struct msm_pinctrl_info *pinctrl_info = NULL;
+	int i;
 
-	if (pinctrl_info->pinctrl) {
-		devm_pinctrl_put(pinctrl_info->pinctrl);
-		pinctrl_info->pinctrl = NULL;
+	for (i = TDM_PRI; i < TDM_INTERFACE_MAX; i++) {
+		pinctrl_info = &pdata->pinctrl_info[i];
+		if (pinctrl_info == NULL)
+			continue;
+		if (pinctrl_info->pinctrl) {
+			devm_pinctrl_put(pinctrl_info->pinctrl);
+			pinctrl_info->pinctrl = NULL;
+		}
 	}
 }
 
@@ -3833,85 +3830,173 @@
 	struct snd_soc_card *card = platform_get_drvdata(pdev);
 	struct msm_asoc_mach_data *pdata = snd_soc_card_get_drvdata(card);
 	struct msm_pinctrl_info *pinctrl_info = NULL;
-	struct pinctrl *pinctrl;
+	struct pinctrl *pinctrl = NULL;
+	int i, j;
+	struct device_node *np = NULL;
+	struct platform_device *pdev_np = NULL;
 	int ret = 0;
 
-	pinctrl_info = &pdata->pinctrl_info;
+	for (i = TDM_PRI; i < TDM_INTERFACE_MAX; i++) {
+		np = of_parse_phandle(pdev->dev.of_node,
+					tdm_gpio_phandle[i], 0);
+		if (!np) {
+			pr_debug("%s: device node %s is null\n",
+					__func__, tdm_gpio_phandle[i]);
+			continue;
+		}
 
-	if (pinctrl_info == NULL) {
-		pr_err("%s: pinctrl_info is NULL\n", __func__);
-		return -EINVAL;
-	}
+		pdev_np = of_find_device_by_node(np);
+		if (!pdev_np) {
+			pr_err("%s: platform device not found\n", __func__);
+			continue;
+		}
 
-	pinctrl = devm_pinctrl_get(&pdev->dev);
-	if (IS_ERR_OR_NULL(pinctrl)) {
-		pr_err("%s: Unable to get pinctrl handle\n", __func__);
-		return -EINVAL;
-	}
-	pinctrl_info->pinctrl = pinctrl;
+		pinctrl_info = &pdata->pinctrl_info[i];
+		if (pinctrl_info == NULL) {
+			pr_err("%s: pinctrl info is null\n", __func__);
+			continue;
+		}
 
-	/* get all the states handles from Device Tree */
-	pinctrl_info->mi2s_disable = pinctrl_lookup_state(pinctrl,
-						"quat_mi2s_disable");
-	if (IS_ERR(pinctrl_info->mi2s_disable)) {
-		pr_err("%s: could not get mi2s_disable pinstate\n", __func__);
-		goto err;
-	}
-	pinctrl_info->mi2s_active = pinctrl_lookup_state(pinctrl,
-						"quat_mi2s_enable");
-	if (IS_ERR(pinctrl_info->mi2s_active)) {
-		pr_err("%s: could not get mi2s_active pinstate\n", __func__);
-		goto err;
-	}
-	pinctrl_info->tdm_disable = pinctrl_lookup_state(pinctrl,
-						"quat_tdm_disable");
-	if (IS_ERR(pinctrl_info->tdm_disable)) {
-		pr_err("%s: could not get tdm_disable pinstate\n", __func__);
-		goto err;
-	}
-	pinctrl_info->tdm_active = pinctrl_lookup_state(pinctrl,
-						"quat_tdm_enable");
-	if (IS_ERR(pinctrl_info->tdm_active)) {
-		pr_err("%s: could not get tdm_active pinstate\n",
-			__func__);
-		goto err;
-	}
-	/* Reset the TLMM pins to a default state */
-	ret = pinctrl_select_state(pinctrl_info->pinctrl,
-					pinctrl_info->mi2s_disable);
-	if (ret != 0) {
-		pr_err("%s: Disable TLMM pins failed with %d\n",
-			__func__, ret);
-		ret = -EIO;
-		goto err;
-	}
-	pinctrl_info->curr_state = STATE_DISABLE;
+		pinctrl = devm_pinctrl_get(&pdev_np->dev);
+		if (IS_ERR_OR_NULL(pinctrl)) {
+			pr_err("%s: fail to get pinctrl handle\n", __func__);
+			goto err;
+		}
+		pinctrl_info->pinctrl = pinctrl;
 
+		/* get all the states handles from Device Tree */
+		pinctrl_info->sleep = pinctrl_lookup_state(pinctrl,
+							"sleep");
+		if (IS_ERR(pinctrl_info->sleep)) {
+			pr_err("%s: could not get sleep pin state\n", __func__);
+			goto err;
+		}
+		pinctrl_info->active = pinctrl_lookup_state(pinctrl,
+							"default");
+		if (IS_ERR(pinctrl_info->active)) {
+			pr_err("%s: could not get active pin state\n",
+				__func__);
+			goto err;
+		}
+
+		/* Reset the TLMM pins to a sleep state */
+		ret = pinctrl_select_state(pinctrl_info->pinctrl,
+						pinctrl_info->sleep);
+		if (ret != 0) {
+			pr_err("%s: set pin state to sleep failed with %d\n",
+				__func__, ret);
+			ret = -EIO;
+			goto err;
+		}
+		pinctrl_info->curr_state = STATE_SLEEP;
+	}
 	return 0;
 
 err:
-	devm_pinctrl_put(pinctrl);
-	pinctrl_info->pinctrl = NULL;
+	for (j = i; j >= 0; j--) {
+		pinctrl_info = &pdata->pinctrl_info[j];
+		if (pinctrl_info == NULL)
+			continue;
+		if (pinctrl_info->pinctrl) {
+			devm_pinctrl_put(pinctrl_info->pinctrl);
+			pinctrl_info->pinctrl = NULL;
+		}
+	}
 	return -EINVAL;
 }
-#else
-static int msm_set_pinctrl(struct msm_pinctrl_info *pinctrl_info,
-				enum pinctrl_pin_state new_state)
-{
-	return 0;
-}
 
-static void msm_release_pinctrl(struct platform_device *pdev)
+static int msm_tdm_get_intf_idx(u16 id)
 {
-	return;
+	switch (id) {
+	case AFE_PORT_ID_PRIMARY_TDM_RX:
+	case AFE_PORT_ID_PRIMARY_TDM_RX_1:
+	case AFE_PORT_ID_PRIMARY_TDM_RX_2:
+	case AFE_PORT_ID_PRIMARY_TDM_RX_3:
+	case AFE_PORT_ID_PRIMARY_TDM_RX_4:
+	case AFE_PORT_ID_PRIMARY_TDM_RX_5:
+	case AFE_PORT_ID_PRIMARY_TDM_RX_6:
+	case AFE_PORT_ID_PRIMARY_TDM_RX_7:
+	case AFE_PORT_ID_PRIMARY_TDM_TX:
+	case AFE_PORT_ID_PRIMARY_TDM_TX_1:
+	case AFE_PORT_ID_PRIMARY_TDM_TX_2:
+	case AFE_PORT_ID_PRIMARY_TDM_TX_3:
+	case AFE_PORT_ID_PRIMARY_TDM_TX_4:
+	case AFE_PORT_ID_PRIMARY_TDM_TX_5:
+	case AFE_PORT_ID_PRIMARY_TDM_TX_6:
+	case AFE_PORT_ID_PRIMARY_TDM_TX_7:
+		return TDM_PRI;
+	case AFE_PORT_ID_SECONDARY_TDM_RX:
+	case AFE_PORT_ID_SECONDARY_TDM_RX_1:
+	case AFE_PORT_ID_SECONDARY_TDM_RX_2:
+	case AFE_PORT_ID_SECONDARY_TDM_RX_3:
+	case AFE_PORT_ID_SECONDARY_TDM_RX_4:
+	case AFE_PORT_ID_SECONDARY_TDM_RX_5:
+	case AFE_PORT_ID_SECONDARY_TDM_RX_6:
+	case AFE_PORT_ID_SECONDARY_TDM_RX_7:
+	case AFE_PORT_ID_SECONDARY_TDM_TX:
+	case AFE_PORT_ID_SECONDARY_TDM_TX_1:
+	case AFE_PORT_ID_SECONDARY_TDM_TX_2:
+	case AFE_PORT_ID_SECONDARY_TDM_TX_3:
+	case AFE_PORT_ID_SECONDARY_TDM_TX_4:
+	case AFE_PORT_ID_SECONDARY_TDM_TX_5:
+	case AFE_PORT_ID_SECONDARY_TDM_TX_6:
+	case AFE_PORT_ID_SECONDARY_TDM_TX_7:
+		return TDM_SEC;
+	case AFE_PORT_ID_TERTIARY_TDM_RX:
+	case AFE_PORT_ID_TERTIARY_TDM_RX_1:
+	case AFE_PORT_ID_TERTIARY_TDM_RX_2:
+	case AFE_PORT_ID_TERTIARY_TDM_RX_3:
+	case AFE_PORT_ID_TERTIARY_TDM_RX_4:
+	case AFE_PORT_ID_TERTIARY_TDM_RX_5:
+	case AFE_PORT_ID_TERTIARY_TDM_RX_6:
+	case AFE_PORT_ID_TERTIARY_TDM_RX_7:
+	case AFE_PORT_ID_TERTIARY_TDM_TX:
+	case AFE_PORT_ID_TERTIARY_TDM_TX_1:
+	case AFE_PORT_ID_TERTIARY_TDM_TX_2:
+	case AFE_PORT_ID_TERTIARY_TDM_TX_3:
+	case AFE_PORT_ID_TERTIARY_TDM_TX_4:
+	case AFE_PORT_ID_TERTIARY_TDM_TX_5:
+	case AFE_PORT_ID_TERTIARY_TDM_TX_6:
+	case AFE_PORT_ID_TERTIARY_TDM_TX_7:
+		return TDM_TERT;
+	case AFE_PORT_ID_QUATERNARY_TDM_RX:
+	case AFE_PORT_ID_QUATERNARY_TDM_RX_1:
+	case AFE_PORT_ID_QUATERNARY_TDM_RX_2:
+	case AFE_PORT_ID_QUATERNARY_TDM_RX_3:
+	case AFE_PORT_ID_QUATERNARY_TDM_RX_4:
+	case AFE_PORT_ID_QUATERNARY_TDM_RX_5:
+	case AFE_PORT_ID_QUATERNARY_TDM_RX_6:
+	case AFE_PORT_ID_QUATERNARY_TDM_RX_7:
+	case AFE_PORT_ID_QUATERNARY_TDM_TX:
+	case AFE_PORT_ID_QUATERNARY_TDM_TX_1:
+	case AFE_PORT_ID_QUATERNARY_TDM_TX_2:
+	case AFE_PORT_ID_QUATERNARY_TDM_TX_3:
+	case AFE_PORT_ID_QUATERNARY_TDM_TX_4:
+	case AFE_PORT_ID_QUATERNARY_TDM_TX_5:
+	case AFE_PORT_ID_QUATERNARY_TDM_TX_6:
+	case AFE_PORT_ID_QUATERNARY_TDM_TX_7:
+		return TDM_QUAT;
+	case AFE_PORT_ID_QUINARY_TDM_RX:
+	case AFE_PORT_ID_QUINARY_TDM_RX_1:
+	case AFE_PORT_ID_QUINARY_TDM_RX_2:
+	case AFE_PORT_ID_QUINARY_TDM_RX_3:
+	case AFE_PORT_ID_QUINARY_TDM_RX_4:
+	case AFE_PORT_ID_QUINARY_TDM_RX_5:
+	case AFE_PORT_ID_QUINARY_TDM_RX_6:
+	case AFE_PORT_ID_QUINARY_TDM_RX_7:
+	case AFE_PORT_ID_QUINARY_TDM_TX:
+	case AFE_PORT_ID_QUINARY_TDM_TX_1:
+	case AFE_PORT_ID_QUINARY_TDM_TX_2:
+	case AFE_PORT_ID_QUINARY_TDM_TX_3:
+	case AFE_PORT_ID_QUINARY_TDM_TX_4:
+	case AFE_PORT_ID_QUINARY_TDM_TX_5:
+	case AFE_PORT_ID_QUINARY_TDM_TX_6:
+	case AFE_PORT_ID_QUINARY_TDM_TX_7:
+		return TDM_QUIN;
+	default: return -EINVAL;
+	}
 }
 
-static int msm_get_pinctrl(struct platform_device *pdev)
-{
-	return 0;
-}
-#endif
-
 static int msm_tdm_be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd,
 				      struct snd_pcm_hw_params *params)
 {
@@ -4661,37 +4746,76 @@
 	struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
 	struct snd_soc_card *card = rtd->card;
 	struct msm_asoc_mach_data *pdata = snd_soc_card_get_drvdata(card);
-	struct msm_pinctrl_info *pinctrl_info = &pdata->pinctrl_info;
+	struct msm_pinctrl_info *pinctrl_info = NULL;
+	struct tdm_conf *intf_conf = NULL;
+	int ret_pinctrl = 0;
+	int index;
 
-	/* currently only supporting TDM_RX_0 and TDM_TX_0 */
-	if ((cpu_dai->id == AFE_PORT_ID_QUATERNARY_TDM_RX) ||
-		(cpu_dai->id == AFE_PORT_ID_QUATERNARY_TDM_TX)) {
-		ret = msm_set_pinctrl(pinctrl_info, STATE_TDM_ACTIVE);
-		if (ret)
-			pr_err("%s: TDM TLMM pinctrl set failed with %d\n",
-				__func__, ret);
+	pr_debug("%s: substream = %s, stream = %d, dai name = %s, dai id = %d\n",
+		__func__, substream->name, substream->stream,
+		cpu_dai->name, cpu_dai->id);
+
+	index = msm_tdm_get_intf_idx(cpu_dai->id);
+	if (index < 0) {
+		ret = -EINVAL;
+		pr_err("%s: CPU DAI id (%d) out of range\n",
+			__func__, cpu_dai->id);
+		goto err;
 	}
 
+	/*
+	 * Mutex protection in case the same TDM
+	 * interface using for both TX and RX so
+	 * that the same clock won't be enable twice.
+	 */
+	intf_conf = &pdata->tdm_intf_conf[index];
+	mutex_lock(&intf_conf->lock);
+	if (++intf_conf->ref_cnt == 1) {
+		pinctrl_info = &pdata->pinctrl_info[index];
+		ret_pinctrl = msm_set_pinctrl(pinctrl_info,
+					      STATE_ACTIVE);
+		if (ret_pinctrl)
+			pr_err("%s: TDM TLMM pinctrl set failed with %d\n",
+				__func__, ret_pinctrl);
+	}
+	mutex_unlock(&intf_conf->lock);
+
+err:
 	return ret;
 }
 
 static void sa6155_tdm_snd_shutdown(struct snd_pcm_substream *substream)
 {
-	int ret = 0;
 	struct snd_soc_pcm_runtime *rtd = substream->private_data;
 	struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
 	struct snd_soc_card *card = rtd->card;
 	struct msm_asoc_mach_data *pdata = snd_soc_card_get_drvdata(card);
-	struct msm_pinctrl_info *pinctrl_info = &pdata->pinctrl_info;
+	struct msm_pinctrl_info *pinctrl_info = NULL;
+	struct tdm_conf *intf_conf = NULL;
+	int ret_pinctrl = 0;
+	int index;
 
-	/* currently only supporting TDM_RX_0 and TDM_TX_0 */
-	if ((cpu_dai->id == AFE_PORT_ID_QUATERNARY_TDM_RX) ||
-		(cpu_dai->id == AFE_PORT_ID_QUATERNARY_TDM_TX)) {
-		ret = msm_set_pinctrl(pinctrl_info, STATE_DISABLE);
-		if (ret)
-			pr_err("%s: TDM TLMM pinctrl set failed with %d\n",
-				__func__, ret);
+	pr_debug("%s: substream = %s, stream = %d\n", __func__,
+		 substream->name, substream->stream);
+
+	index = msm_tdm_get_intf_idx(cpu_dai->id);
+	if (index < 0) {
+		pr_err("%s: CPU DAI id (%d) out of range\n",
+			__func__, cpu_dai->id);
+		return;
 	}
+
+	intf_conf = &pdata->tdm_intf_conf[index];
+	mutex_lock(&intf_conf->lock);
+	if (--intf_conf->ref_cnt == 0) {
+		pinctrl_info = &pdata->pinctrl_info[index];
+		ret_pinctrl = msm_set_pinctrl(pinctrl_info,
+					      STATE_SLEEP);
+		if (ret_pinctrl)
+			pr_err("%s: TDM TLMM pinctrl set failed with %d\n",
+				__func__, ret_pinctrl);
+	}
+	mutex_unlock(&intf_conf->lock);
 }
 
 static struct snd_soc_ops sa6155_tdm_be_ops = {
@@ -4733,7 +4857,8 @@
 	unsigned int fmt = SND_SOC_DAIFMT_CBS_CFS;
 	struct snd_soc_card *card = rtd->card;
 	struct msm_asoc_mach_data *pdata = snd_soc_card_get_drvdata(card);
-	struct msm_pinctrl_info *pinctrl_info = &pdata->pinctrl_info;
+	struct msm_pinctrl_info *pinctrl_info = NULL;
+	struct mi2s_conf *intf_conf = NULL;
 	int ret_pinctrl = 0;
 
 	dev_dbg(rtd->card->dev,
@@ -4753,10 +4878,11 @@
 	 * interface using for both TX and RX so
 	 * that the same clock won't be enable twice.
 	 */
-	mutex_lock(&mi2s_intf_conf[index].lock);
-	if (++mi2s_intf_conf[index].ref_cnt == 1) {
+	intf_conf = &pdata->mi2s_intf_conf[index];
+	mutex_lock(&intf_conf->lock);
+	if (++intf_conf->ref_cnt == 1) {
 		/* Check if msm needs to provide the clock to the interface */
-		if (!mi2s_intf_conf[index].msm_is_mi2s_master) {
+		if (!intf_conf->msm_is_mi2s_master) {
 			mi2s_clk[index].clk_id = mi2s_ebit_clk[index];
 			fmt = SND_SOC_DAIFMT_CBM_CFM;
 		}
@@ -4774,21 +4900,21 @@
 				__func__, index, ret);
 			goto clk_off;
 		}
-		if (index == QUAT_MI2S) {
-			ret_pinctrl = msm_set_pinctrl(pinctrl_info,
-						      STATE_MI2S_ACTIVE);
-			if (ret_pinctrl)
-				pr_err("%s: MI2S TLMM pinctrl set failed with %d\n",
-					__func__, ret_pinctrl);
-		}
+
+		pinctrl_info = &pdata->pinctrl_info[index];
+		ret_pinctrl = msm_set_pinctrl(pinctrl_info,
+					      STATE_ACTIVE);
+		if (ret_pinctrl)
+			pr_err("%s: MI2S TLMM pinctrl set failed with %d\n",
+				__func__, ret_pinctrl);
 	}
 clk_off:
 	if (ret < 0)
 		msm_mi2s_set_sclk(substream, false);
 clean_up:
 	if (ret < 0)
-		mi2s_intf_conf[index].ref_cnt--;
-	mutex_unlock(&mi2s_intf_conf[index].lock);
+		intf_conf->ref_cnt--;
+	mutex_unlock(&intf_conf->lock);
 err:
 	return ret;
 }
@@ -4800,7 +4926,8 @@
 	int index = rtd->cpu_dai->id;
 	struct snd_soc_card *card = rtd->card;
 	struct msm_asoc_mach_data *pdata = snd_soc_card_get_drvdata(card);
-	struct msm_pinctrl_info *pinctrl_info = &pdata->pinctrl_info;
+	struct msm_pinctrl_info *pinctrl_info = NULL;
+	struct mi2s_conf *intf_conf = NULL;
 	int ret_pinctrl = 0;
 
 	pr_debug("%s(): substream = %s  stream = %d\n", __func__,
@@ -4810,21 +4937,22 @@
 		return;
 	}
 
-	mutex_lock(&mi2s_intf_conf[index].lock);
-	if (--mi2s_intf_conf[index].ref_cnt == 0) {
+	intf_conf = &pdata->mi2s_intf_conf[index];
+	mutex_lock(&intf_conf->lock);
+	if (--intf_conf->ref_cnt == 0) {
 		ret = msm_mi2s_set_sclk(substream, false);
 		if (ret < 0)
 			pr_err("%s:clock disable failed for MI2S (%d); ret=%d\n",
 				__func__, index, ret);
-		if (index == QUAT_MI2S) {
-			ret_pinctrl = msm_set_pinctrl(pinctrl_info,
-						      STATE_DISABLE);
-			if (ret_pinctrl)
-				pr_err("%s: MI2S TLMM pinctrl set failed with %d\n",
-					__func__, ret_pinctrl);
-		}
+
+		pinctrl_info = &pdata->pinctrl_info[index];
+		ret_pinctrl = msm_set_pinctrl(pinctrl_info,
+					      STATE_SLEEP);
+		if (ret_pinctrl)
+			pr_err("%s: MI2S TLMM pinctrl set failed with %d\n",
+				__func__, ret_pinctrl);
 	}
-	mutex_unlock(&mi2s_intf_conf[index].lock);
+	mutex_unlock(&intf_conf->lock);
 }
 
 static struct snd_soc_ops msm_mi2s_be_ops = {
@@ -7087,19 +7215,22 @@
 /*****************************************************************************
 * TO BE UPDATED: Codec/Platform specific tdm slot and offset table selection
 *****************************************************************************/
-static int msm_tdm_init(struct device *dev)
+static int msm_tdm_init(struct platform_device *pdev)
 {
+	struct snd_soc_card *card = platform_get_drvdata(pdev);
+	struct msm_asoc_mach_data *pdata = snd_soc_card_get_drvdata(card);
 	const struct of_device_id *match;
+	int count;
 
-	match = of_match_node(sa6155_asoc_machine_of_match, dev->of_node);
+	match = of_match_node(sa6155_asoc_machine_of_match, pdev->dev.of_node);
 	if (!match) {
-		dev_err(dev, "%s: No DT match found for sound card\n",
+		dev_err(&pdev->dev, "%s: No DT match found for sound card\n",
 			__func__);
 		return -EINVAL;
 	}
 
 	if (!strcmp(match->data, "custom_codec")) {
-		dev_dbg(dev, "%s: custom tdm configuration\n", __func__);
+		dev_dbg(&pdev->dev, "%s: custom tdm configuration\n", __func__);
 
 		memcpy(tdm_rx_slot_offset,
 			tdm_rx_slot_offset_custom,
@@ -7111,21 +7242,40 @@
 			tdm_slot_custom,
 			sizeof(tdm_slot_custom));
 	} else {
-		dev_dbg(dev, "%s: default tdm configuration\n", __func__);
+		dev_dbg(&pdev->dev, "%s: default tdm configuration\n", __func__);
+	}
+
+	for (count = 0; count < TDM_INTERFACE_MAX; count++) {
+		mutex_init(&pdata->tdm_intf_conf[count].lock);
+		pdata->tdm_intf_conf[count].ref_cnt = 0;
 	}
 
 	return 0;
 }
 
+static void msm_tdm_deinit(struct platform_device *pdev)
+{
+	struct snd_soc_card *card = platform_get_drvdata(pdev);
+	struct msm_asoc_mach_data *pdata = snd_soc_card_get_drvdata(card);
+	int count;
+
+	for (count = 0; count < TDM_INTERFACE_MAX; count++) {
+		mutex_destroy(&pdata->tdm_intf_conf[count].lock);
+		pdata->tdm_intf_conf[count].ref_cnt = 0;
+	}
+}
+
 static void msm_i2s_auxpcm_init(struct platform_device *pdev)
 {
+	struct snd_soc_card *card = platform_get_drvdata(pdev);
+	struct msm_asoc_mach_data *pdata = snd_soc_card_get_drvdata(card);
 	int count;
 	u32 mi2s_master_slave[MI2S_MAX];
 	int ret;
 
 	for (count = 0; count < MI2S_MAX; count++) {
-		mutex_init(&mi2s_intf_conf[count].lock);
-		mi2s_intf_conf[count].ref_cnt = 0;
+		mutex_init(&pdata->mi2s_intf_conf[count].lock);
+		pdata->mi2s_intf_conf[count].ref_cnt = 0;
 	}
 
 	ret = of_property_read_u32_array(pdev->dev.of_node,
@@ -7136,20 +7286,22 @@
 			__func__);
 	} else {
 		for (count = 0; count < MI2S_MAX; count++) {
-			mi2s_intf_conf[count].msm_is_mi2s_master =
+			pdata->mi2s_intf_conf[count].msm_is_mi2s_master =
 				mi2s_master_slave[count];
 		}
 	}
 }
 
-static void msm_i2s_auxpcm_deinit(void)
+static void msm_i2s_auxpcm_deinit(struct platform_device *pdev)
 {
+	struct snd_soc_card *card = platform_get_drvdata(pdev);
+	struct msm_asoc_mach_data *pdata = snd_soc_card_get_drvdata(card);
 	int count;
 
 	for (count = 0; count < MI2S_MAX; count++) {
-		mutex_destroy(&mi2s_intf_conf[count].lock);
-		mi2s_intf_conf[count].ref_cnt = 0;
-		mi2s_intf_conf[count].msm_is_mi2s_master = 0;
+		mutex_destroy(&pdata->mi2s_intf_conf[count].lock);
+		pdata->mi2s_intf_conf[count].ref_cnt = 0;
+		pdata->mi2s_intf_conf[count].msm_is_mi2s_master = 0;
 	}
 }
 
@@ -7275,7 +7427,7 @@
 	card->controls = msm_snd_controls;
 	card->num_controls = ARRAY_SIZE(msm_snd_controls);
 
-	ret = msm_tdm_init(&pdev->dev);
+	ret = msm_tdm_init(pdev);
 	if (ret) {
 		ret = -EPROBE_DEFER;
 		goto err;
@@ -7297,7 +7449,7 @@
 		pr_debug("%s: pinctrl parsing successful\n", __func__);
 	} else {
 		dev_dbg(&pdev->dev,
-			"%s: Parsing pinctrl failed with %d. Cannot use Ports\n",
+			"%s: pinctrl parsing failed with %d\n",
 			__func__, ret);
 		ret = 0;
 	}
@@ -7318,7 +7470,8 @@
 
 static int msm_asoc_machine_remove(struct platform_device *pdev)
 {
-	msm_i2s_auxpcm_deinit();
+	msm_i2s_auxpcm_deinit(pdev);
+	msm_tdm_deinit(pdev);
 
 	msm_release_pinctrl(pdev);
 	return 0;