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

Commit 407925be authored by Laxminath Kasam's avatar Laxminath Kasam
Browse files

ASoC: msm: Update the AFE clock API support



As 8909 uses afe clock version v1, update
the drivers to be backward compatible and
support v1 version.

Change-Id: I6f4a1d2e06d497d076912a5a176f3694b65de33f
Signed-off-by: default avatarLaxminath Kasam <lkasam@codeaurora.org>
parent 7d43b66b
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -1390,6 +1390,7 @@ the flavor.
- pinctrl-# : Pinctrl states as mentioned in pinctrl-names.

Optional properties:
- qcom,msm-afe-clk-ver: Provides detail of AFE clock API version.
- qcom,hdmi-dba-codec-rx: Boolean. specifies if HDMI DBA audio support is enabled or not.
- qcom,prim-auxpcm-gpio-clk  : GPIO on which Primary AUXPCM clk signal is coming.
- qcom,prim-auxpcm-gpio-sync : GPIO on which Primary AUXPCM SYNC signal is coming.
@@ -1453,6 +1454,7 @@ Example:
		reg-names = "csr_gp_io_mux_mic_ctl",
			    "csr_gp_io_mux_spkr_ctl",
			    "csr_gp_io_lpaif_pri_pcm_pri_mode_muxsel";
		qcom,msm-afe-clk-ver = <1>;
		qcom,msm-ext-pa = "primary";
		qcom,hdmi-dba-codec-rx;
		qcom,msm-mclk-freq = <9600000>;
+1 −1
Original line number Diff line number Diff line
@@ -218,6 +218,7 @@ struct msm8916_asoc_mach_data {
	int spk_ext_pa_gpio;
	int mclk_freq;
	int lb_mode;
	int afe_clk_ver;
	u8 micbias1_cap_mode;
	u8 micbias2_cap_mode;
	atomic_t mclk_rsc_ref;
@@ -228,7 +229,6 @@ struct msm8916_asoc_mach_data {
	struct delayed_work disable_mclk_work;
	struct afe_digital_clk_cfg digital_cdc_clk;
	struct afe_clk_set digital_cdc_core_clk;
	struct afe_clk_set digital_cdc_mclk;
	void __iomem *vaddr_gpio_mux_spkr_ctl;
	void __iomem *vaddr_gpio_mux_mic_ctl;
	void __iomem *vaddr_gpio_mux_quin_ctl;
+250 −324
Original line number Diff line number Diff line
/* Copyright (c) 2015, The Linux Foundation. All rights reserved.
/* Copyright (c) 2015-2016, The Linux Foundation. All rights reserved.
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 and
@@ -53,8 +53,6 @@ enum btsco_rates {
	RATE_16KHZ_ID,
};

static bool ext_codec;

static int msm8952_auxpcm_rate = 8000;
static int msm_btsco_rate = BTSCO_RATE_8KHZ;
static int msm_btsco_ch = 1;
@@ -99,6 +97,36 @@ static struct wcd_mbhc_config mbhc_cfg = {
	.linein_th = 5000,
};

static struct afe_clk_cfg mi2s_rx_clk_v1 = {
	AFE_API_VERSION_I2S_CONFIG,
	Q6AFE_LPASS_IBIT_CLK_1_P536_MHZ,
	Q6AFE_LPASS_OSR_CLK_12_P288_MHZ,
	Q6AFE_LPASS_CLK_SRC_INTERNAL,
	Q6AFE_LPASS_CLK_ROOT_DEFAULT,
	Q6AFE_LPASS_MODE_CLK1_VALID,
	0,
};

static struct afe_clk_cfg mi2s_tx_clk_v1 = {
	AFE_API_VERSION_I2S_CONFIG,
	Q6AFE_LPASS_IBIT_CLK_1_P536_MHZ,
	Q6AFE_LPASS_OSR_CLK_12_P288_MHZ,
	Q6AFE_LPASS_CLK_SRC_INTERNAL,
	Q6AFE_LPASS_CLK_ROOT_DEFAULT,
	Q6AFE_LPASS_MODE_CLK1_VALID,
	0,
};

static struct afe_clk_cfg wsa_ana_clk_v1 = {
	AFE_API_VERSION_I2S_CONFIG,
	0,
	Q6AFE_LPASS_OSR_CLK_9_P600_MHZ,
	Q6AFE_LPASS_CLK_SRC_INTERNAL,
	Q6AFE_LPASS_CLK_ROOT_DEFAULT,
	Q6AFE_LPASS_MODE_CLK2_VALID,
	0,
};

static struct afe_clk_set mi2s_tx_clk = {
	AFE_API_VERSION_I2S_CONFIG,
	Q6AFE_LPASS_CLK_ID_TER_MI2S_IBIT,
@@ -418,230 +446,147 @@ static int msm_mi2s_snd_hw_params(struct snd_pcm_substream *substream,
	return 0;
}

static int quat_mi2s_sclk_ctl(struct snd_pcm_substream *substream, bool enable)
{
	int ret = 0;

	if (enable) {
		if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
			mi2s_rx_clk.enable = enable;
			mi2s_rx_clk.clk_id =
				Q6AFE_LPASS_CLK_ID_QUAD_MI2S_IBIT;
			if (mi2s_rx_bit_format == SNDRV_PCM_FORMAT_S24_LE)
				mi2s_rx_clk.clk_freq_in_hz =
					Q6AFE_LPASS_IBIT_CLK_3_P072_MHZ;
			else
				mi2s_rx_clk.clk_freq_in_hz =
					Q6AFE_LPASS_IBIT_CLK_1_P536_MHZ;
			ret = afe_set_lpass_clock_v2(
					AFE_PORT_ID_QUATERNARY_MI2S_RX,
					&mi2s_rx_clk);
		} else if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) {
			mi2s_tx_clk.enable = enable;
			mi2s_tx_clk.clk_id =
				Q6AFE_LPASS_CLK_ID_QUAD_MI2S_IBIT;
			mi2s_tx_clk.clk_freq_in_hz =
					Q6AFE_LPASS_IBIT_CLK_1_P536_MHZ;
			ret = afe_set_lpass_clock_v2(
					AFE_PORT_ID_QUATERNARY_MI2S_TX,
					&mi2s_tx_clk);
		} else {
			pr_err("%s:Not valid substream.\n", __func__);
		}

		if (ret < 0)
			pr_err("%s:afe_set_lpass_clock_v2 failed\n", __func__);
	} else {
		if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
			mi2s_rx_clk.enable = enable;
			mi2s_rx_clk.clk_id =
				Q6AFE_LPASS_CLK_ID_QUAD_MI2S_IBIT;
			ret = afe_set_lpass_clock_v2(
					AFE_PORT_ID_QUATERNARY_MI2S_RX,
					&mi2s_rx_clk);
		} else if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) {
			mi2s_tx_clk.enable = enable;
			mi2s_tx_clk.clk_id =
				Q6AFE_LPASS_CLK_ID_QUAD_MI2S_IBIT;
			ret = afe_set_lpass_clock_v2(
					AFE_PORT_ID_QUATERNARY_MI2S_TX,
					&mi2s_tx_clk);
		} else {
			pr_err("%s:Not valid substream.\n", __func__);
		}

		if (ret < 0)
			pr_err("%s:afe_set_lpass_clock_v2 failed\n", __func__);
static int msm8952_get_clk_id(int port_id)
{
	switch (port_id) {
	case AFE_PORT_ID_PRIMARY_MI2S_RX:
		return Q6AFE_LPASS_CLK_ID_PRI_MI2S_IBIT;
	case AFE_PORT_ID_SECONDARY_MI2S_RX:
		return Q6AFE_LPASS_CLK_ID_SEC_MI2S_IBIT;
	case AFE_PORT_ID_TERTIARY_MI2S_TX:
		return Q6AFE_LPASS_CLK_ID_TER_MI2S_IBIT;
	case AFE_PORT_ID_QUATERNARY_MI2S_RX:
	case AFE_PORT_ID_QUATERNARY_MI2S_TX:
		return Q6AFE_LPASS_CLK_ID_QUAD_MI2S_IBIT;
	case AFE_PORT_ID_QUINARY_MI2S_RX:
	case AFE_PORT_ID_QUINARY_MI2S_TX:
		return Q6AFE_LPASS_CLK_ID_QUI_MI2S_IBIT;
	case AFE_PORT_ID_SENARY_MI2S_TX:
		return Q6AFE_LPASS_CLK_ID_SEN_MI2S_IBIT;
	default:
		pr_err("%s: invalid port_id: 0x%x\n", __func__, port_id);
		return -EINVAL;
	}
	return ret;
}

static int quin_mi2s_sclk_ctl(struct snd_pcm_substream *substream, bool enable)
static int msm8952_get_port_id(int be_id)
{
	int ret = 0;

	if (enable) {
		if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
			mi2s_rx_clk.enable = enable;
			mi2s_rx_clk.clk_id =
				Q6AFE_LPASS_CLK_ID_QUI_MI2S_IBIT;
			if (mi2s_rx_bit_format == SNDRV_PCM_FORMAT_S24_LE)
				mi2s_rx_clk.clk_freq_in_hz =
					Q6AFE_LPASS_IBIT_CLK_3_P072_MHZ;
			else
				mi2s_rx_clk.clk_freq_in_hz =
					Q6AFE_LPASS_IBIT_CLK_1_P536_MHZ;
			ret = afe_set_lpass_clock_v2(
					AFE_PORT_ID_QUINARY_MI2S_RX,
					&mi2s_rx_clk);
		} else if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) {
			mi2s_tx_clk.enable = enable;
			mi2s_tx_clk.clk_id =
				Q6AFE_LPASS_CLK_ID_QUI_MI2S_IBIT;
			mi2s_tx_clk.clk_freq_in_hz =
				Q6AFE_LPASS_IBIT_CLK_1_P536_MHZ;
			ret = afe_set_lpass_clock_v2(
					AFE_PORT_ID_QUINARY_MI2S_TX,
					&mi2s_tx_clk);
		} else {
			pr_err("%s:Not valid substream.\n", __func__);
		}

		if (ret < 0)
			pr_err("%s:afe_set_lpass_clock_v2 failed\n", __func__);

	} else {
		if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
			mi2s_rx_clk.enable = enable;
			mi2s_rx_clk.clk_id =
				Q6AFE_LPASS_CLK_ID_QUI_MI2S_IBIT;
			ret = afe_set_lpass_clock_v2(
					AFE_PORT_ID_QUINARY_MI2S_RX,
					&mi2s_rx_clk);
		} else if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) {
			mi2s_tx_clk.enable = enable;
			mi2s_tx_clk.clk_id =
				Q6AFE_LPASS_CLK_ID_QUI_MI2S_IBIT;
			ret = afe_set_lpass_clock_v2(
					AFE_PORT_ID_QUINARY_MI2S_TX,
					&mi2s_tx_clk);
		} else {
			pr_err("%s:Not valid substream.\n", __func__);
		}

		if (ret < 0)
			pr_err("%s:afe_set_lpass_clock_v2 failed\n", __func__);
	switch (be_id) {
	case MSM_BACKEND_DAI_PRI_MI2S_RX:
		return AFE_PORT_ID_PRIMARY_MI2S_RX;
	case MSM_BACKEND_DAI_SECONDARY_MI2S_RX:
		return AFE_PORT_ID_SECONDARY_MI2S_RX;
	case MSM_BACKEND_DAI_TERTIARY_MI2S_TX:
		return AFE_PORT_ID_TERTIARY_MI2S_TX;
	case MSM_BACKEND_DAI_QUATERNARY_MI2S_RX:
		return AFE_PORT_ID_QUATERNARY_MI2S_RX;
	case MSM_BACKEND_DAI_QUATERNARY_MI2S_TX:
		return AFE_PORT_ID_QUATERNARY_MI2S_TX;
	case MSM_BACKEND_DAI_QUINARY_MI2S_RX:
		return AFE_PORT_ID_QUINARY_MI2S_RX;
	case MSM_BACKEND_DAI_QUINARY_MI2S_TX:
		return AFE_PORT_ID_QUINARY_MI2S_TX;
	case MSM_BACKEND_DAI_SENARY_MI2S_TX:
		return AFE_PORT_ID_SENARY_MI2S_TX;
	default:
		pr_err("%s: Invalid be_id: %d\n", __func__, be_id);
		return -EINVAL;
	}
	return ret;
}

static int sec_mi2s_sclk_ctl(struct snd_pcm_substream *substream, bool enable)
static int msm_mi2s_sclk_ctl(struct snd_pcm_substream *substream, bool enable)
{
	int ret = 0;
	struct snd_soc_pcm_runtime *rtd = substream->private_data;
	struct snd_soc_card *card = rtd->card;
	struct msm8916_asoc_mach_data *pdata = snd_soc_card_get_drvdata(card);
	int port_id = 0;

	port_id = msm8952_get_port_id(rtd->dai_link->be_id);
	if (port_id < 0) {
		pr_err("%s: Invalid port_id\n", __func__);
		return -EINVAL;
	}
	if (enable) {
		if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
			mi2s_rx_clk.enable = enable;
			mi2s_rx_clk.clk_id =
				Q6AFE_LPASS_CLK_ID_SEC_MI2S_IBIT;
			if (mi2s_rx_bit_format == SNDRV_PCM_FORMAT_S24_LE)
				mi2s_rx_clk.clk_freq_in_hz =
			if (pdata->afe_clk_ver == AFE_CLK_VERSION_V1) {
				if (mi2s_rx_bit_format ==
						SNDRV_PCM_FORMAT_S24_LE)
					mi2s_rx_clk_v1.clk_val1 =
						Q6AFE_LPASS_IBIT_CLK_3_P072_MHZ;
				else
				mi2s_rx_clk.clk_freq_in_hz =
					mi2s_rx_clk_v1.clk_val1 =
						Q6AFE_LPASS_IBIT_CLK_1_P536_MHZ;
			ret = afe_set_lpass_clock_v2(
				AFE_PORT_ID_SECONDARY_MI2S_RX,
						  &mi2s_rx_clk);
		} else
			pr_err("%s:Not valid substream.\n", __func__);

		if (ret < 0)
			pr_err("%s:afe_set_lpass_clock_v2 failed\n", __func__);

				ret = afe_set_lpass_clock(port_id,
							&mi2s_rx_clk_v1);
			} else {
		if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
				mi2s_rx_clk.enable = enable;
				mi2s_rx_clk.clk_id =
				Q6AFE_LPASS_CLK_ID_SEC_MI2S_IBIT;
			ret = afe_set_lpass_clock_v2(
				AFE_PORT_ID_SECONDARY_MI2S_RX,
				&mi2s_rx_clk);
		} else
			pr_err("%s:Not valid substream.\n", __func__);

		if (ret < 0)
			pr_err("%s:afe_set_lpass_clock_v2 failed\n", __func__);
	}
	return ret;
}

static int mi2s_clk_ctl(struct snd_pcm_substream *substream, bool enable)
{
	int ret = 0;
	struct snd_soc_pcm_runtime *rtd = substream->private_data;
	int port_id = 0;

	switch (rtd->dai_link->be_id) {
	case MSM_BACKEND_DAI_SENARY_MI2S_TX:
		port_id = AFE_PORT_ID_SENARY_MI2S_TX;
		break;
	case MSM_BACKEND_DAI_TERTIARY_MI2S_TX:
	default:
		port_id = AFE_PORT_ID_TERTIARY_MI2S_TX;
		break;
	}

	if (enable) {
		if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
			mi2s_rx_clk.enable = enable;
			mi2s_rx_clk.clk_id =
				Q6AFE_LPASS_CLK_ID_PRI_MI2S_IBIT;
			if (mi2s_rx_bit_format == SNDRV_PCM_FORMAT_S24_LE)
						msm8952_get_clk_id(port_id);
				if (mi2s_rx_bit_format ==
						SNDRV_PCM_FORMAT_S24_LE)
					mi2s_rx_clk.clk_freq_in_hz =
						Q6AFE_LPASS_IBIT_CLK_3_P072_MHZ;
				else
					mi2s_rx_clk.clk_freq_in_hz =
						Q6AFE_LPASS_IBIT_CLK_1_P536_MHZ;
			ret = afe_set_lpass_clock_v2(
				AFE_PORT_ID_PRIMARY_MI2S_RX,
				ret = afe_set_lpass_clock_v2(port_id,
							&mi2s_rx_clk);
			}
		} else if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) {
			if (pdata->afe_clk_ver == AFE_CLK_VERSION_V1) {
				mi2s_tx_clk_v1.clk_val1 =
						Q6AFE_LPASS_IBIT_CLK_1_P536_MHZ;
				ret = afe_set_lpass_clock(port_id,
							&mi2s_tx_clk_v1);
			} else {
				mi2s_tx_clk.enable = enable;
				mi2s_tx_clk.clk_id =
				Q6AFE_LPASS_CLK_ID_TER_MI2S_IBIT;
						msm8952_get_clk_id(port_id);
				mi2s_tx_clk.clk_freq_in_hz =
						Q6AFE_LPASS_IBIT_CLK_1_P536_MHZ;
			ret = afe_set_lpass_clock_v2(
				AFE_PORT_ID_TERTIARY_MI2S_TX,
				ret = afe_set_lpass_clock_v2(port_id,
							&mi2s_tx_clk);
		} else
			}
		} else {
			pr_err("%s:Not valid substream.\n", __func__);
		}

		if (ret < 0)
			pr_err("%s:afe_set_lpass_clock_v2 failed\n", __func__);

	} else {
		if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
			if (pdata->afe_clk_ver == AFE_CLK_VERSION_V1) {
				mi2s_rx_clk_v1.clk_val1 =
						Q6AFE_LPASS_IBIT_CLK_DISABLE;
				ret = afe_set_lpass_clock(port_id,
							&mi2s_rx_clk_v1);
			} else {
				mi2s_rx_clk.enable = enable;
				mi2s_rx_clk.clk_id =
				Q6AFE_LPASS_CLK_ID_PRI_MI2S_IBIT;
			ret = afe_set_lpass_clock_v2(
				AFE_PORT_ID_PRIMARY_MI2S_RX,
						msm8952_get_clk_id(port_id);
				ret = afe_set_lpass_clock_v2(port_id,
							&mi2s_rx_clk);
			}
		} else if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) {
			if (pdata->afe_clk_ver == AFE_CLK_VERSION_V1) {
				mi2s_tx_clk_v1.clk_val1 =
						Q6AFE_LPASS_IBIT_CLK_DISABLE;
				ret = afe_set_lpass_clock(port_id,
							&mi2s_tx_clk_v1);
			} else {
				mi2s_tx_clk.enable = enable;
				mi2s_tx_clk.clk_id =
				Q6AFE_LPASS_CLK_ID_TER_MI2S_IBIT;
			ret = afe_set_lpass_clock_v2(
				AFE_PORT_ID_TERTIARY_MI2S_TX,
						msm8952_get_clk_id(port_id);
				ret = afe_set_lpass_clock_v2(port_id,
							&mi2s_tx_clk);
		} else
			}
		} else {
			pr_err("%s:Not valid substream.\n", __func__);
		}

		if (ret < 0)
			pr_err("%s:afe_set_lpass_clock_v2 failed\n", __func__);

	}
	return ret;
}
@@ -662,17 +607,25 @@ static int msm8952_enable_dig_cdc_clk(struct snd_soc_codec *codec,
					&pdata->disable_mclk_work);
			mutex_lock(&pdata->cdc_mclk_mutex);
			if (atomic_read(&pdata->mclk_enabled) == false) {
				if (pdata->afe_clk_ver == AFE_CLK_VERSION_V1) {
					pdata->digital_cdc_clk.clk_val =
							pdata->mclk_freq;
					ret = afe_set_digital_codec_core_clock(
						AFE_PORT_ID_PRIMARY_MI2S_RX,
						&pdata->digital_cdc_clk);
				} else {
					pdata->digital_cdc_core_clk.enable = 1;
					ret = afe_set_lpass_clock_v2(
						AFE_PORT_ID_PRIMARY_MI2S_RX,
						&pdata->digital_cdc_core_clk);
				}
				if (ret < 0) {
					pr_err("%s: failed to enable CCLK\n",
							__func__);
					mutex_unlock(&pdata->cdc_mclk_mutex);
					return ret;
				}
				pr_err("enable CCLK done\n");
				pr_debug("enabled digital codec core clk\n");
				atomic_set(&pdata->mclk_enabled, true);
			}
			mutex_unlock(&pdata->cdc_mclk_mutex);
@@ -682,10 +635,17 @@ static int msm8952_enable_dig_cdc_clk(struct snd_soc_codec *codec,
		cancel_delayed_work_sync(&pdata->disable_mclk_work);
		mutex_lock(&pdata->cdc_mclk_mutex);
		if (atomic_read(&pdata->mclk_enabled) == true) {
			if (pdata->afe_clk_ver == AFE_CLK_VERSION_V1) {
				pdata->digital_cdc_clk.clk_val = 0;
				ret = afe_set_digital_codec_core_clock(
					AFE_PORT_ID_PRIMARY_MI2S_RX,
					&pdata->digital_cdc_clk);
			} else {
				pdata->digital_cdc_core_clk.enable = 0;
				ret = afe_set_lpass_clock_v2(
					AFE_PORT_ID_PRIMARY_MI2S_RX,
					&pdata->digital_cdc_core_clk);
			}
			if (ret < 0)
				pr_err("%s: failed to disable CCLK\n",
						__func__);
@@ -789,14 +749,18 @@ static int loopback_mclk_put(struct snd_kcontrol *kcontrol,
		mutex_lock(&pdata->cdc_mclk_mutex);
		if ((!atomic_read(&pdata->mclk_rsc_ref)) &&
				(!atomic_read(&pdata->mclk_enabled))) {
			if (pdata->afe_clk_ver == AFE_CLK_VERSION_V1) {
				pdata->digital_cdc_clk.clk_val =
						pdata->mclk_freq;
				ret = afe_set_digital_codec_core_clock(
					AFE_PORT_ID_PRIMARY_MI2S_RX,
					&pdata->digital_cdc_clk);
			} else {
				pdata->digital_cdc_core_clk.enable = 1;
			pdata->digital_cdc_mclk.enable = 1;
				ret = afe_set_lpass_clock_v2(
					AFE_PORT_ID_PRIMARY_MI2S_RX,
					&pdata->digital_cdc_core_clk);
			ret |= afe_set_lpass_clock_v2(
				AFE_PORT_ID_PRIMARY_MI2S_RX,
				&pdata->digital_cdc_mclk);
			}
			if (ret < 0) {
				pr_err("%s: failed to enable the MCLK: %d\n",
						__func__, ret);
@@ -821,10 +785,17 @@ static int loopback_mclk_put(struct snd_kcontrol *kcontrol,
		mutex_lock(&pdata->cdc_mclk_mutex);
		if ((!atomic_dec_return(&pdata->mclk_rsc_ref)) &&
				(atomic_read(&pdata->mclk_enabled))) {
			if (pdata->afe_clk_ver == AFE_CLK_VERSION_V1) {
				pdata->digital_cdc_clk.clk_val = 0;
				ret = afe_set_digital_codec_core_clock(
					AFE_PORT_ID_PRIMARY_MI2S_RX,
					&pdata->digital_cdc_clk);
			} else {
				pdata->digital_cdc_core_clk.enable = 0;
				ret = afe_set_lpass_clock_v2(
					AFE_PORT_ID_PRIMARY_MI2S_RX,
					&pdata->digital_cdc_core_clk);
			}
			if (ret < 0) {
				pr_err("%s: failed to disable the CCLK: %d\n",
						__func__, ret);
@@ -1018,10 +989,18 @@ static int msm8952_enable_wsa_mclk(struct snd_soc_card *card, bool enable)
	mutex_lock(&pdata->wsa_mclk_mutex);
	if (enable) {
		if (!atomic_read(&pdata->wsa_mclk_rsc_ref)) {
			if (pdata->afe_clk_ver == AFE_CLK_VERSION_V1) {
				wsa_ana_clk_v1.clk_val1 =
						Q6AFE_LPASS_OSR_CLK_9_P600_MHZ;
				ret = afe_set_lpass_clock(
						AFE_PORT_ID_PRIMARY_MI2S_RX,
						&wsa_ana_clk_v1);
			} else {
				wsa_ana_clk.enable = enable;
				ret = afe_set_lpass_clock_v2(
						AFE_PORT_ID_PRIMARY_MI2S_RX,
						&wsa_ana_clk);
			}
			if (ret < 0) {
				pr_err("%s: failed to enable mclk %d\n",
					__func__, ret);
@@ -1033,10 +1012,18 @@ static int msm8952_enable_wsa_mclk(struct snd_soc_card *card, bool enable)
		if (!atomic_read(&pdata->wsa_mclk_rsc_ref))
			goto done;
		if (!atomic_dec_return(&pdata->wsa_mclk_rsc_ref)) {
			if (pdata->afe_clk_ver == AFE_CLK_VERSION_V1) {
				wsa_ana_clk_v1.clk_val1 =
						Q6AFE_LPASS_OSR_CLK_DISABLE;
				ret = afe_set_lpass_clock(
						AFE_PORT_ID_PRIMARY_MI2S_RX,
						&wsa_ana_clk_v1);
			} else {
				wsa_ana_clk.enable = enable;
				ret = afe_set_lpass_clock_v2(
						AFE_PORT_ID_PRIMARY_MI2S_RX,
						&wsa_ana_clk);
			}
			if (ret < 0) {
				pr_err("%s: failed to disable mclk %d\n",
					__func__, ret);
@@ -1078,7 +1065,7 @@ static int msm_mi2s_snd_startup(struct snd_pcm_substream *substream)
		iowrite32(val, pdata->vaddr_gpio_mux_mic_ctl);
	}

	ret = mi2s_clk_ctl(substream, true);
	ret = msm_mi2s_sclk_ctl(substream, true);
	if (ret < 0) {
		pr_err("%s: failed to enable sclk %d\n",
				__func__, ret);
@@ -1122,7 +1109,7 @@ static void msm_mi2s_snd_shutdown(struct snd_pcm_substream *substream)
	pr_debug("%s(): substream = %s  stream = %d\n", __func__,
			substream->name, substream->stream);

	ret = mi2s_clk_ctl(substream, false);
	ret = msm_mi2s_sclk_ctl(substream, false);
	if (ret < 0)
		pr_err("%s:clock disable failed; ret=%d\n", __func__,
				ret);
@@ -1224,7 +1211,7 @@ static int msm_sec_mi2s_snd_startup(struct snd_pcm_substream *substream)
			val = val | 0x0004835c;
			iowrite32(val, pdata->vaddr_gpio_mux_spkr_ctl);
		}
		ret = sec_mi2s_sclk_ctl(substream, true);
		ret = msm_mi2s_sclk_ctl(substream, true);
		if (ret < 0) {
			pr_err("failed to enable sclk\n");
			return ret;
@@ -1252,7 +1239,7 @@ static int msm_sec_mi2s_snd_startup(struct snd_pcm_substream *substream)
	}
	return ret;
err:
	ret = sec_mi2s_sclk_ctl(substream, false);
	ret = msm_mi2s_sclk_ctl(substream, false);
	if (ret < 0)
		pr_err("failed to disable sclk\n");
	return ret;
@@ -1274,7 +1261,7 @@ static void msm_sec_mi2s_snd_shutdown(struct snd_pcm_substream *substream)
					__func__, "sec_i2s");
			return;
		}
		ret = sec_mi2s_sclk_ctl(substream, false);
		ret = msm_mi2s_sclk_ctl(substream, false);
		if (ret < 0)
			pr_err("%s:clock disable failed\n", __func__);
	}
@@ -1297,7 +1284,7 @@ static int msm_quat_mi2s_snd_startup(struct snd_pcm_substream *substream)
			val = val | 0x02020002;
			iowrite32(val, pdata->vaddr_gpio_mux_mic_ctl);
		}
		ret = quat_mi2s_sclk_ctl(substream, true);
		ret = msm_mi2s_sclk_ctl(substream, true);
		if (ret < 0) {
			pr_err("failed to enable sclk\n");
			return ret;
@@ -1317,7 +1304,7 @@ static int msm_quat_mi2s_snd_startup(struct snd_pcm_substream *substream)
	}
	return ret;
err:
	ret = quat_mi2s_sclk_ctl(substream, false);
	ret = msm_mi2s_sclk_ctl(substream, false);
	if (ret < 0)
		pr_err("failed to disable sclk\n");
	return ret;
@@ -1333,7 +1320,7 @@ static void msm_quat_mi2s_snd_shutdown(struct snd_pcm_substream *substream)
	pr_debug("%s(): substream = %s  stream = %d\n", __func__,
				substream->name, substream->stream);
	if ((pdata->ext_pa & QUAT_MI2S_ID) == QUAT_MI2S_ID) {
		ret = quat_mi2s_sclk_ctl(substream, false);
		ret = msm_mi2s_sclk_ctl(substream, false);
		if (ret < 0)
			pr_err("%s:clock disable failed\n", __func__);
		if (atomic_read(&quat_mi2s_clk_ref) > 0)
@@ -1365,7 +1352,7 @@ static int msm_quin_mi2s_snd_startup(struct snd_pcm_substream *substream)
	} else {
		return -EINVAL;
	}
	ret = quin_mi2s_sclk_ctl(substream, true);
	ret = msm_mi2s_sclk_ctl(substream, true);
	if (ret < 0) {
		pr_err("failed to enable sclk\n");
		return ret;
@@ -1382,7 +1369,7 @@ static int msm_quin_mi2s_snd_startup(struct snd_pcm_substream *substream)
	}
	return ret;
err:
	ret = quin_mi2s_sclk_ctl(substream, false);
	ret = msm_mi2s_sclk_ctl(substream, false);
	if (ret < 0)
		pr_err("failed to disable sclk\n");
	return ret;
@@ -1398,7 +1385,7 @@ static void msm_quin_mi2s_snd_shutdown(struct snd_pcm_substream *substream)
	pr_debug("%s(): substream = %s  stream = %d\n", __func__,
				substream->name, substream->stream);
	if ((pdata->ext_pa & QUIN_MI2S_ID) == QUIN_MI2S_ID) {
		ret = quin_mi2s_sclk_ctl(substream, false);
		ret = msm_mi2s_sclk_ctl(substream, false);
		if (ret < 0)
			pr_err("%s:clock disable failed\n", __func__);
		if (atomic_read(&quin_mi2s_clk_ref) > 0)
@@ -2488,10 +2475,18 @@ void msm8952_disable_mclk(struct work_struct *work)
	if (atomic_read(&pdata->mclk_enabled) == true
			&& atomic_read(&pdata->mclk_rsc_ref) == 0) {
		pr_debug("Disable the mclk\n");
		if (pdata->afe_clk_ver == AFE_CLK_VERSION_V1) {
			pdata->digital_cdc_clk.clk_val = 0;
			ret = afe_set_digital_codec_core_clock(
				AFE_PORT_ID_PRIMARY_MI2S_RX,
				&pdata->digital_cdc_clk);

		} else {
			pdata->digital_cdc_core_clk.enable = 0;
			ret = afe_set_lpass_clock_v2(
				AFE_PORT_ID_PRIMARY_MI2S_RX,
				&pdata->digital_cdc_core_clk);
		}
		if (ret < 0)
			pr_err("%s failed to disable the CCLK\n", __func__);
		atomic_set(&pdata->mclk_enabled, false);
@@ -2746,15 +2741,10 @@ static int msm8952_asoc_machine_probe(struct platform_device *pdev)
	const char *wsa_str = NULL;
	const char *wsa_prefix_str = NULL;
	int num_strings;
	int ret, id, i;
	int ret, id, i, val;
	struct resource	*muxsel;
	char *temp_str = NULL;

	if (ext_codec == true) {
		pr_err("%s: ext codec setprop is true\n", __func__);
		return -EINVAL;
	}

	pdata = devm_kzalloc(&pdev->dev,
			sizeof(struct msm8916_asoc_mach_data), GFP_KERNEL);
	if (!pdata)
@@ -2793,15 +2783,15 @@ static int msm8952_asoc_machine_probe(struct platform_device *pdev)
	}

	muxsel = platform_get_resource_byname(pdev, IORESOURCE_MEM,
			"csr_gp_io_mux_quin_ctl");
			"csr_gp_io_lpaif_pri_pcm_pri_mode_muxsel");
	if (!muxsel) {
		dev_err(&pdev->dev, "MUX addr invalid for MI2S\n");
		ret = -ENODEV;
		goto err;
	}
	pdata->vaddr_gpio_mux_quin_ctl =
	pdata->vaddr_gpio_mux_pcm_ctl =
		ioremap(muxsel->start, resource_size(muxsel));
	if (pdata->vaddr_gpio_mux_quin_ctl == NULL) {
	if (pdata->vaddr_gpio_mux_pcm_ctl == NULL) {
		pr_err("%s ioremap failure for muxsel virt addr\n",
				__func__);
		ret = -ENOMEM;
@@ -2809,21 +2799,20 @@ static int msm8952_asoc_machine_probe(struct platform_device *pdev)
	}

	muxsel = platform_get_resource_byname(pdev, IORESOURCE_MEM,
			"csr_gp_io_lpaif_pri_pcm_pri_mode_muxsel");
			"csr_gp_io_mux_quin_ctl");
	if (!muxsel) {
		dev_err(&pdev->dev, "MUX addr invalid for MI2S\n");
		ret = -ENODEV;
		goto err;
		dev_dbg(&pdev->dev, "MUX addr invalid for MI2S\n");
		goto parse_mclk_freq;
	}
	pdata->vaddr_gpio_mux_pcm_ctl =
	pdata->vaddr_gpio_mux_quin_ctl =
		ioremap(muxsel->start, resource_size(muxsel));
	if (pdata->vaddr_gpio_mux_pcm_ctl == NULL) {
	if (pdata->vaddr_gpio_mux_quin_ctl == NULL) {
		pr_err("%s ioremap failure for muxsel virt addr\n",
				__func__);
		ret = -ENOMEM;
		goto err;
	}

parse_mclk_freq:
	ret = of_property_read_u32(pdev->dev.of_node, mclk, &id);
	if (ret) {
		dev_err(&pdev->dev,
@@ -2965,6 +2954,18 @@ static int msm8952_asoc_machine_probe(struct platform_device *pdev)
		mbhc_cfg.hs_ext_micbias = false;
	}

	ret = of_property_read_u32(pdev->dev.of_node,
				  "qcom,msm-afe-clk-ver", &val);
	if (ret)
		pdata->afe_clk_ver = AFE_CLK_VERSION_V2;
	else
		pdata->afe_clk_ver = val;
	/* initialize the mclk */
	pdata->digital_cdc_clk.i2s_cfg_minor_version =
					AFE_API_VERSION_I2S_CONFIG;
	pdata->digital_cdc_clk.clk_val = pdata->mclk_freq;
	pdata->digital_cdc_clk.clk_root = 5;
	pdata->digital_cdc_clk.reserved = 0;
	/* initialize the digital codec core clk */
	pdata->digital_cdc_core_clk.clk_set_minor_version =
			AFE_API_VERSION_I2S_CONFIG;
@@ -3096,81 +3097,6 @@ static void __exit msm8952_machine_exit(void)
}
module_exit(msm8952_machine_exit);

static ssize_t codec_detect_store(struct kobject *kobj,
		struct kobj_attribute *attr, const char *buf,
		size_t count)
{
	int boot = 0;

	if (sscanf(buf, "%du", &boot) == 1) {
		if (boot == 1)
			ext_codec = true;
	}
	return count;
}

static struct kobj_attribute codec_detect_attribute =
	__ATTR(boot, 0220, NULL, codec_detect_store);

static struct attribute *attrs[] = {
	&codec_detect_attribute.attr,
	NULL,
};

static int codec_detector_init_sysfs(void)
{
	int ret = -EINVAL;
	struct kobject *boot_cdc_det = NULL;
	struct attribute_group *attr_group;

	attr_group = kzalloc(sizeof(*(attr_group)),
				GFP_KERNEL);
	if (!attr_group) {
		ret = -ENOMEM;
		goto error_return;
	}

	attr_group->attrs = attrs;

	boot_cdc_det = kobject_create_and_add("codec_type", kernel_kobj);
	if (!boot_cdc_det) {
		pr_err("%s: sysfs create and add failed\n",
						__func__);
		ret = -ENOMEM;
		goto error_return;
	}

	ret = sysfs_create_group(boot_cdc_det, attr_group);
	if (ret) {
		pr_err("%s: sysfs create group failed %d\n",
							__func__, ret);
		goto error_return;
	}

	return 0;

error_return:
	kfree(attr_group);
	if (boot_cdc_det) {
		kobject_del(boot_cdc_det);
		boot_cdc_det = NULL;
	}

	return ret;
}

static int __init codec_detector_init(void)
{
	int ret = codec_detector_init_sysfs();

	if (ret != 0) {
		pr_err("%s: Error in initing sysfs\n", __func__);
		return ret;
	}
	return 0;
}
module_init(codec_detector_init);

MODULE_DESCRIPTION("ALSA SoC msm");
MODULE_LICENSE("GPL v2");
MODULE_ALIAS("platform:" DRV_NAME);