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

Commit 957bcf41 authored by Siena Richard's avatar Siena Richard
Browse files

ASoC: audio-ext-clk: check AFE version before setting clocks



AFE clock APIs can change depending on the AVS service version. Check
the clock APIs reported by AFE to determine the correct AFE clock API
to use when setting the LPASS clocks.

CRs-Fixed: 2018143
Signed-off-by: default avatarSiena Richard <sienar@codeaurora.org>
Change-Id: Ia009abf4fbcacb8ba26281f30475698cf40bcd6c
parent f969b026
Loading
Loading
Loading
Loading
+111 −67
Original line number Diff line number Diff line
@@ -31,6 +31,11 @@ enum clk_mux {
	LPASS_MCLK2,
};

enum clk_enablement {
	CLK_DISABLE = 0,
	CLK_ENABLE,
};

struct pinctrl_info {
	struct pinctrl *pinctrl;
	struct pinctrl_state *sleep;
@@ -169,44 +174,56 @@ static void audio_ext_clk2_unprepare(struct clk *clk)
		pr_err("%s: failed to reset clock, ret = %d\n", __func__, ret);
}

static int audio_ext_lpass_mclk_prepare(struct clk *clk)
static int audio_ext_set_lpass_mclk_v1(struct clk *clk,
				       enum clk_enablement enable)
{
	struct audio_ext_lpass_mclk *audio_lpass_mclk;
	struct pinctrl_info *pnctrl_info;
	struct afe_clk_cfg *lpass_clk = NULL;
	int ret, val = 0;
	struct pinctrl_state *pnctrl_state;
	struct afe_clk_cfg lpass_clks = lpass_default;
	int val = 0;
	int ret;

	audio_lpass_mclk = container_of(clk, struct audio_ext_lpass_mclk, c);
	pnctrl_info = &audio_lpass_mclk->pnctrl_info;
	pr_debug("%s: Setting clock using v1, enable(%d)\n", __func__, enable);

	lpass_clk = kzalloc(sizeof(struct afe_clk_cfg), GFP_KERNEL);
	if (!lpass_clk)
		return -ENOMEM;
	audio_lpass_mclk = container_of(clk, struct audio_ext_lpass_mclk, c);
	if (audio_lpass_mclk == NULL) {
		pr_err("%s: audio_lpass_mclk is NULL\n", __func__);
		ret = -EINVAL;
		goto done;
	}

	if (pnctrl_info->pinctrl) {
		ret = pinctrl_select_state(pnctrl_info->pinctrl,
				pnctrl_info->active);
	pnctrl_info = &audio_lpass_mclk->pnctrl_info;
	if (pnctrl_info && pnctrl_info->pinctrl) {
		pnctrl_state =
			enable ? pnctrl_info->active : pnctrl_info->sleep;
		ret = pinctrl_select_state(pnctrl_info->pinctrl, pnctrl_state);
		if (ret) {
			pr_err("%s: active state select failed with %d\n",
				__func__, ret);
			pr_err("%s: pinctrl state selection for %s failed with %d\n",
				__func__,
				(pnctrl_state == pnctrl_info->active) ?
					"active" : "sleep",
				ret);
			ret = -EIO;
			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;
		lpass_clks.clk_val2 =
			enable ? Q6AFE_LPASS_OSR_CLK_12_P288_MHZ : 0;
		lpass_clks.clk_set_mode = Q6AFE_LPASS_MODE_CLK2_VALID;
		ret = afe_set_lpass_clock(AFE_PORT_ID_SECONDARY_MI2S_RX,
				lpass_clk);
					  &lpass_clks);
		if (ret < 0) {
			pr_err("%s afe_set_lpass_clock failed, ret = %d\n",
			pr_err("%s: afe_set_lpass_clock failed with ret = %d\n",
			       __func__, ret);
			kfree(lpass_clk);
			return -EINVAL;
			ret = -EINVAL;
			goto done;
		}
	} else {
		if (audio_lpass_mclk->lpass_csr_gpio_mux_spkrctl_vaddr) {
		if (audio_lpass_mclk->lpass_csr_gpio_mux_spkrctl_vaddr &&
		    enable) {
			val = ioread32(audio_lpass_mclk->
					lpass_csr_gpio_mux_spkrctl_vaddr);
			val = val | 0x00000002;
@@ -214,65 +231,92 @@ static int audio_ext_lpass_mclk_prepare(struct clk *clk)
					lpass_csr_gpio_mux_spkrctl_vaddr);
		}

		digital_cdc_core_clk.enable = 1;
		digital_cdc_core_clk.enable = enable;
		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;
			pr_err("%s: afe_set_digital_codec_core_clock failed with ret %d\n",
			       __func__, ret);
			goto done;
		}
	}

	ret = 0;

done:
	kfree(lpass_clk);
	return 0;
	return ret;
}

static void audio_ext_lpass_mclk_unprepare(struct clk *clk)
static int audio_ext_set_lpass_mclk_v2(enum clk_enablement enable)
{
	struct audio_ext_lpass_mclk *audio_lpass_mclk;
	struct pinctrl_info *pnctrl_info;
	struct afe_clk_cfg *lpass_clk = NULL;
	int ret;
	struct afe_clk_set m_clk = lpass_default2;
	struct afe_clk_set ibit_clk = lpass_default2;
	int ret = 0;

	audio_lpass_mclk = container_of(clk, struct audio_ext_lpass_mclk, c);
	pnctrl_info = &audio_lpass_mclk->pnctrl_info;
	pr_debug("%s: Setting clock using v2, enable(%d)\n", __func__, enable);

	lpass_clk = kzalloc(sizeof(struct afe_clk_cfg), GFP_KERNEL);
	if (!lpass_clk)
		return;
	/* Set both mclk and ibit clocks when using LPASS_CLK_VER_2 */
	m_clk.clk_id = Q6AFE_LPASS_CLK_ID_MCLK_3;
	m_clk.enable = enable;
	ret = afe_set_lpass_clock_v2(AFE_PORT_ID_PRIMARY_MI2S_RX, &m_clk);
	if (ret < 0) {
		pr_err("%s: afe_set_lpass_clock_v2 failed for mclk_3 with ret %d\n",
		       __func__, ret);
		goto done;
	}

	if (pnctrl_info->pinctrl) {
		ret = pinctrl_select_state(pnctrl_info->pinctrl,
					   pnctrl_info->sleep);
		if (ret) {
			pr_err("%s: active state select failed with %d\n",
	ibit_clk.clk_id = Q6AFE_LPASS_CLK_ID_PRI_MI2S_IBIT;
	ibit_clk.clk_freq_in_hz = Q6AFE_LPASS_IBIT_CLK_1_P536_MHZ;
	ibit_clk.enable = enable;
	ret = afe_set_lpass_clock_v2(AFE_PORT_ID_PRIMARY_MI2S_RX, &ibit_clk);
	if (ret < 0) {
		pr_err("%s: afe_set_lpass_clock_v2 failed for ibit with ret %d\n",
		       __func__, ret);
			ret = -EIO;
			goto err;
		goto err_ibit_clk_set;
	}

	ret = 0;

done:
	return ret;

err_ibit_clk_set:
	m_clk.enable = CLK_DISABLE;
	if (afe_set_lpass_clock_v2(AFE_PORT_ID_PRIMARY_MI2S_RX, &m_clk)) {
		pr_err("%s: afe_set_lpass_clock_v2 failed to disable mclk_3\n",
		       __func__);
	}
	return ret;
}
	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);
		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);
static int audio_ext_lpass_mclk_prepare(struct clk *clk)
{
	enum lpass_clk_ver lpass_clk_ver;
	int ret;

	lpass_clk_ver = afe_get_lpass_clk_ver();

	if (lpass_clk_ver >= LPASS_CLK_VER_2)
		ret = audio_ext_set_lpass_mclk_v2(CLK_ENABLE);
	else
		ret = audio_ext_set_lpass_mclk_v1(clk, CLK_ENABLE);

	return ret;
}
err:
	kfree(lpass_clk);

static void audio_ext_lpass_mclk_unprepare(struct clk *clk)
{
	enum lpass_clk_ver lpass_clk_ver;
	int ret;

	lpass_clk_ver = afe_get_lpass_clk_ver();

	if (lpass_clk_ver >= LPASS_CLK_VER_2)
		ret = audio_ext_set_lpass_mclk_v2(CLK_DISABLE);
	else
		ret = audio_ext_set_lpass_mclk_v1(clk, CLK_DISABLE);

	pr_debug("%s: Unprepare of mclk returned %d\n", __func__, ret);
}

static int audio_ext_lpass_mclk2_prepare(struct clk *clk)