Loading asoc/msm-pcm-routing-v2.c +47 −0 Original line number Diff line number Diff line Loading @@ -30180,6 +30180,50 @@ static const struct snd_kcontrol_new aptx_dec_license_controls[] = { msm_aptx_dec_license_control_put), }; static int msm_routing_get_pll_clk_drift(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { return 0; } static int msm_routing_put_pll_clk_drift(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { u16 port_id = 0; int32_t clk_drift = 0; uint32_t clk_reset = 0; int be_idx, ret = -EINVAL; be_idx = ucontrol->value.integer.value[0]; clk_drift = ucontrol->value.integer.value[1]; clk_reset = 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 (!msm_bedais[be_idx].active && !clk_reset) { pr_err("%s:BE is not active %d, cannot set clock drift\n", __func__, be_idx); return -EINVAL; } port_id = msm_bedais[be_idx].port_id; pr_debug("%s: clk drift %d be idx %d clk reset %d port id 0x%x\n", __func__, clk_drift, be_idx, clk_reset, port_id); ret = afe_set_pll_clk_drift(port_id, clk_drift, clk_reset); if (ret < 0) pr_err("%s: failed to set pll clk drift\n", __func__); return ret; } static const struct snd_kcontrol_new pll_clk_drift_controls[] = { SOC_SINGLE_MULTI_EXT("PLL config data", SND_SOC_NOPM, 0, 0xFFFFFFFF, 0, 128, msm_routing_get_pll_clk_drift, msm_routing_put_pll_clk_drift), }; static int msm_routing_put_port_chmap_mixer(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { Loading Loading @@ -30480,6 +30524,9 @@ static int msm_routing_probe(struct snd_soc_component *component) port_multi_channel_map_mixer_controls, ARRAY_SIZE(port_multi_channel_map_mixer_controls)); snd_soc_add_component_controls(component, pll_clk_drift_controls, ARRAY_SIZE(pll_clk_drift_controls)); return 0; } asoc/qcs405.c +8 −0 Original line number Diff line number Diff line Loading @@ -6309,6 +6309,7 @@ static int msm_meta_mi2s_snd_startup(struct snd_pcm_substream *substream) unsigned int fmt = SND_SOC_DAIFMT_CBS_CFS; struct snd_soc_card *card = rtd->card; struct msm_asoc_mach_data *pdata = snd_soc_card_get_drvdata(card); u16 port_id = 0; dev_dbg(rtd->card->dev, "%s: substream = %s stream = %d, dai name %s, dai ID %d\n", Loading Loading @@ -6342,6 +6343,13 @@ static int msm_meta_mi2s_snd_startup(struct snd_pcm_substream *substream) meta_mi2s_intf_conf[index].clk_enable[i] = true; 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 (ret < 0) pr_err("%s: afe_set_clk_id fail %d\n", __func__, ret); ret = snd_soc_dai_set_fmt(cpu_dai, fmt); if (ret < 0) { pr_err("%s: set fmt cpu dai failed for META_MI2S (%d), err:%d\n", Loading dsp/q6afe.c +191 −0 Original line number Diff line number Diff line Loading @@ -184,6 +184,43 @@ struct afe_ctl { uint32_t v_vali_flag; }; struct afe_clkinfo_per_port { u16 port_id; /* AFE port ID */ uint32_t clk_id; /* Clock ID */ }; 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}, { AFE_PORT_ID_PRIMARY_SPDIF_RX, AFE_CLOCK_SET_CLOCK_ID_PRI_SPDIF_OUTPUT_CORE}, { AFE_PORT_ID_PRIMARY_SPDIF_TX, AFE_CLOCK_SET_CLOCK_ID_PRI_SPDIF_INPUT_CORE}, { AFE_PORT_ID_SECONDARY_SPDIF_RX, AFE_CLOCK_SET_CLOCK_ID_SEC_SPDIF_OUTPUT_CORE}, { AFE_PORT_ID_SECONDARY_SPDIF_TX, AFE_CLOCK_SET_CLOCK_ID_SEC_SPDIF_INPUT_CORE}, { AFE_PORT_ID_PRIMARY_META_MI2S_RX, Q6AFE_LPASS_CLK_ID_PRI_MI2S_IBIT}, { AFE_PORT_ID_SECONDARY_META_MI2S_RX, Q6AFE_LPASS_CLK_ID_PRI_MI2S_IBIT}, }; static atomic_t afe_ports_mad_type[SLIMBUS_PORT_LAST - SLIMBUS_0_RX]; static unsigned long afe_configured_cmd; Loading Loading @@ -8307,6 +8344,156 @@ int afe_set_lpass_clock(u16 port_id, struct afe_clk_cfg *cfg) } EXPORT_SYMBOL(afe_set_lpass_clock); static int afe_get_port_idx(u16 port_id) { u16 afe_port = 0; int i = -EINVAL; pr_debug("%s: port id 0x%x\n", __func__, port_id); if ((port_id >= AFE_PORT_ID_TDM_PORT_RANGE_START) && (port_id <= AFE_PORT_ID_TDM_PORT_RANGE_END)) afe_port = port_id & 0xFFF0; else if ((port_id == AFE_PORT_ID_PRIMARY_SPDIF_RX) || (port_id == AFE_PORT_ID_PRIMARY_SPDIF_TX) || (port_id == AFE_PORT_ID_SECONDARY_SPDIF_RX) || (port_id == AFE_PORT_ID_SECONDARY_SPDIF_TX)) afe_port = port_id; else afe_port = port_id & 0xFFFE; for (i = 0; i < ARRAY_SIZE(clkinfo_per_port); i++) { if (afe_port == clkinfo_per_port[i].port_id) { pr_debug("%s: idx 0x%x port id 0x%x\n", __func__, i, afe_port); return i; } } pr_debug("%s: cannot get idx for port id 0x%x\n", __func__, afe_port); return -EINVAL; } static int afe_get_clk_id(u16 port_id) { 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); 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); return clk_id; } /** * afe_set_clk_id - Update clock id for AFE port * * @port_id: AFE port id * @clk_id: CLock ID * * Returns 0 on success, appropriate error code otherwise */ int afe_set_clk_id(u16 port_id, uint32_t clk_id) { 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); 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); return 0; } EXPORT_SYMBOL(afe_set_clk_id); /** * afe_set_pll_clk_drift - Set audio interface PLL clock drift * * @port_id: AFE port id * @set_clk_drift: clk drift to adjust PLL * @clk_reset: reset Interface clock to original value * * Returns 0 on success, appropriate error code otherwise */ int afe_set_pll_clk_drift(u16 port_id, int32_t set_clk_drift, uint32_t clk_reset) { struct afe_set_clk_drift clk_drift; struct param_hdr_v3 param_hdr; uint32_t clk_id; int index = 0, ret = 0; memset(¶m_hdr, 0, sizeof(param_hdr)); memset(&clk_drift, 0, sizeof(clk_drift)); index = q6audio_get_port_index(port_id); if (index < 0 || index >= AFE_MAX_PORTS) { pr_err("%s: index[%d] invalid!\n", __func__, index); return -EINVAL; } ret = afe_q6_interface_prepare(); if (ret != 0) { pr_err_ratelimited("%s: Q6 interface prepare failed %d\n", __func__, ret); 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", __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, clk_drift.clk_reset, port_id); mutex_lock(&this_afe.afe_clk_lock); param_hdr.module_id = AFE_MODULE_CLOCK_SET; param_hdr.instance_id = INSTANCE_ID_0; 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); mutex_unlock(&this_afe.afe_clk_lock); return ret; } EXPORT_SYMBOL(afe_set_pll_clk_drift); /** * afe_set_lpass_clk_cfg - Set AFE clk config * Loading Loading @@ -8393,6 +8580,10 @@ 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_debug("%s: afe_set_clk_id fail %d\n", __func__, ret); ret = afe_set_lpass_clk_cfg(index, cfg); if (ret) pr_err("%s: afe_set_lpass_clk_cfg_v2 failed %d\n", Loading include/dsp/apr_audio-v2.h +29 −0 Original line number Diff line number Diff line Loading @@ -12102,6 +12102,35 @@ 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; /* * Clock drift (in PPB) to be set. * @values * - need to get values from DSP team */ int32_t clk_drift; /* * Clock rest. * @values * - 1 -- Reset PLL with the original frequency * - 0 -- Adjust the clock with the clk drift value */ uint32_t clk_reset; } __packed; /* This param id is used to adjust audio interface PLL*/ #define AFE_PARAM_ID_CLOCK_ADJUST 0x000102C6 enum afe_lpass_digital_clk_src { Q6AFE_LPASS_DIGITAL_ROOT_INVALID, Q6AFE_LPASS_DIGITAL_ROOT_PRI_MI2S_OSR, Loading include/dsp/q6afe-v2.h +3 −0 Original line number Diff line number Diff line Loading @@ -488,6 +488,9 @@ void afe_register_wakeup_irq_callback( void (*afe_cb_wakeup_irq)(void *handle)); int afe_get_doa_tracking_mon(u16 port_id, struct doa_tracking_mon_param *doa_tracking_data); int afe_set_pll_clk_drift(u16 port_id, int32_t set_clk_drift, uint32_t clk_reset); int afe_set_clk_id(u16 port_id, uint32_t clk_id); enum { AFE_LPASS_CORE_HW_BLOCK_ID_NONE, Loading Loading
asoc/msm-pcm-routing-v2.c +47 −0 Original line number Diff line number Diff line Loading @@ -30180,6 +30180,50 @@ static const struct snd_kcontrol_new aptx_dec_license_controls[] = { msm_aptx_dec_license_control_put), }; static int msm_routing_get_pll_clk_drift(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { return 0; } static int msm_routing_put_pll_clk_drift(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { u16 port_id = 0; int32_t clk_drift = 0; uint32_t clk_reset = 0; int be_idx, ret = -EINVAL; be_idx = ucontrol->value.integer.value[0]; clk_drift = ucontrol->value.integer.value[1]; clk_reset = 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 (!msm_bedais[be_idx].active && !clk_reset) { pr_err("%s:BE is not active %d, cannot set clock drift\n", __func__, be_idx); return -EINVAL; } port_id = msm_bedais[be_idx].port_id; pr_debug("%s: clk drift %d be idx %d clk reset %d port id 0x%x\n", __func__, clk_drift, be_idx, clk_reset, port_id); ret = afe_set_pll_clk_drift(port_id, clk_drift, clk_reset); if (ret < 0) pr_err("%s: failed to set pll clk drift\n", __func__); return ret; } static const struct snd_kcontrol_new pll_clk_drift_controls[] = { SOC_SINGLE_MULTI_EXT("PLL config data", SND_SOC_NOPM, 0, 0xFFFFFFFF, 0, 128, msm_routing_get_pll_clk_drift, msm_routing_put_pll_clk_drift), }; static int msm_routing_put_port_chmap_mixer(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { Loading Loading @@ -30480,6 +30524,9 @@ static int msm_routing_probe(struct snd_soc_component *component) port_multi_channel_map_mixer_controls, ARRAY_SIZE(port_multi_channel_map_mixer_controls)); snd_soc_add_component_controls(component, pll_clk_drift_controls, ARRAY_SIZE(pll_clk_drift_controls)); return 0; }
asoc/qcs405.c +8 −0 Original line number Diff line number Diff line Loading @@ -6309,6 +6309,7 @@ static int msm_meta_mi2s_snd_startup(struct snd_pcm_substream *substream) unsigned int fmt = SND_SOC_DAIFMT_CBS_CFS; struct snd_soc_card *card = rtd->card; struct msm_asoc_mach_data *pdata = snd_soc_card_get_drvdata(card); u16 port_id = 0; dev_dbg(rtd->card->dev, "%s: substream = %s stream = %d, dai name %s, dai ID %d\n", Loading Loading @@ -6342,6 +6343,13 @@ static int msm_meta_mi2s_snd_startup(struct snd_pcm_substream *substream) meta_mi2s_intf_conf[index].clk_enable[i] = true; 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 (ret < 0) pr_err("%s: afe_set_clk_id fail %d\n", __func__, ret); ret = snd_soc_dai_set_fmt(cpu_dai, fmt); if (ret < 0) { pr_err("%s: set fmt cpu dai failed for META_MI2S (%d), err:%d\n", Loading
dsp/q6afe.c +191 −0 Original line number Diff line number Diff line Loading @@ -184,6 +184,43 @@ struct afe_ctl { uint32_t v_vali_flag; }; struct afe_clkinfo_per_port { u16 port_id; /* AFE port ID */ uint32_t clk_id; /* Clock ID */ }; 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}, { AFE_PORT_ID_PRIMARY_SPDIF_RX, AFE_CLOCK_SET_CLOCK_ID_PRI_SPDIF_OUTPUT_CORE}, { AFE_PORT_ID_PRIMARY_SPDIF_TX, AFE_CLOCK_SET_CLOCK_ID_PRI_SPDIF_INPUT_CORE}, { AFE_PORT_ID_SECONDARY_SPDIF_RX, AFE_CLOCK_SET_CLOCK_ID_SEC_SPDIF_OUTPUT_CORE}, { AFE_PORT_ID_SECONDARY_SPDIF_TX, AFE_CLOCK_SET_CLOCK_ID_SEC_SPDIF_INPUT_CORE}, { AFE_PORT_ID_PRIMARY_META_MI2S_RX, Q6AFE_LPASS_CLK_ID_PRI_MI2S_IBIT}, { AFE_PORT_ID_SECONDARY_META_MI2S_RX, Q6AFE_LPASS_CLK_ID_PRI_MI2S_IBIT}, }; static atomic_t afe_ports_mad_type[SLIMBUS_PORT_LAST - SLIMBUS_0_RX]; static unsigned long afe_configured_cmd; Loading Loading @@ -8307,6 +8344,156 @@ int afe_set_lpass_clock(u16 port_id, struct afe_clk_cfg *cfg) } EXPORT_SYMBOL(afe_set_lpass_clock); static int afe_get_port_idx(u16 port_id) { u16 afe_port = 0; int i = -EINVAL; pr_debug("%s: port id 0x%x\n", __func__, port_id); if ((port_id >= AFE_PORT_ID_TDM_PORT_RANGE_START) && (port_id <= AFE_PORT_ID_TDM_PORT_RANGE_END)) afe_port = port_id & 0xFFF0; else if ((port_id == AFE_PORT_ID_PRIMARY_SPDIF_RX) || (port_id == AFE_PORT_ID_PRIMARY_SPDIF_TX) || (port_id == AFE_PORT_ID_SECONDARY_SPDIF_RX) || (port_id == AFE_PORT_ID_SECONDARY_SPDIF_TX)) afe_port = port_id; else afe_port = port_id & 0xFFFE; for (i = 0; i < ARRAY_SIZE(clkinfo_per_port); i++) { if (afe_port == clkinfo_per_port[i].port_id) { pr_debug("%s: idx 0x%x port id 0x%x\n", __func__, i, afe_port); return i; } } pr_debug("%s: cannot get idx for port id 0x%x\n", __func__, afe_port); return -EINVAL; } static int afe_get_clk_id(u16 port_id) { 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); 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); return clk_id; } /** * afe_set_clk_id - Update clock id for AFE port * * @port_id: AFE port id * @clk_id: CLock ID * * Returns 0 on success, appropriate error code otherwise */ int afe_set_clk_id(u16 port_id, uint32_t clk_id) { 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); 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); return 0; } EXPORT_SYMBOL(afe_set_clk_id); /** * afe_set_pll_clk_drift - Set audio interface PLL clock drift * * @port_id: AFE port id * @set_clk_drift: clk drift to adjust PLL * @clk_reset: reset Interface clock to original value * * Returns 0 on success, appropriate error code otherwise */ int afe_set_pll_clk_drift(u16 port_id, int32_t set_clk_drift, uint32_t clk_reset) { struct afe_set_clk_drift clk_drift; struct param_hdr_v3 param_hdr; uint32_t clk_id; int index = 0, ret = 0; memset(¶m_hdr, 0, sizeof(param_hdr)); memset(&clk_drift, 0, sizeof(clk_drift)); index = q6audio_get_port_index(port_id); if (index < 0 || index >= AFE_MAX_PORTS) { pr_err("%s: index[%d] invalid!\n", __func__, index); return -EINVAL; } ret = afe_q6_interface_prepare(); if (ret != 0) { pr_err_ratelimited("%s: Q6 interface prepare failed %d\n", __func__, ret); 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", __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, clk_drift.clk_reset, port_id); mutex_lock(&this_afe.afe_clk_lock); param_hdr.module_id = AFE_MODULE_CLOCK_SET; param_hdr.instance_id = INSTANCE_ID_0; 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); mutex_unlock(&this_afe.afe_clk_lock); return ret; } EXPORT_SYMBOL(afe_set_pll_clk_drift); /** * afe_set_lpass_clk_cfg - Set AFE clk config * Loading Loading @@ -8393,6 +8580,10 @@ 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_debug("%s: afe_set_clk_id fail %d\n", __func__, ret); ret = afe_set_lpass_clk_cfg(index, cfg); if (ret) pr_err("%s: afe_set_lpass_clk_cfg_v2 failed %d\n", Loading
include/dsp/apr_audio-v2.h +29 −0 Original line number Diff line number Diff line Loading @@ -12102,6 +12102,35 @@ 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; /* * Clock drift (in PPB) to be set. * @values * - need to get values from DSP team */ int32_t clk_drift; /* * Clock rest. * @values * - 1 -- Reset PLL with the original frequency * - 0 -- Adjust the clock with the clk drift value */ uint32_t clk_reset; } __packed; /* This param id is used to adjust audio interface PLL*/ #define AFE_PARAM_ID_CLOCK_ADJUST 0x000102C6 enum afe_lpass_digital_clk_src { Q6AFE_LPASS_DIGITAL_ROOT_INVALID, Q6AFE_LPASS_DIGITAL_ROOT_PRI_MI2S_OSR, Loading
include/dsp/q6afe-v2.h +3 −0 Original line number Diff line number Diff line Loading @@ -488,6 +488,9 @@ void afe_register_wakeup_irq_callback( void (*afe_cb_wakeup_irq)(void *handle)); int afe_get_doa_tracking_mon(u16 port_id, struct doa_tracking_mon_param *doa_tracking_data); int afe_set_pll_clk_drift(u16 port_id, int32_t set_clk_drift, uint32_t clk_reset); int afe_set_clk_id(u16 port_id, uint32_t clk_id); enum { AFE_LPASS_CORE_HW_BLOCK_ID_NONE, Loading