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

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

Merge "ASoC: msm: qdsp6v2: add support for source tracking feature"

parents c68cd390 b64d53d9
Loading
Loading
Loading
Loading
+83 −24
Original line number Diff line number Diff line
@@ -57,6 +57,8 @@ struct audio_ext_ap_clk2 {
struct audio_ext_lpass_mclk {
	struct pinctrl_info pnctrl_info;
	struct clk c;
	u32 lpass_clock;
	void __iomem *lpass_csr_gpio_mux_spkrctl_vaddr;
};

static struct afe_clk_set clk2_config = {
@@ -87,6 +89,15 @@ static struct afe_clk_set lpass_default2 = {
	0,
};

static struct afe_clk_set digital_cdc_core_clk = {
	Q6AFE_LPASS_CLK_CONFIG_API_VERSION,
	Q6AFE_LPASS_CLK_ID_INTERNAL_DIGITAL_CODEC_CORE,
	Q6AFE_LPASS_OSR_CLK_9_P600_MHZ,
	Q6AFE_LPASS_CLK_ATTRIBUTE_COUPLE_NO,
	Q6AFE_LPASS_CLK_ROOT_DEFAULT,
	0,
};

static inline struct audio_ext_ap_clk *to_audio_ap_clk(struct clk *clk)
{
	return container_of(clk, struct audio_ext_ap_clk, c);
@@ -163,7 +174,7 @@ static int audio_ext_lpass_mclk_prepare(struct clk *clk)
	struct audio_ext_lpass_mclk *audio_lpass_mclk;
	struct pinctrl_info *pnctrl_info;
	struct afe_clk_cfg *lpass_clk = NULL;
	int ret;
	int ret, val = 0;

	audio_lpass_mclk = container_of(clk, struct audio_ext_lpass_mclk, c);
	pnctrl_info = &audio_lpass_mclk->pnctrl_info;
@@ -179,21 +190,41 @@ static int audio_ext_lpass_mclk_prepare(struct clk *clk)
			pr_err("%s: active state select failed with %d\n",
				__func__, ret);
			ret = -EIO;
			goto err;
			goto done;
		}
	}

	if (!audio_lpass_mclk->lpass_clock) {
		memcpy(lpass_clk, &lpass_default, sizeof(struct afe_clk_cfg));
		lpass_clk->clk_val2 = Q6AFE_LPASS_OSR_CLK_12_P288_MHZ;
		lpass_clk->clk_set_mode = Q6AFE_LPASS_MODE_CLK2_VALID;
	ret = afe_set_lpass_clock(AFE_PORT_ID_SECONDARY_MI2S_RX, lpass_clk);
		ret = afe_set_lpass_clock(AFE_PORT_ID_SECONDARY_MI2S_RX,
				lpass_clk);
		if (ret < 0) {
			pr_err("%s afe_set_lpass_clock failed, ret = %d\n",
					__func__, ret);
			kfree(lpass_clk);
			return -EINVAL;
		}
err:
	} else {
		if (audio_lpass_mclk->lpass_csr_gpio_mux_spkrctl_vaddr) {
			val = ioread32(audio_lpass_mclk->
					lpass_csr_gpio_mux_spkrctl_vaddr);
			val = val | 0x00000002;
			iowrite32(val, audio_lpass_mclk->
					lpass_csr_gpio_mux_spkrctl_vaddr);
		}

		digital_cdc_core_clk.enable = 1;
		ret = afe_set_lpass_clock_v2(AFE_PORT_ID_PRIMARY_MI2S_RX,
				&digital_cdc_core_clk);
		if (ret < 0) {
			pr_err("%s afe_set_digital_codec_core_clock failed\n",
					__func__);
			kfree(lpass_clk);
			return ret;
		}
	}
done:
	kfree(lpass_clk);
	return 0;
}
@@ -214,7 +245,7 @@ static void audio_ext_lpass_mclk_unprepare(struct clk *clk)

	if (pnctrl_info->pinctrl) {
		ret = pinctrl_select_state(pnctrl_info->pinctrl,
					   pnctrl_info->active);
					   pnctrl_info->sleep);
		if (ret) {
			pr_err("%s: active state select failed with %d\n",
				__func__, ret);
@@ -222,14 +253,24 @@ static void audio_ext_lpass_mclk_unprepare(struct clk *clk)
			goto err;
		}
	}

	if (!audio_lpass_mclk->lpass_clock) {
		memcpy(lpass_clk, &lpass_default, sizeof(struct afe_clk_cfg));
		lpass_clk->clk_val2 = 0;
		lpass_clk->clk_set_mode = Q6AFE_LPASS_MODE_CLK2_VALID;
	ret = afe_set_lpass_clock(AFE_PORT_ID_SECONDARY_MI2S_RX, lpass_clk);
		ret = afe_set_lpass_clock(AFE_PORT_ID_SECONDARY_MI2S_RX,
				lpass_clk);
		if (ret < 0)
			pr_err("%s: afe_set_lpass_clock failed, ret = %d\n",
				__func__, ret);

	} else {
		digital_cdc_core_clk.enable = 0;
		ret = afe_set_lpass_clock_v2(AFE_PORT_ID_PRIMARY_MI2S_RX,
				&digital_cdc_core_clk);
		if (ret < 0)
			pr_err("%s: afe_set_digital_codec_core_clock failed, ret = %d\n",
					__func__, ret);
	}
err:
	kfree(lpass_clk);
}
@@ -437,11 +478,26 @@ static int audio_ref_clk_probe(struct platform_device *pdev)
	u32 mclk_freq;
	const char *mclk_id = "qcom,lpass-mclk-id";
	const char *mclk_str = NULL;
	u32 lpass_csr_gpio_mux_spkrctl_reg = 0;

	ret = of_property_read_u32(pdev->dev.of_node,
			"qcom,lpass-clock",
			&audio_lpass_mclk.lpass_clock);
	if (ret)
		dev_dbg(&pdev->dev, "%s: qcom,lpass-clock is undefined\n",
				__func__);

	ret = of_property_read_u32(pdev->dev.of_node,
			"qcom,codec-mclk-clk-freq",
			&mclk_freq);
	if (!ret && mclk_freq == 12288000) {
	if (!ret && (mclk_freq == 12288000 || audio_lpass_mclk.lpass_clock)) {
		ret = of_property_read_u32(pdev->dev.of_node, "reg",
				&lpass_csr_gpio_mux_spkrctl_reg);
		if (!ret) {
			audio_lpass_mclk.lpass_csr_gpio_mux_spkrctl_vaddr =
				ioremap(lpass_csr_gpio_mux_spkrctl_reg, 4);
		}

		ret = audio_get_pinctrl(pdev, LPASS_MCLK);
		if (ret)
			dev_err(&pdev->dev, "%s: Parsing pinctrl %s failed\n",
@@ -548,6 +604,9 @@ static int audio_ref_clk_remove(struct platform_device *pdev)
		pnctrl_info->pinctrl = NULL;
	}

	if (audio_lpass_mclk.lpass_csr_gpio_mux_spkrctl_vaddr)
		iounmap(audio_lpass_mclk.lpass_csr_gpio_mux_spkrctl_vaddr);

	return 0;
}

+112 −48
Original line number Diff line number Diff line
@@ -164,23 +164,21 @@ static void *def_tasha_mbhc_cal(void)
	return tasha_wcd_cal;
}

static struct afe_clk_cfg mi2s_rx_clk = {
static struct afe_clk_set mi2s_tx_clk = {
	AFE_API_VERSION_I2S_CONFIG,
	Q6AFE_LPASS_CLK_ID_QUAD_MI2S_IBIT,
	Q6AFE_LPASS_IBIT_CLK_1_P536_MHZ,
	Q6AFE_LPASS_OSR_CLK_12_P288_MHZ,
	Q6AFE_LPASS_CLK_SRC_INTERNAL,
	Q6AFE_LPASS_CLK_ATTRIBUTE_COUPLE_NO,
	Q6AFE_LPASS_CLK_ROOT_DEFAULT,
	Q6AFE_LPASS_MODE_CLK1_VALID,
	0,
};

static struct afe_clk_cfg mi2s_tx_clk = {
static struct afe_clk_set mi2s_rx_clk = {
	AFE_API_VERSION_I2S_CONFIG,
	Q6AFE_LPASS_CLK_ID_PRI_MI2S_IBIT,
	Q6AFE_LPASS_IBIT_CLK_1_P536_MHZ,
	Q6AFE_LPASS_OSR_CLK_12_P288_MHZ,
	Q6AFE_LPASS_CLK_SRC_INTERNAL,
	Q6AFE_LPASS_CLK_ATTRIBUTE_COUPLE_NO,
	Q6AFE_LPASS_CLK_ROOT_DEFAULT,
	Q6AFE_LPASS_MODE_CLK1_VALID,
	0,
};

@@ -541,20 +539,88 @@ static int msm_mi2s_snd_hw_params(struct snd_pcm_substream *substream,
	return 0;
}

static int ext_mi2s_clk_ctl(struct snd_pcm_substream *substream, bool enable,
							u16 port_id)
static int apq8009_get_port_id(int be_id)
{
	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;
	}
}

static int apq8009_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;
	}
}

static uint32_t get_mi2s_rx_clk_val(void)
{
	uint32_t clk_val;

	clk_val = pri_rx_sample_rate * bits_per_sample * 2;

	return clk_val;
}

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

	port_id = apq8009_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) {
			clk_val = pri_rx_sample_rate * bits_per_sample * 2;
			mi2s_rx_clk.clk_val1 = clk_val;
			ret = afe_set_lpass_clock(port_id, &mi2s_rx_clk);
			mi2s_rx_clk.enable = enable;
			mi2s_rx_clk.clk_id = apq8009_get_clk_id(port_id);
			mi2s_rx_clk.clk_freq_in_hz =
				get_mi2s_rx_clk_val();
			ret = afe_set_lpass_clock_v2(port_id, &mi2s_rx_clk);
		} else if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) {
			mi2s_tx_clk.clk_val1 = Q6AFE_LPASS_IBIT_CLK_1_P536_MHZ;
			ret = afe_set_lpass_clock(port_id, &mi2s_tx_clk);
			mi2s_tx_clk.enable = enable;
			mi2s_tx_clk.clk_id = apq8009_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(port_id, &mi2s_tx_clk);
		} else
			pr_err("%s:Not valid substream.\n", __func__);

@@ -563,11 +629,15 @@ static int ext_mi2s_clk_ctl(struct snd_pcm_substream *substream, bool enable,
					__func__, ret);
	} else {
		if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
			mi2s_rx_clk.clk_val1 = Q6AFE_LPASS_IBIT_CLK_DISABLE;
			ret = afe_set_lpass_clock(port_id, &mi2s_rx_clk);
			mi2s_rx_clk.enable = enable;
			mi2s_rx_clk.clk_id = apq8009_get_clk_id(port_id);
			mi2s_rx_clk.clk_freq_in_hz = 0;
			ret = afe_set_lpass_clock_v2(port_id, &mi2s_rx_clk);
		} else if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) {
			mi2s_tx_clk.clk_val1 = Q6AFE_LPASS_IBIT_CLK_DISABLE;
			ret = afe_set_lpass_clock(port_id, &mi2s_tx_clk);
			mi2s_tx_clk.enable = enable;
			mi2s_tx_clk.clk_id = apq8009_get_clk_id(port_id);
			mi2s_tx_clk.clk_freq_in_hz = 0;
			ret = afe_set_lpass_clock_v2(port_id, &mi2s_tx_clk);
		} else
			pr_err("%s:Not valid substream %d\n", __func__,
					substream->stream);
@@ -699,12 +769,11 @@ static int msm_quat_mi2s_snd_startup(struct snd_pcm_substream *substream)
	val = val|0x2020002;
	iowrite32(val, vaddr);

	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
		ret = ext_mi2s_clk_ctl(substream, true,
				AFE_PORT_ID_QUATERNARY_MI2S_RX);
	else if (substream->stream == SNDRV_PCM_STREAM_CAPTURE)
		ret = ext_mi2s_clk_ctl(substream, true,
				AFE_PORT_ID_QUATERNARY_MI2S_TX);
	ret = ext_mi2s_clk_ctl(substream, true);
	if (ret < 0) {
		pr_err("%s: failed to enable sclk\n", __func__);
		return ret;
	}

	ret = msm_gpioset_activate(CLIENT_WCD_EXT, "quat_i2s");
	if (ret < 0) {
@@ -720,8 +789,7 @@ static int msm_quat_mi2s_snd_startup(struct snd_pcm_substream *substream)
	}
	return ret;
err:
	ret = ext_mi2s_clk_ctl(substream, false,
			AFE_PORT_ID_QUATERNARY_MI2S_TX);
	ret = ext_mi2s_clk_ctl(substream, false);
	if (ret < 0)
		pr_err("failed to disable sclk\n");
	return ret;
@@ -734,12 +802,11 @@ 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);
	atomic_dec_return(&quat_mi2s_clk_ref);
	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
		ret = ext_mi2s_clk_ctl(substream, false,
				AFE_PORT_ID_QUATERNARY_MI2S_RX);
	else if (substream->stream == SNDRV_PCM_STREAM_CAPTURE)
		ret = ext_mi2s_clk_ctl(substream, false,
				AFE_PORT_ID_QUATERNARY_MI2S_TX);

	ret = ext_mi2s_clk_ctl(substream, false);
	if (ret < 0)
		pr_err("%s: failed to disable sclk\n", __func__);

	ret = msm_gpioset_suspend(CLIENT_WCD_EXT, "quat_i2s");
	if (ret < 0)
		pr_err("%s: gpio set cannot be de-activated %sd",
@@ -768,12 +835,11 @@ static int msm_mi2s_snd_startup(struct snd_pcm_substream *substream)
	val = val | 0x00000002;
	iowrite32(val, vaddr);

	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
		ret = ext_mi2s_clk_ctl(substream, true,
				AFE_PORT_ID_PRIMARY_MI2S_RX);
	else if (substream->stream == SNDRV_PCM_STREAM_CAPTURE)
		ret = ext_mi2s_clk_ctl(substream, true,
				AFE_PORT_ID_PRIMARY_MI2S_TX);
	ret = ext_mi2s_clk_ctl(substream, true);
	if (ret < 0) {
		pr_err("%s: failed to enable sclk\n", __func__);
		return ret;
	}

	ret = msm_gpioset_activate(CLIENT_WCD_EXT, "pri_i2s");
	if (ret < 0) {
@@ -790,8 +856,7 @@ static int msm_mi2s_snd_startup(struct snd_pcm_substream *substream)
	}
	return ret;
err:
	ret = ext_mi2s_clk_ctl(substream, false,
			AFE_PORT_ID_PRIMARY_MI2S_TX);
	ret = ext_mi2s_clk_ctl(substream, false);
	if (ret < 0)
		pr_err("failed to disable sclk\n");
	return ret;
@@ -804,12 +869,11 @@ static void msm_mi2s_snd_shutdown(struct snd_pcm_substream *substream)
	pr_debug("%s(): substream = %s  stream = %d\n", __func__,
			substream->name, substream->stream);
	atomic_dec_return(&pri_mi2s_clk_ref);
	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
		ext_mi2s_clk_ctl(substream, false,
				AFE_PORT_ID_PRIMARY_MI2S_RX);
	else if (substream->stream == SNDRV_PCM_STREAM_CAPTURE)
		ext_mi2s_clk_ctl(substream, false,
				AFE_PORT_ID_PRIMARY_MI2S_TX);

	ret = ext_mi2s_clk_ctl(substream, false);
	if (ret < 0)
		pr_err("%s: failed to enable sclk\n", __func__);

	ret = msm_gpioset_suspend(CLIENT_WCD_EXT, "pri_i2s");
	if (ret < 0)
		pr_err("%s: gpio set cannot be de-activated %sd",
+18 −0
Original line number Diff line number Diff line
@@ -6327,6 +6327,9 @@ static int msm_audio_sound_focus_derive_port_id(struct snd_kcontrol *kcontrol,
	} else if (!strcmp(kcontrol->id.name + strlen(prefix),
					"TERT_MI2S")) {
		*port_id = AFE_PORT_ID_TERTIARY_MI2S_TX;
	} else if (!strcmp(kcontrol->id.name + strlen(prefix),
					"QUATERNARY_MI2S")) {
		*port_id = AFE_PORT_ID_QUATERNARY_MI2S_TX;
	} else {
		pr_err("%s: mixer ctl name=%s, could not derive valid port id\n",
			__func__, kcontrol->id.name);
@@ -6531,6 +6534,21 @@ static const struct snd_kcontrol_new msm_source_tracking_controls[] = {
		.info	= msm_source_tracking_info,
		.get	= msm_audio_source_tracking_get,
	},
	{
		.access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
		.iface  = SNDRV_CTL_ELEM_IFACE_MIXER,
		.name   = "Sound Focus Audio Tx QUATERNARY_MI2S",
		.info   = msm_sound_focus_info,
		.get    = msm_audio_sound_focus_get,
		.put    = msm_audio_sound_focus_put,
	},
	{
		.access = SNDRV_CTL_ELEM_ACCESS_READ,
		.iface  = SNDRV_CTL_ELEM_IFACE_MIXER,
		.name   = "Source Tracking Audio Tx QUATERNARY_MI2S",
		.info   = msm_source_tracking_info,
		.get    = msm_audio_source_tracking_get,
	},
};

static int spkr_prot_put_vi_lch_port(struct snd_kcontrol *kcontrol,