Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit e7b9f7aa authored by Linux Build Service Account's avatar Linux Build Service Account Committed by Gerrit - the friendly Code Review server
Browse files

Merge "asoc: sm6150: Add support for MI2S and TDM interfaces"

parents ee4bd965 353a583a
Loading
Loading
Loading
Loading
+223 −282
Original line number Original line Diff line number Diff line
@@ -117,6 +117,32 @@ enum {
	AUX_PCM_MAX,
	AUX_PCM_MAX,
};
};


enum {
	TDM_0 = 0,
	TDM_1,
	TDM_2,
	TDM_3,
	TDM_4,
	TDM_5,
	TDM_6,
	TDM_7,
	TDM_PORT_MAX,
};

enum {
	TDM_PRI = 0,
	TDM_SEC,
	TDM_TERT,
	TDM_QUAT,
	TDM_QUIN,
	TDM_INTERFACE_MAX,
};

struct tdm_port {
	u32 mode;
	u32 channel;
};

enum {
enum {
	WSA_CDC_DMA_RX_0 = 0,
	WSA_CDC_DMA_RX_0 = 0,
	WSA_CDC_DMA_RX_1,
	WSA_CDC_DMA_RX_1,
@@ -142,6 +168,7 @@ struct mi2s_conf {
	struct mutex lock;
	struct mutex lock;
	u32 ref_cnt;
	u32 ref_cnt;
	u32 msm_is_mi2s_master;
	u32 msm_is_mi2s_master;
	u32 msm_is_ext_mclk;
};
};


static u32 mi2s_ebit_clk[MI2S_MAX] = {
static u32 mi2s_ebit_clk[MI2S_MAX] = {
@@ -173,25 +200,10 @@ struct aux_codec_dev_info {
	u32 index;
	u32 index;
};
};


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 */
};

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;
	enum pinctrl_pin_state curr_state;
};

struct msm_asoc_mach_data {
struct msm_asoc_mach_data {
	struct snd_info_entry *codec_root;
	struct snd_info_entry *codec_root;
	struct msm_pinctrl_info pinctrl_info;
	int usbc_en2_gpio; /* used by gpio driver API */
	int usbc_en2_gpio; /* used by gpio driver API */
	struct device_node *mi2s_gpio_p[MI2S_MAX]; /* used by pinctrl API */
	struct device_node *dmic01_gpio_p; /* used by pinctrl API */
	struct device_node *dmic01_gpio_p; /* used by pinctrl API */
	struct device_node *dmic23_gpio_p; /* used by pinctrl API */
	struct device_node *dmic23_gpio_p; /* used by pinctrl API */
	struct device_node *us_euro_gpio_p; /* used by pinctrl API */
	struct device_node *us_euro_gpio_p; /* used by pinctrl API */
@@ -207,37 +219,8 @@ struct msm_asoc_wcd93xx_codec {
				   enum afe_config_type config_type);
				   enum afe_config_type config_type);
};
};


static const char *const pin_states[] = {"sleep", "i2s-active",
					 "tdm-active"};

static struct snd_soc_card snd_soc_card_sm6150_msm;
static struct snd_soc_card snd_soc_card_sm6150_msm;


enum {
	TDM_0 = 0,
	TDM_1,
	TDM_2,
	TDM_3,
	TDM_4,
	TDM_5,
	TDM_6,
	TDM_7,
	TDM_PORT_MAX,
};

enum {
	TDM_PRI = 0,
	TDM_SEC,
	TDM_TERT,
	TDM_QUAT,
	TDM_QUIN,
	TDM_INTERFACE_MAX,
};

struct tdm_port {
	u32 mode;
	u32 channel;
};

/* TDM default config */
/* TDM default config */
static struct dev_config tdm_rx_cfg[TDM_INTERFACE_MAX][TDM_PORT_MAX] = {
static struct dev_config tdm_rx_cfg[TDM_INTERFACE_MAX][TDM_PORT_MAX] = {
	{ /* PRI TDM */
	{ /* PRI TDM */
@@ -727,6 +710,49 @@ static struct afe_clk_set mi2s_clk[MI2S_MAX] = {


};
};


static struct afe_clk_set mi2s_mclk[MI2S_MAX] = {
	{
		AFE_API_VERSION_I2S_CONFIG,
		Q6AFE_LPASS_CLK_ID_MCLK_3,
		Q6AFE_LPASS_OSR_CLK_9_P600_MHZ,
		Q6AFE_LPASS_CLK_ATTRIBUTE_COUPLE_NO,
		Q6AFE_LPASS_CLK_ROOT_DEFAULT,
		0,
	},
	{
		AFE_API_VERSION_I2S_CONFIG,
		Q6AFE_LPASS_CLK_ID_MCLK_2,
		Q6AFE_LPASS_OSR_CLK_9_P600_MHZ,
		Q6AFE_LPASS_CLK_ATTRIBUTE_COUPLE_NO,
		Q6AFE_LPASS_CLK_ROOT_DEFAULT,
		0,
	},
	{
		AFE_API_VERSION_I2S_CONFIG,
		Q6AFE_LPASS_CLK_ID_MCLK_1,
		Q6AFE_LPASS_OSR_CLK_9_P600_MHZ,
		Q6AFE_LPASS_CLK_ATTRIBUTE_COUPLE_NO,
		Q6AFE_LPASS_CLK_ROOT_DEFAULT,
		0,
	},
	{
		AFE_API_VERSION_I2S_CONFIG,
		Q6AFE_LPASS_CLK_ID_MCLK_1,
		Q6AFE_LPASS_OSR_CLK_9_P600_MHZ,
		Q6AFE_LPASS_CLK_ATTRIBUTE_COUPLE_NO,
		Q6AFE_LPASS_CLK_ROOT_DEFAULT,
		0,
	},
	{
		AFE_API_VERSION_I2S_CONFIG,
		Q6AFE_LPASS_CLK_ID_QUI_MI2S_OSR,
		Q6AFE_LPASS_OSR_CLK_9_P600_MHZ,
		Q6AFE_LPASS_CLK_ATTRIBUTE_COUPLE_NO,
		Q6AFE_LPASS_CLK_ROOT_DEFAULT,
		0,
	}
};

static struct mi2s_conf mi2s_intf_conf[MI2S_MAX];
static struct mi2s_conf mi2s_intf_conf[MI2S_MAX];


static int slim_get_sample_rate_val(int sample_rate)
static int slim_get_sample_rate_val(int sample_rate)
@@ -4927,11 +4953,9 @@ static int msm_int_audrx_init(struct snd_soc_pcm_runtime *rtd)
	dev_dbg(component->dev, "%s: Number of aux devices: %d\n",
	dev_dbg(component->dev, "%s: Number of aux devices: %d\n",
		__func__, rtd->card->num_aux_devs);
		__func__, rtd->card->num_aux_devs);
	if (rtd->card->num_aux_devs &&
	if (rtd->card->num_aux_devs &&
	    !list_empty(&rtd->card->component_dev_list)) {
	    !list_empty(&rtd->card->aux_comp_list)) {
		aux_comp = list_first_entry(
		aux_comp = list_first_entry(&rtd->card->aux_comp_list,
				&rtd->card->component_dev_list,
				struct snd_soc_component, card_aux_list);
				struct snd_soc_component,
				card_aux_list);
		if (!strcmp(aux_comp->name, WSA8810_NAME_1) ||
		if (!strcmp(aux_comp->name, WSA8810_NAME_1) ||
		    !strcmp(aux_comp->name, WSA8810_NAME_2)) {
		    !strcmp(aux_comp->name, WSA8810_NAME_2)) {
			wsa_macro_set_spkr_mode(component,
			wsa_macro_set_spkr_mode(component,
@@ -5387,194 +5411,6 @@ static int msm_mi2s_set_sclk(struct snd_pcm_substream *substream, bool enable)
	return ret;
	return ret;
}
}


static int msm_set_pinctrl(struct msm_pinctrl_info *pinctrl_info,
				enum pinctrl_pin_state new_state)
{
	int ret = 0;
	int curr_state = 0;

	if (pinctrl_info == NULL) {
		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__);
		ret = -EINVAL;
		goto err;
	}

	curr_state = pinctrl_info->curr_state;
	pinctrl_info->curr_state = new_state;
	pr_debug("%s: curr_state = %s new_state = %s\n", __func__,
		 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__);
		goto err;
	}

	if (curr_state != STATE_DISABLE &&
		pinctrl_info->curr_state != STATE_DISABLE) {
		pr_debug("%s: state already active cannot switch\n", __func__);
		ret = -EIO;
		goto err;
	}

	switch (pinctrl_info->curr_state) {
	case STATE_MI2S_ACTIVE:
		ret = pinctrl_select_state(pinctrl_info->pinctrl,
					pinctrl_info->mi2s_active);
		if (ret) {
			pr_err("%s: MI2S state select failed with %d\n",
				__func__, ret);
			ret = -EIO;
			goto err;
		}
		break;
	case STATE_TDM_ACTIVE:
		ret = pinctrl_select_state(pinctrl_info->pinctrl,
					pinctrl_info->tdm_active);
		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",
				__func__, ret);
			ret = -EIO;
			goto err;
		}
		break;
	default:
		pr_err("%s: TLMM pin state is invalid\n", __func__);
		return -EINVAL;
	}

err:
	return ret;
}

static int msm_get_pinctrl(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);
	struct msm_pinctrl_info *pinctrl_info = NULL;
	struct pinctrl *pinctrl;
	int ret = 0;

	pinctrl_info = &pdata->pinctrl_info;

	if (pinctrl_info == NULL) {
		pr_err("%s: pinctrl_info is NULL\n", __func__);
		return -EINVAL;
	}

	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;

	/* get all the states handles from Device Tree */
	pinctrl_info->mi2s_disable = pinctrl_lookup_state(pinctrl,
						"quat-mi2s-sleep");
	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-active");
	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-sleep");
	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-active");
	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;

	return 0;

err:
	devm_pinctrl_put(pinctrl);
	pinctrl_info->pinctrl = NULL;
	return -EINVAL;
}

static int msm_tdm_be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd,
				      struct snd_pcm_hw_params *params)
{
	struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
	struct snd_interval *rate = hw_param_interval(params,
					SNDRV_PCM_HW_PARAM_RATE);
	struct snd_interval *channels = hw_param_interval(params,
					SNDRV_PCM_HW_PARAM_CHANNELS);

	if (cpu_dai->id == AFE_PORT_ID_QUATERNARY_TDM_RX) {
		channels->min = channels->max =
				tdm_rx_cfg[TDM_QUAT][TDM_0].channels;
		param_set_mask(params, SNDRV_PCM_HW_PARAM_FORMAT,
			       tdm_rx_cfg[TDM_QUAT][TDM_0].bit_format);
		rate->min = rate->max =
				tdm_rx_cfg[TDM_QUAT][TDM_0].sample_rate;
	} else if (cpu_dai->id == AFE_PORT_ID_SECONDARY_TDM_RX) {
		channels->min = channels->max =
				tdm_rx_cfg[TDM_SEC][TDM_0].channels;
		param_set_mask(params, SNDRV_PCM_HW_PARAM_FORMAT,
			       tdm_rx_cfg[TDM_SEC][TDM_0].bit_format);
		rate->min = rate->max = tdm_rx_cfg[TDM_SEC][TDM_0].sample_rate;
	} else if (cpu_dai->id == AFE_PORT_ID_QUINARY_TDM_RX) {
		channels->min = channels->max =
				tdm_rx_cfg[TDM_QUIN][TDM_0].channels;
		param_set_mask(params, SNDRV_PCM_HW_PARAM_FORMAT,
			       tdm_rx_cfg[TDM_QUIN][TDM_0].bit_format);
		rate->min = rate->max = tdm_rx_cfg[TDM_QUIN][TDM_0].sample_rate;
	} else {
		pr_err("%s: dai id 0x%x not supported\n",
			__func__, cpu_dai->id);
		return -EINVAL;
	}

	pr_debug("%s: dai id = 0x%x channels = %d rate = %d format = 0x%x\n",
		__func__, cpu_dai->id, channels->max, rate->max,
		params_format(params));

	return 0;
}

static int sm6150_tdm_snd_hw_params(struct snd_pcm_substream *substream,
static int sm6150_tdm_snd_hw_params(struct snd_pcm_substream *substream,
				     struct snd_pcm_hw_params *params)
				     struct snd_pcm_hw_params *params)
{
{
@@ -5691,6 +5527,38 @@ static int sm6150_tdm_snd_hw_params(struct snd_pcm_substream *substream,
	return ret;
	return ret;
}
}


static int msm_get_tdm_mode(u32 port_id)
{
	int tdm_mode;

	switch (port_id) {
	case AFE_PORT_ID_PRIMARY_TDM_RX:
	case AFE_PORT_ID_PRIMARY_TDM_TX:
		tdm_mode = TDM_PRI;
	break;
	case AFE_PORT_ID_SECONDARY_TDM_RX:
	case AFE_PORT_ID_SECONDARY_TDM_TX:
		tdm_mode = TDM_SEC;
	break;
	case AFE_PORT_ID_TERTIARY_TDM_RX:
	case AFE_PORT_ID_TERTIARY_TDM_TX:
		tdm_mode = TDM_TERT;
	break;
	case AFE_PORT_ID_QUATERNARY_TDM_RX:
	case AFE_PORT_ID_QUATERNARY_TDM_TX:
		tdm_mode = TDM_QUAT;
	break;
	case AFE_PORT_ID_QUINARY_TDM_RX:
	case AFE_PORT_ID_QUINARY_TDM_TX:
		tdm_mode = TDM_QUIN;
	break;
	default:
		pr_err("%s: Invalid port id: %d\n", __func__, port_id);
		tdm_mode = -EINVAL;
	}
	return tdm_mode;
}

static int sm6150_tdm_snd_startup(struct snd_pcm_substream *substream)
static int sm6150_tdm_snd_startup(struct snd_pcm_substream *substream)
{
{
	int ret = 0;
	int ret = 0;
@@ -5698,37 +5566,38 @@ static int sm6150_tdm_snd_startup(struct snd_pcm_substream *substream)
	struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
	struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
	struct snd_soc_card *card = rtd->card;
	struct snd_soc_card *card = rtd->card;
	struct msm_asoc_mach_data *pdata = snd_soc_card_get_drvdata(card);
	struct msm_asoc_mach_data *pdata = snd_soc_card_get_drvdata(card);
	struct msm_pinctrl_info *pinctrl_info = &pdata->pinctrl_info;
	int tdm_mode = msm_get_tdm_mode(cpu_dai->id);


	/* currently only supporting TDM_RX_0 and TDM_TX_0 */
	if (tdm_mode < 0) {
	if ((cpu_dai->id == AFE_PORT_ID_QUATERNARY_TDM_RX) ||
		dev_err(rtd->card->dev, "%s: Invalid tdm_mode\n", __func__);
		(cpu_dai->id == AFE_PORT_ID_QUATERNARY_TDM_TX)) {
		return tdm_mode;
		ret = msm_set_pinctrl(pinctrl_info, STATE_TDM_ACTIVE);
		if (ret)
			pr_err("%s: TDM TLMM pinctrl set failed with %d\n",
				__func__, ret);
	}
	}


	/* currently only supporting TDM_RX_0 and TDM_TX_0 */
	if (pdata->mi2s_gpio_p[tdm_mode])
		ret = msm_cdc_pinctrl_select_active_state(
				pdata->mi2s_gpio_p[tdm_mode]);

	return ret;
	return ret;
}
}


static void sm6150_tdm_snd_shutdown(struct snd_pcm_substream *substream)
static void sm6150_tdm_snd_shutdown(struct snd_pcm_substream *substream)
{
{
	int ret = 0;
	struct snd_soc_pcm_runtime *rtd = substream->private_data;
	struct snd_soc_pcm_runtime *rtd = substream->private_data;
	struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
	struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
	struct snd_soc_card *card = rtd->card;
	struct snd_soc_card *card = rtd->card;
	struct msm_asoc_mach_data *pdata = snd_soc_card_get_drvdata(card);
	struct msm_asoc_mach_data *pdata = snd_soc_card_get_drvdata(card);
	struct msm_pinctrl_info *pinctrl_info = &pdata->pinctrl_info;
	int tdm_mode = msm_get_tdm_mode(cpu_dai->id);


	/* currently only supporting TDM_RX_0 and TDM_TX_0 */
	if (tdm_mode < 0) {
	if ((cpu_dai->id == AFE_PORT_ID_QUATERNARY_TDM_RX) ||
		dev_err(rtd->card->dev, "%s: Invalid tdm_mode\n", __func__);
		(cpu_dai->id == AFE_PORT_ID_QUATERNARY_TDM_TX)) {
		return;
		ret = msm_set_pinctrl(pinctrl_info, STATE_DISABLE);
		if (ret)
			pr_err("%s: TDM TLMM pinctrl set failed with %d\n",
				__func__, ret);
	}
	}

	/* currently only supporting TDM_RX_0 and TDM_TX_0 */
	if (pdata->mi2s_gpio_p[tdm_mode])
		msm_cdc_pinctrl_select_sleep_state(
				pdata->mi2s_gpio_p[tdm_mode]);
}
}


static struct snd_soc_ops sm6150_tdm_be_ops = {
static struct snd_soc_ops sm6150_tdm_be_ops = {
@@ -5767,17 +5636,22 @@ static int msm_mi2s_snd_startup(struct snd_pcm_substream *substream)
	struct snd_soc_pcm_runtime *rtd = substream->private_data;
	struct snd_soc_pcm_runtime *rtd = substream->private_data;
	struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
	struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
	int index = cpu_dai->id;
	int index = cpu_dai->id;
	int port_id = msm_get_port_id(rtd->dai_link->id);
	unsigned int fmt = SND_SOC_DAIFMT_CBS_CFS;
	unsigned int fmt = SND_SOC_DAIFMT_CBS_CFS;
	struct snd_soc_card *card = rtd->card;
	struct snd_soc_card *card = rtd->card;
	struct msm_asoc_mach_data *pdata = snd_soc_card_get_drvdata(card);
	struct msm_asoc_mach_data *pdata = snd_soc_card_get_drvdata(card);
	struct msm_pinctrl_info *pinctrl_info = &pdata->pinctrl_info;
	int ret_pinctrl = 0;


	dev_dbg(rtd->card->dev,
	dev_dbg(rtd->card->dev,
		"%s: substream = %s  stream = %d, dai name %s, dai ID %d\n",
		"%s: substream = %s  stream = %d, dai name %s, dai ID %d\n",
		__func__, substream->name, substream->stream,
		__func__, substream->name, substream->stream,
		cpu_dai->name, cpu_dai->id);
		cpu_dai->name, cpu_dai->id);


	if (port_id < 0) {
		dev_err(rtd->card->dev, "%s: Invalid port_id\n", __func__);
		ret = port_id;
		goto err;
	}

	if (index < PRIM_MI2S || index >= MI2S_MAX) {
	if (index < PRIM_MI2S || index >= MI2S_MAX) {
		ret = -EINVAL;
		ret = -EINVAL;
		dev_err(rtd->card->dev,
		dev_err(rtd->card->dev,
@@ -5811,13 +5685,21 @@ static int msm_mi2s_snd_startup(struct snd_pcm_substream *substream)
				__func__, index, ret);
				__func__, index, ret);
			goto clk_off;
			goto clk_off;
		}
		}
		if (index == QUAT_MI2S) {
		if (mi2s_intf_conf[index].msm_is_ext_mclk) {
			ret_pinctrl = msm_set_pinctrl(pinctrl_info,
			pr_debug("%s: Enabling mclk, clk_freq_in_hz = %u\n",
						      STATE_MI2S_ACTIVE);
				__func__, mi2s_mclk[index].clk_freq_in_hz);
			if (ret_pinctrl)
			ret = afe_set_lpass_clock_v2(port_id,
				pr_err("%s: MI2S TLMM pinctrl set failed with %d\n",
						     &mi2s_mclk[index]);
					__func__, ret_pinctrl);
			if (ret < 0) {
				pr_err("%s: afe lpass mclk failed, err:%d\n",
					__func__, ret);
				goto clk_off;
			}
			}
			mi2s_mclk[index].enable = 1;
		}
		if (pdata->mi2s_gpio_p[index])
			msm_cdc_pinctrl_select_active_state(
					pdata->mi2s_gpio_p[index]);
	}
	}
clk_off:
clk_off:
	if (ret < 0)
	if (ret < 0)
@@ -5835,13 +5717,18 @@ static void msm_mi2s_snd_shutdown(struct snd_pcm_substream *substream)
	int ret;
	int ret;
	struct snd_soc_pcm_runtime *rtd = substream->private_data;
	struct snd_soc_pcm_runtime *rtd = substream->private_data;
	int index = rtd->cpu_dai->id;
	int index = rtd->cpu_dai->id;
	int port_id = msm_get_port_id(rtd->dai_link->id);
	struct snd_soc_card *card = rtd->card;
	struct snd_soc_card *card = rtd->card;
	struct msm_asoc_mach_data *pdata = snd_soc_card_get_drvdata(card);
	struct msm_asoc_mach_data *pdata = snd_soc_card_get_drvdata(card);
	struct msm_pinctrl_info *pinctrl_info = &pdata->pinctrl_info;
	int ret_pinctrl = 0;


	pr_debug("%s(): substream = %s  stream = %d\n", __func__,
	pr_debug("%s(): substream = %s  stream = %d\n", __func__,
		 substream->name, substream->stream);
		 substream->name, substream->stream);

	if (port_id < 0) {
		dev_err(rtd->card->dev, "%s: Invalid port_id\n", __func__);
		return;
	}

	if (index < PRIM_MI2S || index >= MI2S_MAX) {
	if (index < PRIM_MI2S || index >= MI2S_MAX) {
		pr_err("%s:invalid MI2S DAI(%d)\n", __func__, index);
		pr_err("%s:invalid MI2S DAI(%d)\n", __func__, index);
		return;
		return;
@@ -5849,16 +5736,24 @@ static void msm_mi2s_snd_shutdown(struct snd_pcm_substream *substream)


	mutex_lock(&mi2s_intf_conf[index].lock);
	mutex_lock(&mi2s_intf_conf[index].lock);
	if (--mi2s_intf_conf[index].ref_cnt == 0) {
	if (--mi2s_intf_conf[index].ref_cnt == 0) {
		if (pdata->mi2s_gpio_p[index])
			msm_cdc_pinctrl_select_sleep_state(
					pdata->mi2s_gpio_p[index]);

		ret = msm_mi2s_set_sclk(substream, false);
		ret = msm_mi2s_set_sclk(substream, false);
		if (ret < 0)
		if (ret < 0)
			pr_err("%s:clock disable failed for MI2S (%d); ret=%d\n",
			pr_err("%s:clock disable failed for MI2S (%d); ret=%d\n",
				__func__, index, ret);
				__func__, index, ret);
		if (index == QUAT_MI2S) {

			ret_pinctrl = msm_set_pinctrl(pinctrl_info,
		if (mi2s_intf_conf[index].msm_is_ext_mclk) {
						      STATE_DISABLE);
			pr_debug("%s: Disabling mclk, clk_freq_in_hz = %u\n",
			if (ret_pinctrl)
				 __func__, mi2s_mclk[index].clk_freq_in_hz);
				pr_err("%s: MI2S TLMM pinctrl set failed with %d\n",
			ret = afe_set_lpass_clock_v2(port_id,
					__func__, ret_pinctrl);
						     &mi2s_mclk[index]);
			if (ret < 0)
				pr_err("%s: mclk disable failed for MCLK (%d); ret=%d\n",
					__func__, index, ret);
			mi2s_mclk[index].enable = 0;
		}
		}
	}
	}
	mutex_unlock(&mi2s_intf_conf[index].lock);
	mutex_unlock(&mi2s_intf_conf[index].lock);
@@ -6793,7 +6688,7 @@ static struct snd_soc_dai_link msm_common_be_dai_links[] = {
		.no_pcm = 1,
		.no_pcm = 1,
		.dpcm_playback = 1,
		.dpcm_playback = 1,
		.id = MSM_BACKEND_DAI_QUAT_TDM_RX_0,
		.id = MSM_BACKEND_DAI_QUAT_TDM_RX_0,
		.be_hw_params_fixup = msm_tdm_be_hw_params_fixup,
		.be_hw_params_fixup = msm_be_hw_params_fixup,
		.ops = &sm6150_tdm_be_ops,
		.ops = &sm6150_tdm_be_ops,
		.ignore_suspend = 1,
		.ignore_suspend = 1,
		.ignore_pmdown_time = 1,
		.ignore_pmdown_time = 1,
@@ -6812,6 +6707,35 @@ static struct snd_soc_dai_link msm_common_be_dai_links[] = {
		.ops = &sm6150_tdm_be_ops,
		.ops = &sm6150_tdm_be_ops,
		.ignore_suspend = 1,
		.ignore_suspend = 1,
	},
	},
	{
		.name = LPASS_BE_QUIN_TDM_RX_0,
		.stream_name = "Quinary TDM0 Playback",
		.cpu_dai_name = "msm-dai-q6-tdm.36928",
		.platform_name = "msm-pcm-routing",
		.codec_name = "msm-stub-codec.1",
		.codec_dai_name = "msm-stub-rx",
		.no_pcm = 1,
		.dpcm_playback = 1,
		.id = MSM_BACKEND_DAI_QUIN_TDM_RX_0,
		.be_hw_params_fixup = msm_be_hw_params_fixup,
		.ops = &sm6150_tdm_be_ops,
		.ignore_suspend = 1,
		.ignore_pmdown_time = 1,
	},
	{
		.name = LPASS_BE_QUIN_TDM_TX_0,
		.stream_name = "Quinary TDM0 Capture",
		.cpu_dai_name = "msm-dai-q6-tdm.36929",
		.platform_name = "msm-pcm-routing",
		.codec_name = "msm-stub-codec.1",
		.codec_dai_name = "msm-stub-tx",
		.no_pcm = 1,
		.dpcm_capture = 1,
		.id = MSM_BACKEND_DAI_QUIN_TDM_TX_0,
		.be_hw_params_fixup = msm_be_hw_params_fixup,
		.ops = &sm6150_tdm_be_ops,
		.ignore_suspend = 1,
	},
};
};


static struct snd_soc_dai_link msm_tavil_be_dai_links[] = {
static struct snd_soc_dai_link msm_tavil_be_dai_links[] = {
@@ -8354,6 +8278,7 @@ static void msm_i2s_auxpcm_init(struct platform_device *pdev)
{
{
	int count;
	int count;
	u32 mi2s_master_slave[MI2S_MAX];
	u32 mi2s_master_slave[MI2S_MAX];
	u32 mi2s_ext_mclk[MI2S_MAX];
	int ret;
	int ret;


	for (count = 0; count < MI2S_MAX; count++) {
	for (count = 0; count < MI2S_MAX; count++) {
@@ -8373,6 +8298,18 @@ static void msm_i2s_auxpcm_init(struct platform_device *pdev)
				mi2s_master_slave[count];
				mi2s_master_slave[count];
		}
		}
	}
	}

	ret = of_property_read_u32_array(pdev->dev.of_node,
					 "qcom,msm-mi2s-ext-mclk",
					 mi2s_ext_mclk, MI2S_MAX);
	if (ret) {
		dev_dbg(&pdev->dev, "%s: no qcom,msm-mi2s-ext-mclk in DT node\n",
			__func__);
	} else {
		for (count = 0; count < MI2S_MAX; count++)
			mi2s_intf_conf[count].msm_is_ext_mclk =
				mi2s_ext_mclk[count];
	}
}
}


static void msm_i2s_auxpcm_deinit(void)
static void msm_i2s_auxpcm_deinit(void)
@@ -8383,6 +8320,7 @@ static void msm_i2s_auxpcm_deinit(void)
		mutex_destroy(&mi2s_intf_conf[count].lock);
		mutex_destroy(&mi2s_intf_conf[count].lock);
		mi2s_intf_conf[count].ref_cnt = 0;
		mi2s_intf_conf[count].ref_cnt = 0;
		mi2s_intf_conf[count].msm_is_mi2s_master = 0;
		mi2s_intf_conf[count].msm_is_mi2s_master = 0;
		mi2s_intf_conf[count].msm_is_ext_mclk = 0;
	}
	}
}
}


@@ -8581,6 +8519,7 @@ static int msm_asoc_machine_probe(struct platform_device *pdev)
			"qcom,mbhc-audio-jack-type",
			"qcom,mbhc-audio-jack-type",
			pdev->dev.of_node->full_name);
			pdev->dev.of_node->full_name);
		dev_dbg(&pdev->dev, "Jack type properties set to default\n");
		dev_dbg(&pdev->dev, "Jack type properties set to default\n");
		ret = 0;
	} else {
	} else {
		if (!strcmp(mbhc_audio_jack_type, "4-pole-jack")) {
		if (!strcmp(mbhc_audio_jack_type, "4-pole-jack")) {
			wcd_mbhc_cfg.enable_anc_mic_detect = false;
			wcd_mbhc_cfg.enable_anc_mic_detect = false;
@@ -8596,6 +8535,18 @@ static int msm_asoc_machine_probe(struct platform_device *pdev)
			dev_dbg(&pdev->dev, "Unknown value, set to default\n");
			dev_dbg(&pdev->dev, "Unknown value, set to default\n");
		}
		}
	}
	}

	pdata->mi2s_gpio_p[PRIM_MI2S] = of_parse_phandle(pdev->dev.of_node,
					"qcom,pri-mi2s-gpios", 0);
	pdata->mi2s_gpio_p[SEC_MI2S] = of_parse_phandle(pdev->dev.of_node,
					"qcom,sec-mi2s-gpios", 0);
	pdata->mi2s_gpio_p[TERT_MI2S] = of_parse_phandle(pdev->dev.of_node,
					"qcom,tert-mi2s-gpios", 0);
	pdata->mi2s_gpio_p[QUAT_MI2S] = of_parse_phandle(pdev->dev.of_node,
					"qcom,quat-mi2s-gpios", 0);
	pdata->mi2s_gpio_p[QUIN_MI2S] = of_parse_phandle(pdev->dev.of_node,
					"qcom,quin-mi2s-gpios", 0);

	/*
	/*
	 * Parse US-Euro gpio info from DT. Report no error if us-euro
	 * Parse US-Euro gpio info from DT. Report no error if us-euro
	 * entry is not found in DT file as some targets do not support
	 * entry is not found in DT file as some targets do not support
@@ -8623,16 +8574,6 @@ static int msm_asoc_machine_probe(struct platform_device *pdev)
				"fsa4480-i2c-handle",
				"fsa4480-i2c-handle",
				pdev->dev.of_node->full_name);
				pdev->dev.of_node->full_name);
	}
	}
	/* Parse pinctrl info from devicetree */
	ret = msm_get_pinctrl(pdev);
	if (!ret) {
		pr_debug("%s: pinctrl parsing successful\n", __func__);
	} else {
		dev_dbg(&pdev->dev,
			"%s: Parsing pinctrl failed with %d. Cannot use Ports\n",
			__func__, ret);
		ret = 0;
	}


	msm_i2s_auxpcm_init(pdev);
	msm_i2s_auxpcm_init(pdev);
	if (strcmp(card->name, "sm6150-tavil-snd-card")) {
	if (strcmp(card->name, "sm6150-tavil-snd-card")) {