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

Commit 5bf7be9a authored by qctecmdr's avatar qctecmdr Committed by Gerrit - the friendly Code Review server
Browse files

Merge "asoc: qcs405: Update clk src string from dts"

parents 55752e98 9eab8132
Loading
Loading
Loading
Loading
+46 −0
Original line number Diff line number Diff line
@@ -30796,6 +30796,50 @@ static const struct snd_kcontrol_new
	},
};
static int msm_routing_put_mclk_src_cfg(struct snd_kcontrol *kcontrol,
					struct snd_ctl_elem_value *ucontrol)
{
	u16 port_id = 0;
	int32_t mclk_src_id = 0;
	uint32_t mclk_freq = 0;
	int be_idx, ret = -EINVAL;
	be_idx = ucontrol->value.integer.value[0];
	mclk_src_id = ucontrol->value.integer.value[1];
	mclk_freq = ucontrol->value.integer.value[2];
	if (be_idx < 0 && be_idx >= MSM_BACKEND_DAI_MAX) {
		pr_err("%s: Invalid be id %d\n", __func__, be_idx);
		return -EINVAL;
	}
	if (mclk_src_id < MCLK_SRC_INT && mclk_src_id >= MCLK_SRC_MAX) {
		pr_err("%s: Invalid MCLK src %d\n", __func__, mclk_src_id);
		return -EINVAL;
	}
	if (msm_bedais[be_idx].active) {
		pr_err("%s:BE is active %d, cannot set mclk clock src\n",
			__func__, be_idx);
		return -EINVAL;
	}
	port_id = msm_bedais[be_idx].port_id;
	pr_debug("%s: be idx %d mclk_src id %d mclk_freq %d port id 0x%x\n",
		  __func__, be_idx, mclk_src_id, mclk_freq, port_id);
	ret = afe_set_mclk_src_cfg(port_id, mclk_src_id, mclk_freq);
	if (ret < 0)
		pr_err("%s: failed to set mclk src cfg\n", __func__);
	return ret;
}
static const struct snd_kcontrol_new mclk_src_controls[] = {
	SOC_SINGLE_MULTI_EXT("MCLK_SRC CFG", SND_SOC_NOPM, 0, 24576000, 0, 3,
					NULL, msm_routing_put_mclk_src_cfg),
};
static int msm_routing_stereo_channel_reverse_control_get(
			struct snd_kcontrol *kcontrol,
			struct snd_ctl_elem_value *ucontrol)
@@ -31087,6 +31131,8 @@ static int msm_routing_probe(struct snd_soc_component *component)
	snd_soc_add_component_controls(component, pll_clk_drift_controls,
				      ARRAY_SIZE(pll_clk_drift_controls));
	snd_soc_add_component_controls(component, mclk_src_controls,
				      ARRAY_SIZE(mclk_src_controls));
	return 0;
}
+32 −4
Original line number Diff line number Diff line
// SPDX-License-Identifier: GPL-2.0-only
/* Copyright (c) 2018-2020, The Linux Foundation. All rights reserved.
/* Copyright (c) 2018-2021, The Linux Foundation. All rights reserved.
 */
#include <linux/clk.h>
#include <linux/delay.h>
@@ -219,6 +219,8 @@ struct msm_asoc_wcd93xx_codec {
static const char *const pin_states[] = {"sleep", "i2s-active",
					 "tdm-active"};

const char *clk_src_name[CLK_SRC_MAX];

enum {
	TDM_0 = 0,
	TDM_1,
@@ -6742,10 +6744,17 @@ static int msm_meta_mi2s_snd_startup(struct snd_pcm_substream *substream)

		if (i == 0) {
			port_id = msm_get_port_id(rtd->dai_link->id);
			ret = afe_set_clk_id(port_id,
					     mi2s_clk[member_port].clk_id);
			if (meta_mi2s_rx_cfg[index].sample_rate
					% SAMPLING_RATE_8KHZ) {
				if (clk_src_name[CLK_SRC_FRACT] != NULL)
					ret = afe_set_source_clk(port_id,
							clk_src_name[CLK_SRC_FRACT]);
			} else if (clk_src_name[CLK_SRC_INTEGRAL] != NULL) {
				ret = afe_set_source_clk(port_id,
						clk_src_name[CLK_SRC_INTEGRAL]);
			}
			if (ret < 0)
				pr_err("%s: afe_set_clk_id fail %d\n",
				pr_err("%s: afe_set_source_name fail %d\n",
					 __func__, ret);

			ret = snd_soc_dai_set_fmt(cpu_dai, fmt);
@@ -9906,6 +9915,8 @@ static int msm_asoc_machine_probe(struct platform_device *pdev)
	const char *micb_supply_str1 = "tdm-vdd-micb";
	const char *micb_voltage_str = "qcom,tdm-vdd-micb-voltage";
	const char *micb_current_str = "qcom,tdm-vdd-micb-current";
	const char *clk_src_name_str_integ = "qcom,clk-src-name-integ";
	const char *clk_src_name_str_fract = "qcom,clk-src-name-fract";
	u32 v_base_addr;

	if (!pdev->dev.of_node) {
@@ -9918,6 +9929,23 @@ static int msm_asoc_machine_probe(struct platform_device *pdev)
	if (!pdata)
		return -ENOMEM;

	ret = of_property_read_string_index(pdev->dev.of_node,
			clk_src_name_str_integ, 0,
			&clk_src_name[CLK_SRC_INTEGRAL]);
	if (ret)
		dev_err(&pdev->dev,
			"No clk src name[%d] from device tree\n",
			CLK_SRC_INTEGRAL);
	ret = of_property_read_string_index(pdev->dev.of_node,
			clk_src_name_str_fract, 0,
			&clk_src_name[CLK_SRC_FRACT]);
	if (ret)
		dev_err(&pdev->dev,
			"No clk src name[%d] from device tree\n",
			CLK_SRC_FRACT);
	if (clk_src_name[CLK_SRC_INTEGRAL] != NULL &&
			clk_src_name[CLK_SRC_FRACT] != NULL)
		afe_set_clk_src_array(clk_src_name);
	ret = of_property_read_u32(
		pdev->dev.of_node, "tcsr_i2s_dsd_prim", &v_base_addr);
	if (ret) {
+392 −63
Original line number Diff line number Diff line
@@ -255,45 +255,72 @@ struct afe_ctl {

struct afe_clkinfo_per_port {
	u16 port_id; /* AFE port ID */
	uint32_t clk_id; /* Clock ID */
	uint32_t mclk_src_id; /* MCLK SRC ID */
	uint32_t mclk_freq; /* MCLK_FREQ */
	char clk_src_name[CLK_SRC_NAME_MAX];
};

struct afe_clkinfo_per_port clkinfo_per_port[] = {
	{ AFE_PORT_ID_PRIMARY_MI2S_RX, Q6AFE_LPASS_CLK_ID_PRI_MI2S_IBIT},
	{ AFE_PORT_ID_SECONDARY_MI2S_RX, Q6AFE_LPASS_CLK_ID_SEC_MI2S_IBIT},
	{ AFE_PORT_ID_TERTIARY_MI2S_RX, Q6AFE_LPASS_CLK_ID_TER_MI2S_IBIT},
	{ AFE_PORT_ID_QUATERNARY_MI2S_RX, Q6AFE_LPASS_CLK_ID_QUAD_MI2S_IBIT},
	{ AFE_PORT_ID_QUINARY_MI2S_RX, Q6AFE_LPASS_CLK_ID_QUI_MI2S_IBIT},
	{ AFE_PORT_ID_SENARY_MI2S_RX, Q6AFE_LPASS_CLK_ID_SEN_MI2S_IBIT},
	{ AFE_PORT_ID_PRIMARY_PCM_RX, Q6AFE_LPASS_CLK_ID_PRI_PCM_IBIT},
	{ AFE_PORT_ID_SECONDARY_PCM_RX, Q6AFE_LPASS_CLK_ID_SEC_PCM_IBIT},
	{ AFE_PORT_ID_TERTIARY_PCM_RX, Q6AFE_LPASS_CLK_ID_TER_PCM_IBIT},
	{ AFE_PORT_ID_QUATERNARY_PCM_RX, Q6AFE_LPASS_CLK_ID_QUAD_PCM_IBIT},
	{ AFE_PORT_ID_QUINARY_PCM_RX, Q6AFE_LPASS_CLK_ID_QUIN_PCM_IBIT},
	{ AFE_PORT_ID_SENARY_PCM_RX, Q6AFE_LPASS_CLK_ID_SEN_PCM_IBIT},
	{ AFE_PORT_ID_PRIMARY_TDM_RX, Q6AFE_LPASS_CLK_ID_PRI_TDM_IBIT},
	{ AFE_PORT_ID_SECONDARY_TDM_RX, Q6AFE_LPASS_CLK_ID_SEC_TDM_IBIT},
	{ AFE_PORT_ID_TERTIARY_TDM_RX, Q6AFE_LPASS_CLK_ID_TER_TDM_IBIT},
	{ AFE_PORT_ID_QUATERNARY_TDM_RX, Q6AFE_LPASS_CLK_ID_QUAD_TDM_IBIT},
	{ AFE_PORT_ID_QUINARY_TDM_RX, Q6AFE_LPASS_CLK_ID_QUIN_TDM_IBIT},
struct afe_ext_mclk_cb_info {
	afe_enable_mclk_and_get_info_cb_func ext_mclk_cb;
	void *private_data;
};

static struct afe_clkinfo_per_port clkinfo_per_port[] = {
	{ AFE_PORT_ID_PRIMARY_MI2S_RX,
		MCLK_SRC_INT, Q6AFE_EXT_MCLK_FREQ_DEFAULT, ""},
	{ AFE_PORT_ID_SECONDARY_MI2S_RX,
		MCLK_SRC_INT, Q6AFE_EXT_MCLK_FREQ_DEFAULT, ""},
	{ AFE_PORT_ID_TERTIARY_MI2S_RX,
		MCLK_SRC_INT, Q6AFE_EXT_MCLK_FREQ_DEFAULT, ""},
	{ AFE_PORT_ID_QUATERNARY_MI2S_RX,
		MCLK_SRC_INT, Q6AFE_EXT_MCLK_FREQ_DEFAULT, ""},
	{ AFE_PORT_ID_QUINARY_MI2S_RX,
		MCLK_SRC_INT, Q6AFE_EXT_MCLK_FREQ_DEFAULT, ""},
	{ AFE_PORT_ID_SENARY_MI2S_RX,
		MCLK_SRC_INT, Q6AFE_EXT_MCLK_FREQ_DEFAULT, ""},
	{ AFE_PORT_ID_PRIMARY_PCM_RX,
		MCLK_SRC_INT, Q6AFE_EXT_MCLK_FREQ_DEFAULT, ""},
	{ AFE_PORT_ID_SECONDARY_PCM_RX,
		MCLK_SRC_INT, Q6AFE_EXT_MCLK_FREQ_DEFAULT, ""},
	{ AFE_PORT_ID_TERTIARY_PCM_RX,
		MCLK_SRC_INT, Q6AFE_EXT_MCLK_FREQ_DEFAULT, ""},
	{ AFE_PORT_ID_QUATERNARY_PCM_RX,
		MCLK_SRC_INT, Q6AFE_EXT_MCLK_FREQ_DEFAULT, ""},
	{ AFE_PORT_ID_QUINARY_PCM_RX,
		MCLK_SRC_INT, Q6AFE_EXT_MCLK_FREQ_DEFAULT, ""},
	{ AFE_PORT_ID_SENARY_PCM_RX,
		MCLK_SRC_INT, Q6AFE_EXT_MCLK_FREQ_DEFAULT, ""},
	{ AFE_PORT_ID_PRIMARY_TDM_RX,
		MCLK_SRC_INT, Q6AFE_EXT_MCLK_FREQ_DEFAULT, ""},
	{ AFE_PORT_ID_SECONDARY_TDM_RX,
		MCLK_SRC_INT, Q6AFE_EXT_MCLK_FREQ_DEFAULT, ""},
	{ AFE_PORT_ID_TERTIARY_TDM_RX,
		MCLK_SRC_INT, Q6AFE_EXT_MCLK_FREQ_DEFAULT, ""},
	{ AFE_PORT_ID_QUATERNARY_TDM_RX,
		MCLK_SRC_INT, Q6AFE_EXT_MCLK_FREQ_DEFAULT, ""},
	{ AFE_PORT_ID_QUINARY_TDM_RX,
		MCLK_SRC_INT, Q6AFE_EXT_MCLK_FREQ_DEFAULT, ""},
	{ AFE_PORT_ID_PRIMARY_SPDIF_RX,
		AFE_CLOCK_SET_CLOCK_ID_PRI_SPDIF_OUTPUT_CORE},
		MCLK_SRC_INT, Q6AFE_EXT_MCLK_FREQ_DEFAULT, ""},
	{ AFE_PORT_ID_PRIMARY_SPDIF_TX,
		AFE_CLOCK_SET_CLOCK_ID_PRI_SPDIF_INPUT_CORE},
		MCLK_SRC_INT, Q6AFE_EXT_MCLK_FREQ_DEFAULT, ""},
	{ AFE_PORT_ID_SECONDARY_SPDIF_RX,
		AFE_CLOCK_SET_CLOCK_ID_SEC_SPDIF_OUTPUT_CORE},
		MCLK_SRC_INT, Q6AFE_EXT_MCLK_FREQ_DEFAULT, ""},
	{ AFE_PORT_ID_SECONDARY_SPDIF_TX,
		AFE_CLOCK_SET_CLOCK_ID_SEC_SPDIF_INPUT_CORE},
		MCLK_SRC_INT, Q6AFE_EXT_MCLK_FREQ_DEFAULT, ""},
	{ AFE_PORT_ID_PRIMARY_META_MI2S_RX,
		Q6AFE_LPASS_CLK_ID_PRI_MI2S_IBIT},
		MCLK_SRC_INT, Q6AFE_EXT_MCLK_FREQ_DEFAULT, ""},
	{ AFE_PORT_ID_SECONDARY_META_MI2S_RX,
		Q6AFE_LPASS_CLK_ID_PRI_MI2S_IBIT},
		MCLK_SRC_INT, Q6AFE_EXT_MCLK_FREQ_DEFAULT, ""},
};

static struct afe_ext_mclk_cb_info afe_ext_mclk;

static atomic_t afe_ports_mad_type[SLIMBUS_PORT_LAST - SLIMBUS_0_RX];
static unsigned long afe_configured_cmd;

static struct afe_ctl this_afe;
static char clk_src_name[CLK_SRC_MAX][CLK_SRC_NAME_MAX];

#define TIMEOUT_MS 1000
#define Q6AFE_MAX_VOLUME 0x3FFF
@@ -429,6 +456,37 @@ static int afe_get_cal_hw_delay(int32_t path,
				struct audio_cal_hw_delay_entry *entry);
static int remap_cal_data(struct cal_block_data *cal_block, int cal_index);

/**
 * afe_register_ext_mclk_cb - register callback for external mclk
 *
 * @fn - external mclk callback function
 * @private_data - external mclk callback specific data
 *
 * Returns 0 in case of success and -EINVAL for failure
 */
int afe_register_ext_mclk_cb(afe_enable_mclk_and_get_info_cb_func fn,
				void *private_data)
{
	if (fn && private_data) {
		afe_ext_mclk.ext_mclk_cb = fn;
		afe_ext_mclk.private_data = private_data;
		return 0;
	}

	return -EINVAL;
}
EXPORT_SYMBOL(afe_register_ext_mclk_cb);

/**
 * afe_unregister_ext_mclk_cb - unregister external mclk callback
 */
void afe_unregister_ext_mclk_cb(void)
{
	afe_ext_mclk.ext_mclk_cb = NULL;
	afe_ext_mclk.private_data = NULL;
}
EXPORT_SYMBOL(afe_unregister_ext_mclk_cb);

int afe_get_spk_initial_cal(void)
{
	return this_afe.initial_cal;
@@ -3010,6 +3068,54 @@ static int afe_get_cal_topology_id(u16 port_id, u32 *topology_id,
	return ret;
}

static int afe_port_topology_deregister(u16 port_id)
{
	struct param_hdr_v3 param_info;
	int ret = 0;
	uint32_t build_major_version = 0;
	uint32_t build_minor_version = 0;
	uint32_t build_branch_version = 0;
	uint32_t afe_api_version = 0;

	ret = q6core_get_avcs_avs_build_version_info(
			&build_major_version, &build_minor_version,
			&build_branch_version);
	if (ret < 0)
		goto done;

	ret = q6core_get_avcs_api_version_per_service(
			APRV2_IDS_SERVICE_ID_ADSP_AFE_V);
	if (ret < 0)
		goto done;
	afe_api_version = ret;
	pr_debug("%s: mjor: %u, mnor: %u, brnch: %u, afe_api: %u\n",
		__func__, build_major_version, build_minor_version,
		build_branch_version, afe_api_version);
	if ((build_major_version != AVS_BUILD_MAJOR_VERSION_V2) ||
			(build_minor_version != AVS_BUILD_MINOR_VERSION_V9) ||
			(build_branch_version !=
				AVS_BUILD_BRANCH_VERSION_V3) ||
				(afe_api_version < AFE_API_VERSION_V9)) {
		ret = 0;
		goto done;
	}

	memset(&param_info, 0, sizeof(param_info));
	param_info.module_id = AFE_MODULE_AUDIO_DEV_INTERFACE;
	param_info.instance_id = INSTANCE_ID_0;
	param_info.param_id = AFE_PARAM_ID_DEREGISTER_TOPOLOGY;
	param_info.param_size =  0;
	ret = q6afe_pack_and_set_param_in_band(port_id,
			q6audio_get_port_index(port_id),
			param_info, NULL);

	return ret;
done:
	pr_debug("%s build ver mismatch - leaving function %d\n",
		__func__, ret);
	return ret;
}

static int afe_send_port_topology_id(u16 port_id)
{
	struct afe_param_id_set_topology_cfg topology;
@@ -3018,6 +3124,13 @@ static int afe_send_port_topology_id(u16 port_id)
	int index = 0;
	int ret = 0;

	ret = afe_port_topology_deregister(port_id);
	if (ret < 0) {
		pr_err("%s: AFE deregister topology for port 0x%x failed %d\n",
			__func__, port_id, ret);
		goto done;
	}

	memset(&topology, 0, sizeof(topology));
	memset(&param_info, 0, sizeof(param_info));
	index = q6audio_get_port_index(port_id);
@@ -8679,53 +8792,73 @@ static int afe_get_port_idx(u16 port_id)
	return -EINVAL;
}

static int afe_get_clk_id(u16 port_id)
static int afe_get_clk_src(u16 port_id, char *clk_src)
{
	u16 afe_port = 0;
	uint32_t clk_id = -EINVAL;
	int idx = 0;

	idx = afe_get_port_idx(port_id);
	if (idx < 0) {
		pr_err("%s: cannot get clock id for port id 0x%x\n", __func__,
			afe_port);
			idx);
		return -EINVAL;
	}

	clk_id = clkinfo_per_port[idx].clk_id;
	pr_debug("%s: clk id 0x%x port id 0x%x\n", __func__, clk_id,
		  afe_port);
	if (clkinfo_per_port[idx].clk_src_name == NULL)
		return -EINVAL;
	strlcpy(clk_src, clkinfo_per_port[idx].clk_src_name,
				CLK_SRC_NAME_MAX);
	pr_debug("%s: clk src name %s port id 0x%x\n", __func__, clk_src,
		  idx);

	return clk_id;
	return 0;
}

/**
 * afe_set_clk_id - Update clock id for AFE port
 * afe_set_source_clk - Set audio interface PLL clock source
 *
 * @port_id: AFE port id
 * @clk_id: CLock ID
 * @clk_src: Clock source name for port id
 *
 * Returns 0 on success, appropriate error code otherwise
 */
int afe_set_clk_id(u16 port_id, uint32_t clk_id)
int afe_set_source_clk(u16 port_id, const char *clk_src)
{
	u16 afe_port = 0;
	int idx = 0;

	idx = afe_get_port_idx(port_id);
	if (idx < 0) {
		pr_debug("%s: cannot set clock id for port id 0x%x\n", __func__,
			afe_port);
			idx);
		return -EINVAL;
	}

	clkinfo_per_port[idx].clk_id = clk_id;
	pr_debug("%s: updated clk id 0x%x port id 0x%x\n", __func__,
		  clkinfo_per_port[idx].clk_id, afe_port);
	if (clk_src == NULL)
		return -EINVAL;
	strlcpy(clkinfo_per_port[idx].clk_src_name, clk_src, CLK_SRC_NAME_MAX);
	pr_debug("%s: updated clk src name %s port id 0x%x\n", __func__,
		  clkinfo_per_port[idx].clk_src_name, idx);

	return 0;
}
EXPORT_SYMBOL(afe_set_clk_id);
EXPORT_SYMBOL(afe_set_source_clk);

/**
 * afe_set_clk_src_array -  Set afe clk src array from machine driver
 *
 * @clk_src_array: clk src array for integral and fract clk src
 *
 */
void afe_set_clk_src_array(const char *clk_src_array[CLK_SRC_MAX])
{
	int i;

	for (i = 0; i < CLK_SRC_MAX; i++) {
		if (clk_src_array[i] != NULL)
			strlcpy(clk_src_name[i], clk_src_array[i],
					CLK_SRC_NAME_MAX);
	}
}
EXPORT_SYMBOL(afe_set_clk_src_array);

/**
 * afe_set_pll_clk_drift - Set audio interface PLL clock drift
@@ -8741,8 +8874,33 @@ int afe_set_pll_clk_drift(u16 port_id, int32_t set_clk_drift,
{
	struct afe_set_clk_drift clk_drift;
	struct param_hdr_v3 param_hdr;
	uint32_t clk_id;
	char clk_src_name[CLK_SRC_NAME_MAX];
	int index = 0, ret = 0;
	uint32_t build_major_version = 0;
	uint32_t build_minor_version = 0;
	uint32_t build_branch_version = 0;
	int afe_api_version = 0;

	ret = q6core_get_avcs_avs_build_version_info(
			&build_major_version, &build_minor_version,
						&build_branch_version);
	if (ret < 0) {
		pr_err("%s error in retrieving avs build version %d\n",
				__func__, ret);
		return ret;
	}

	afe_api_version = q6core_get_avcs_api_version_per_service(
				APRV2_IDS_SERVICE_ID_ADSP_AFE_V);
	if (afe_api_version < 0) {
		pr_err("%s error in retrieving afe api version %d\n",
				__func__, afe_api_version);
		return afe_api_version;
	}

	pr_debug("%s: mjor: %u, mnor: %u, brnch: %u, afe_api: %u\n",
		__func__, build_major_version, build_minor_version,
		build_branch_version, afe_api_version);

	memset(&param_hdr, 0, sizeof(param_hdr));
	memset(&clk_drift, 0, sizeof(clk_drift));
@@ -8760,24 +8918,18 @@ int afe_set_pll_clk_drift(u16 port_id, int32_t set_clk_drift,
		return ret;
	}

	clk_id = afe_get_clk_id(port_id);
	if (clk_id < 0) {
		pr_err("%s: cannot get clk id for port id 0x%x\n",
	ret = afe_get_clk_src(port_id, clk_src_name);
	if (ret) {
		pr_err("%s: cannot get clk src name for port id 0x%x\n",
			__func__, port_id);
		return -EINVAL;
	}

	if (clk_id & 0x01) {
		pr_err("%s: cannot adjust clock drift for external clock id 0x%x\n",
			__func__, clk_id);
		return -EINVAL;
	}

	clk_drift.clk_drift = set_clk_drift;
	clk_drift.clk_reset = clk_reset;
	clk_drift.clk_id = clk_id;
	pr_debug("%s: clk id = 0x%x clk drift  = %d clk reset = %d port id 0x%x\n",
		  __func__, clk_drift.clk_id, clk_drift.clk_drift,
	strlcpy(clk_drift.clk_src_name, clk_src_name, CLK_SRC_NAME_MAX);
	pr_debug("%s: clk src= %s clkdrft= %d clkrst= %d port id 0x%x\n",
		  __func__, clk_drift.clk_src_name, clk_drift.clk_drift,
		 clk_drift.clk_reset, port_id);

	mutex_lock(&this_afe.afe_clk_lock);
@@ -8786,17 +8938,110 @@ int afe_set_pll_clk_drift(u16 port_id, int32_t set_clk_drift,
	param_hdr.param_id = AFE_PARAM_ID_CLOCK_ADJUST;
	param_hdr.param_size = sizeof(struct afe_set_clk_drift);

	if ((build_major_version == AVS_BUILD_MAJOR_VERSION_V2) &&
	    (build_minor_version == AVS_BUILD_MINOR_VERSION_V9) &&
	    (build_branch_version == AVS_BUILD_BRANCH_VERSION_V3) &&
	    (afe_api_version >= AFE_API_VERSION_V10)) {

		param_hdr.param_size = sizeof(struct afe_set_clk_drift);
		ret = q6afe_svc_pack_and_set_param_in_band(index, param_hdr,
						   (u8 *) &clk_drift);
		if (ret < 0)
			pr_err_ratelimited("%s: AFE PLL clk drift failed with ret %d\n",
				    __func__, ret);

	} else {
		ret = -EINVAL;
		pr_err_ratelimited("%s: AFE PLL clk drift failed ver mismatch %d\n",
				    __func__, ret);
	}
	mutex_unlock(&this_afe.afe_clk_lock);
	return ret;
}
EXPORT_SYMBOL(afe_set_pll_clk_drift);

static int afe_set_lpass_clk_cfg_ext_mclk(int index, struct afe_clk_set *cfg,
							uint32_t mclk_freq)
{
	struct param_hdr_v3 param_hdr;
	struct afe_param_id_clock_set_v2_t dyn_mclk_cfg;
	int ret = 0;

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

	if (index < 0 || index >= AFE_MAX_PORTS) {
		pr_err("%s: index[%d] invalid!\n", __func__, index);
		return -EINVAL;
	}

	memset(&param_hdr, 0, sizeof(param_hdr));
	param_hdr.module_id = AFE_MODULE_CLOCK_SET;
	param_hdr.instance_id = INSTANCE_ID_0;
	param_hdr.param_id = AFE_PARAM_ID_CLOCK_SET_V2;
	param_hdr.param_size = sizeof(struct afe_param_id_clock_set_v2_t);

	memset(&dyn_mclk_cfg, 0, sizeof(dyn_mclk_cfg));
	dyn_mclk_cfg.clk_freq_in_hz = cfg->clk_freq_in_hz;
	if (afe_ext_mclk.ext_mclk_cb) {
		ret =  afe_ext_mclk.ext_mclk_cb(afe_ext_mclk.private_data,
			cfg->enable, mclk_freq, &dyn_mclk_cfg);
		if (ret) {
			pr_err_ratelimited("%s: get mclk cfg failed %d\n",
					__func__, ret);
			return ret;
		}
	} else {
		pr_err_ratelimited("%s: mclk callback not registered\n",
					__func__);
		return -EINVAL;
	}

	dyn_mclk_cfg.clk_set_minor_version = 1;
	dyn_mclk_cfg.clk_id = cfg->clk_id;
	dyn_mclk_cfg.clk_attri = cfg->clk_attri;
	dyn_mclk_cfg.enable = cfg->enable;

	pr_debug("%s: Minor version =0x%x clk id = %d\n", __func__,
		dyn_mclk_cfg.clk_set_minor_version, dyn_mclk_cfg.clk_id);
	pr_debug("%s: clk freq (Hz) = %d, clk attri = 0x%x\n", __func__,
		dyn_mclk_cfg.clk_freq_in_hz, dyn_mclk_cfg.clk_attri);
	pr_debug("%s: clk root = 0x%x clk enable = 0x%x\n", __func__,
		dyn_mclk_cfg.clk_root, dyn_mclk_cfg.enable);
	pr_debug("%s: divider_2x =%d m = %d n = %d, d =%d\n", __func__,
		dyn_mclk_cfg.divider_2x, dyn_mclk_cfg.m, dyn_mclk_cfg.n,
		dyn_mclk_cfg.d);

	ret = afe_q6_interface_prepare();
	if (ret != 0) {
		pr_err_ratelimited("%s: Q6 interface prepare failed %d\n",
				__func__, ret);
		goto stop_mclk;
	}

	mutex_lock(&this_afe.afe_cmd_lock);
	ret = q6afe_svc_pack_and_set_param_in_band(index, param_hdr,
						   (u8 *) &dyn_mclk_cfg);
	if (ret < 0)
		pr_err_ratelimited("%s: ext MCLK clk cfg failed with ret %d\n",
				__func__, ret);

	mutex_unlock(&this_afe.afe_cmd_lock);

	if (ret >= 0)
		return ret;

stop_mclk:
	if (afe_ext_mclk.ext_mclk_cb && cfg->enable) {
		afe_ext_mclk.ext_mclk_cb(afe_ext_mclk.private_data,
				cfg->enable, mclk_freq, &dyn_mclk_cfg);
	}

	return ret;
}

/**
 * afe_set_lpass_clk_cfg - Set AFE clk config
 *
@@ -8869,6 +9114,11 @@ int afe_set_lpass_clock_v2(u16 port_id, struct afe_clk_set *cfg)
{
	int index = 0;
	int ret = 0;
	u16 idx = 0;
	uint32_t build_major_version = 0;
	uint32_t build_minor_version = 0;
	uint32_t build_branch_version = 0;
	int afe_api_version = 0;

	index = q6audio_get_port_index(port_id);
	if (index < 0 || index >= AFE_MAX_PORTS) {
@@ -8883,11 +9133,60 @@ int afe_set_lpass_clock_v2(u16 port_id, struct afe_clk_set *cfg)
		return -EINVAL;
	}

	ret = afe_set_clk_id(port_id, cfg->clk_id);
	if (clk_src_name != NULL) {
		if (cfg->clk_freq_in_hz % AFE_SAMPLING_RATE_8KHZ) {
			if (clk_src_name[CLK_SRC_FRACT] != NULL)
				ret = afe_set_source_clk(port_id,
						clk_src_name[CLK_SRC_FRACT]);
		} else if (clk_src_name[CLK_SRC_INTEGRAL] != NULL) {
			ret = afe_set_source_clk(port_id,
					clk_src_name[CLK_SRC_INTEGRAL]);
		}
		if (ret < 0)
			pr_err("%s: afe_set_source_clk fail %d\n",
				__func__, ret);
	}
	idx = afe_get_port_idx(port_id);
	if (idx < 0) {
		pr_err("%s: cannot get clock id for port id 0x%x\n", __func__,
			port_id);
		return -EINVAL;
	}

	if (clkinfo_per_port[idx].mclk_src_id != MCLK_SRC_INT) {
		pr_debug("%s: ext MCLK src %d\n",
			__func__, clkinfo_per_port[idx].mclk_src_id);

		ret = q6core_get_avcs_avs_build_version_info(
			&build_major_version, &build_minor_version,
						&build_branch_version);
		if (ret < 0)
			return ret;

		ret = q6core_get_avcs_api_version_per_service(
					APRV2_IDS_SERVICE_ID_ADSP_AFE_V);
		if (ret < 0)
		pr_debug("%s: afe_set_clk_id fail %d\n", __func__, ret);
			return ret;

		afe_api_version = ret;

		pr_debug("%s: mjor: %u, mnor: %u, brnch: %u, afe_api: %u\n",
			__func__, build_major_version, build_minor_version,
			build_branch_version, afe_api_version);
		if ((build_major_version != AVS_BUILD_MAJOR_VERSION_V2) ||
		    (build_minor_version != AVS_BUILD_MINOR_VERSION_V9) ||
		    (build_branch_version != AVS_BUILD_BRANCH_VERSION_V3) ||
		    (afe_api_version < AFE_API_VERSION_V8)) {
			pr_err("%s: ext mclk not supported by AVS\n", __func__);
			return -EINVAL;
		}

		ret = afe_set_lpass_clk_cfg_ext_mclk(index, cfg,
					clkinfo_per_port[idx].mclk_freq);
	} else {
		ret = afe_set_lpass_clk_cfg(index, cfg);
	}

	if (ret)
		pr_err("%s: afe_set_lpass_clk_cfg_v2 failed %d\n",
			__func__, ret);
@@ -8896,6 +9195,36 @@ int afe_set_lpass_clock_v2(u16 port_id, struct afe_clk_set *cfg)
}
EXPORT_SYMBOL(afe_set_lpass_clock_v2);

/**
 * afe_set_mclk_src_cfg - Set audio interface MCLK source configuration
 *
 * @port_id: AFE port id
 * @mclk_src_id: mclk id to represent internal or one of external MCLK
 * @mclk_freq: frequency of the MCLK
 *
 * Returns 0 on success, appropriate error code otherwise
 */
int afe_set_mclk_src_cfg(u16 port_id, uint32_t mclk_src_id, uint32_t mclk_freq)
{
	int idx = 0;

	idx = afe_get_port_idx(port_id);
	if (idx < 0) {
		pr_err("%s: cannot get clock id for port id 0x%x\n",
			__func__, port_id);
		return -EINVAL;
	}

	clkinfo_per_port[idx].mclk_src_id = mclk_src_id;
	clkinfo_per_port[idx].mclk_freq = mclk_freq;

	pr_debug("%s: mclk src id 0x%x mclk_freq %d port id 0x%x\n",
		__func__, mclk_src_id, mclk_freq, port_id);

	return 0;
}
EXPORT_SYMBOL(afe_set_mclk_src_cfg);

int afe_set_lpass_internal_digital_codec_clock(u16 port_id,
			struct afe_digital_clk_cfg *cfg)
{
+39 −1
Original line number Diff line number Diff line
// SPDX-License-Identifier: GPL-2.0-only
/*
 * Copyright (c) 2012-2020, The Linux Foundation. All rights reserved.
 * Copyright (c) 2012-2021, The Linux Foundation. All rights reserved.
 */

#include <linux/kernel.h>
@@ -739,6 +739,44 @@ int q6core_get_avcs_api_version_per_service(uint32_t service_id)
}
EXPORT_SYMBOL(q6core_get_avcs_api_version_per_service);

/**
 * q6core_get_avcs_avs_build_version_info - Get AVS build version information
 *
 * @build_major_version - pointer to build major version
 * @build_minor_version - pointer to build minor version
 * @build_branch_version - pointer to build branch version
 *
 * Returns 0 on success and error on failure
 */
int q6core_get_avcs_avs_build_version_info(
	uint32_t *build_major_version, uint32_t *build_minor_version,
					uint32_t *build_branch_version)
{

	struct avcs_fwk_ver_info *cached_ver_info = NULL;
	int ret = 0;

	if (!build_major_version || !build_minor_version ||
		!build_branch_version)
		return -EINVAL;

	ret = q6core_get_avcs_fwk_version();
	if (ret < 0)
		return ret;

	cached_ver_info = q6core_lcl.q6core_avcs_ver_info.ver_info;

	*build_major_version =
			cached_ver_info->avcs_fwk_version.build_major_version;
	*build_minor_version =
			cached_ver_info->avcs_fwk_version.build_minor_version;
	*build_branch_version =
			cached_ver_info->avcs_fwk_version.build_branch_version;

	return ret;
}
EXPORT_SYMBOL(q6core_get_avcs_avs_build_version_info);

/**
 * core_set_license -
 *       command to set license for module
+40 −11
Original line number Diff line number Diff line
/* SPDX-License-Identifier: GPL-2.0-only */
/*
 * Copyright (c) 2012-2020, The Linux Foundation. All rights reserved.
 * Copyright (c) 2012-2021, The Linux Foundation. All rights reserved.
 */


@@ -3965,6 +3965,7 @@ struct afe_param_id_device_hw_delay_cfg {
} __packed;

#define AFE_PARAM_ID_SET_TOPOLOGY    0x0001025A
#define AFE_PARAM_ID_DEREGISTER_TOPOLOGY	0x000102E8
#define AFE_API_VERSION_TOPOLOGY_V1 0x1

struct afe_param_id_set_topology_cfg {
@@ -12166,6 +12167,27 @@ struct afe_clk_set {
	uint32_t enable;
};

#define AVS_BUILD_MAJOR_VERSION_V2		2
#define AVS_BUILD_MINOR_VERSION_V9		9
#define AVS_BUILD_BRANCH_VERSION_V3		3

#define AFE_PARAM_ID_CLOCK_SET_V2		0x000102E6

#define AFE_API_VERSION_CLOCK_SET_V2		0x1

struct afe_param_id_clock_set_v2_t {
	uint32_t	clk_set_minor_version;
	uint32_t	clk_id;
	uint32_t	clk_freq_in_hz;
	uint16_t	clk_attri;
	uint16_t	clk_root;
	uint32_t	enable;
	uint32_t	divider_2x;
	uint32_t	m;
	uint32_t	n;
	uint32_t	d;
};

struct afe_clk_cfg {
/* Minor version used for tracking the version of the I2S
 * configuration interface.
@@ -12206,16 +12228,15 @@ struct afe_clk_cfg {
#define AFE_MODULE_CLOCK_SET		0x0001028F
#define AFE_PARAM_ID_CLOCK_SET		0x00010290

struct afe_set_clk_drift {
	/*
	 * Clock ID
	 *	@values
	 *	- 0x100 to 0x10E
	 *	- 0x200 to 0x20C
	 *	- 0x500 to 0x505
	 */
	uint32_t clk_id;
#define CLK_SRC_NAME_MAX 32

enum {
	CLK_SRC_INTEGRAL,
	CLK_SRC_FRACT,
	CLK_SRC_MAX
};

struct afe_set_clk_drift {
	/*
	 * Clock drift  (in PPB) to be set.
	 *	@values
@@ -12224,12 +12245,20 @@ struct afe_set_clk_drift {
	int32_t clk_drift;

	/*
	 * Clock rest.
	 * Clock reset.
	 *	@values
	 *	- 1 -- Reset PLL with the original frequency
	 *	- 0 -- Adjust the clock with the clk drift value
	 */
	uint32_t clk_reset;
	/*
	 * Clock src name.
	 *  @values
	 *  - values to be set from machine driver
	 *  - LPAPLL0 -- integral clk src
	 *  - LPAPLL2 -- fractional clk src
	 */
	char clk_src_name[CLK_SRC_NAME_MAX];
} __packed;

/* This param id is used to adjust audio interface PLL*/
Loading