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

This commit is contained in:
qctecmdr 2021-03-09 09:41:01 -08:00 committed by Gerrit - the friendly Code Review server
commit 2e51c87fc7
4 changed files with 195 additions and 101 deletions

View File

@ -1,5 +1,5 @@
// 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);
@ -9907,6 +9916,8 @@ static int msm_asoc_machine_probe(struct platform_device *pdev)
const char *micb_voltage_str = "qcom,tdm-vdd-micb-voltage";
const char *micb_current_str = "qcom,tdm-vdd-micb-current";
u32 v_base_addr;
const char *clk_src_name_str_integ = "qcom,clk-src-name-integ";
const char *clk_src_name_str_fract = "qcom,clk-src-name-fract";
if (!pdev->dev.of_node) {
dev_err(&pdev->dev, "No platform supplied from device tree\n");
@ -9943,6 +9954,23 @@ static int msm_asoc_machine_probe(struct platform_device *pdev)
}
}
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);
/* test for ep92 HDMI bridge and update dai links accordingly */
ret = msm_detect_ep92_dev(pdev, card);
if (ret)

View File

@ -268,9 +268,9 @@ 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_ext_mclk_cb_info {
@ -279,56 +279,52 @@ struct afe_ext_mclk_cb_info {
};
static struct afe_clkinfo_per_port clkinfo_per_port[] = {
{ AFE_PORT_ID_PRIMARY_MI2S_RX, Q6AFE_LPASS_CLK_ID_PRI_MI2S_IBIT,
MCLK_SRC_INT, Q6AFE_EXT_MCLK_FREQ_DEFAULT},
{ AFE_PORT_ID_SECONDARY_MI2S_RX, Q6AFE_LPASS_CLK_ID_SEC_MI2S_IBIT,
MCLK_SRC_INT, Q6AFE_EXT_MCLK_FREQ_DEFAULT},
{ AFE_PORT_ID_TERTIARY_MI2S_RX, Q6AFE_LPASS_CLK_ID_TER_MI2S_IBIT,
MCLK_SRC_INT, Q6AFE_EXT_MCLK_FREQ_DEFAULT},
{ AFE_PORT_ID_QUATERNARY_MI2S_RX, Q6AFE_LPASS_CLK_ID_QUAD_MI2S_IBIT,
MCLK_SRC_INT, Q6AFE_EXT_MCLK_FREQ_DEFAULT},
{ AFE_PORT_ID_QUINARY_MI2S_RX, Q6AFE_LPASS_CLK_ID_QUI_MI2S_IBIT,
MCLK_SRC_INT, Q6AFE_EXT_MCLK_FREQ_DEFAULT},
{ AFE_PORT_ID_SENARY_MI2S_RX, Q6AFE_LPASS_CLK_ID_SEN_MI2S_IBIT,
MCLK_SRC_INT, Q6AFE_EXT_MCLK_FREQ_DEFAULT},
{ AFE_PORT_ID_PRIMARY_PCM_RX, Q6AFE_LPASS_CLK_ID_PRI_PCM_IBIT,
MCLK_SRC_INT, Q6AFE_EXT_MCLK_FREQ_DEFAULT},
{ AFE_PORT_ID_SECONDARY_PCM_RX, Q6AFE_LPASS_CLK_ID_SEC_PCM_IBIT,
MCLK_SRC_INT, Q6AFE_EXT_MCLK_FREQ_DEFAULT},
{ AFE_PORT_ID_TERTIARY_PCM_RX, Q6AFE_LPASS_CLK_ID_TER_PCM_IBIT,
MCLK_SRC_INT, Q6AFE_EXT_MCLK_FREQ_DEFAULT},
{ AFE_PORT_ID_QUATERNARY_PCM_RX, Q6AFE_LPASS_CLK_ID_QUAD_PCM_IBIT,
MCLK_SRC_INT, Q6AFE_EXT_MCLK_FREQ_DEFAULT},
{ AFE_PORT_ID_QUINARY_PCM_RX, Q6AFE_LPASS_CLK_ID_QUIN_PCM_IBIT,
MCLK_SRC_INT, Q6AFE_EXT_MCLK_FREQ_DEFAULT},
{ AFE_PORT_ID_SENARY_PCM_RX, Q6AFE_LPASS_CLK_ID_SEN_PCM_IBIT,
MCLK_SRC_INT, Q6AFE_EXT_MCLK_FREQ_DEFAULT},
{ AFE_PORT_ID_PRIMARY_TDM_RX, Q6AFE_LPASS_CLK_ID_PRI_TDM_IBIT,
MCLK_SRC_INT, Q6AFE_EXT_MCLK_FREQ_DEFAULT},
{ AFE_PORT_ID_SECONDARY_TDM_RX, Q6AFE_LPASS_CLK_ID_SEC_TDM_IBIT,
MCLK_SRC_INT, Q6AFE_EXT_MCLK_FREQ_DEFAULT},
{ AFE_PORT_ID_TERTIARY_TDM_RX, Q6AFE_LPASS_CLK_ID_TER_TDM_IBIT,
MCLK_SRC_INT, Q6AFE_EXT_MCLK_FREQ_DEFAULT},
{ AFE_PORT_ID_QUATERNARY_TDM_RX, Q6AFE_LPASS_CLK_ID_QUAD_TDM_IBIT,
MCLK_SRC_INT, Q6AFE_EXT_MCLK_FREQ_DEFAULT},
{ AFE_PORT_ID_QUINARY_TDM_RX, Q6AFE_LPASS_CLK_ID_QUIN_TDM_IBIT,
MCLK_SRC_INT, Q6AFE_EXT_MCLK_FREQ_DEFAULT},
{ 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},
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},
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},
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},
MCLK_SRC_INT, Q6AFE_EXT_MCLK_FREQ_DEFAULT, ""},
{ AFE_PORT_ID_PRIMARY_META_MI2S_RX,
MCLK_SRC_INT, Q6AFE_EXT_MCLK_FREQ_DEFAULT, ""},
{ AFE_PORT_ID_SECONDARY_META_MI2S_RX,
MCLK_SRC_INT, Q6AFE_EXT_MCLK_FREQ_DEFAULT, ""},
};
static struct afe_ext_mclk_cb_info afe_ext_mclk;
@ -337,6 +333,7 @@ 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
@ -9230,53 +9227,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
@ -9292,8 +9309,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));
@ -9311,24 +9353,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);
@ -9337,12 +9373,22 @@ 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);
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);
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;
}
@ -9524,10 +9570,19 @@ 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 (ret < 0)
pr_err("%s: afe_set_clk_id fail %d\n", __func__, ret);
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__,

View File

@ -12349,16 +12349,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
@ -12367,12 +12366,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*/

View File

@ -1,6 +1,6 @@
/* 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.
*/
#ifndef __Q6AFE_V2_H__
#define __Q6AFE_V2_H__
@ -53,7 +53,9 @@
#define AFE_API_VERSION_V9 9
/* for external mclk dynamic switch */
#define AFE_API_VERSION_V8 8
#define AFE_API_VERSION_V10 10
#define AFE_SAMPLING_RATE_8KHZ 8000
/* the different modes for data*/
#define BAP_UNICAST 1
@ -545,6 +547,8 @@ enum {
AFE_LPASS_CORE_HW_DCODEC_BLOCK,
AFE_LPASS_CORE_HW_VOTE_MAX
};
int afe_set_source_clk(u16 port_id, const char *clk_src);
void afe_set_clk_src_array(const char *clk_src[CLK_SRC_MAX]);
int afe_set_mclk_src_cfg(u16 port_id, uint32_t mclk_src_id, uint32_t mclk_freq);
typedef int (*afe_enable_mclk_and_get_info_cb_func) (void *private_data,