Loading asoc/qcs405.c +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> Loading Loading @@ -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, Loading Loading @@ -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); Loading Loading @@ -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"); Loading Loading @@ -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) Loading dsp/q6afe.c +140 −85 Original line number Diff line number Diff line Loading @@ -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 { Loading @@ -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; Loading @@ -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 Loading Loading @@ -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 Loading @@ -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(¶m_hdr, 0, sizeof(param_hdr)); memset(&clk_drift, 0, sizeof(clk_drift)); Loading @@ -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); Loading @@ -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); 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; } Loading Loading @@ -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 (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_clk_id fail %d\n", __func__, ret); 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__, Loading include/dsp/apr_audio-v2.h +17 −10 Original line number Diff line number Diff line Loading @@ -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 Loading @@ -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*/ Loading include/dsp/q6afe-v2.h +5 −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. */ #ifndef __Q6AFE_V2_H__ #define __Q6AFE_V2_H__ Loading Loading @@ -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 Loading Loading @@ -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, Loading Loading
asoc/qcs405.c +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> Loading Loading @@ -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, Loading Loading @@ -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); Loading Loading @@ -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"); Loading Loading @@ -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) Loading
dsp/q6afe.c +140 −85 Original line number Diff line number Diff line Loading @@ -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 { Loading @@ -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; Loading @@ -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 Loading Loading @@ -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 Loading @@ -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(¶m_hdr, 0, sizeof(param_hdr)); memset(&clk_drift, 0, sizeof(clk_drift)); Loading @@ -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); Loading @@ -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); 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; } Loading Loading @@ -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 (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_clk_id fail %d\n", __func__, ret); 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__, Loading
include/dsp/apr_audio-v2.h +17 −10 Original line number Diff line number Diff line Loading @@ -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 Loading @@ -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*/ Loading
include/dsp/q6afe-v2.h +5 −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. */ #ifndef __Q6AFE_V2_H__ #define __Q6AFE_V2_H__ Loading Loading @@ -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 Loading Loading @@ -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, Loading