Loading include/sound/apr_audio-v2.h +68 −0 Original line number Diff line number Diff line Loading @@ -8353,6 +8353,74 @@ struct asm_aptx_dec_fmt_blk_v2 { */ } __packed; /* Q6Core Specific */ #define AVCS_CMD_GET_FWK_VERSION (0x0001292C) #define AVCS_CMDRSP_GET_FWK_VERSION (0x0001292D) #define AVCS_SERVICE_ID_ALL (0xFFFFFFFF) #define AVCS_SERVICE_ID_AFE (0x4) struct avcs_get_fwk_version { /* * Indicates the major version of the AVS build. * This value is incremented on chipset family boundaries. */ uint32_t build_major_version; /* * Minor version of the AVS build. * This value represents the mainline to which the AVS build belongs. */ uint32_t build_minor_version; /* Indicates the AVS branch version to which the image belongs. */ uint32_t build_branch_version; /* Indicates the AVS sub-branch or customer product line information. */ uint32_t build_subbranch_version; /* Number of supported AVS services in the current build. */ uint32_t num_services; }; struct avs_svc_api_info { /* * APRV2 service IDs for the individual static services. * * @values * - APRV2_IDS_SERVICE_ID_ADSP_CORE_V * - APRV2_IDS_SERVICE_ID_ADSP_AFE_V * - APRV2_IDS_SERVICE_ID_ADSP_ASM_V * - APRV2_IDS_SERVICE_ID_ADSP_ADM_V * - APRV2_IDS_SERVICE_ID_ADSP_MVM_V * - APRV2_IDS_SERVICE_ID_ADSP_CVS_V * - APRV2_IDS_SERVICE_ID_ADSP_CVP_V * - APRV2_IDS_SERVICE_ID_ADSP_LSM_V */ uint32_t service_id; /* * Indicates the API version of the service. * * Each new API update that warrants a change on the HLOS side triggers * an increment in the version. */ uint32_t api_version; /* * Indicates the API increments on a sub-branch (not on the mainline). * * API branch version numbers can increment independently on different * sub-branches. */ uint32_t api_branch_version; }; struct avcs_fwk_ver_info { struct avcs_get_fwk_version avcs_build; struct avs_svc_api_info services[0]; }; /* LSM Specific */ #define VW_FEAT_DIM (39) Loading include/sound/q6afe-v2.h +6 −0 Original line number Diff line number Diff line Loading @@ -189,6 +189,11 @@ enum afe_cal_mode { AFE_CAL_MODE_NONE, }; enum lpass_clk_ver { LPASS_CLK_VER_1, LPASS_CLK_VER_2, }; struct afe_audio_buffer { dma_addr_t phys; void *data; Loading Loading @@ -234,6 +239,7 @@ struct aanc_data { int afe_open(u16 port_id, union afe_port_config *afe_config, int rate); int afe_close(int port_id); enum lpass_clk_ver afe_get_lpass_clk_ver(void); int afe_loopback(u16 enable, u16 rx_port, u16 tx_port); int afe_sidetone(u16 tx_port_id, u16 rx_port_id, u16 enable, uint16_t gain); int afe_loopback_gain(u16 port_id, u16 volume); Loading include/sound/q6core.h +5 −1 Original line number Diff line number Diff line /* Copyright (c) 2012-2016, The Linux Foundation. All rights reserved. /* Copyright (c) 2012-2017, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and Loading @@ -13,6 +13,7 @@ #ifndef __Q6CORE_H__ #define __Q6CORE_H__ #include <linux/qdsp6v2/apr.h> #include <sound/apr_audio-v2.h> Loading @@ -21,6 +22,9 @@ bool q6core_is_adsp_ready(void); int q6core_get_avcs_fwk_ver_info(uint32_t service_id, struct avcs_fwk_ver_info *ver_info); #define ADSP_CMD_SET_DTS_EAGLE_DATA_ID 0x00012919 #define DTS_EAGLE_LICENSE_ID 0x00028346 struct adsp_dts_eagle { Loading sound/soc/codecs/audio-ext-clk.c +111 −67 Original line number Diff line number Diff line Loading @@ -31,6 +31,11 @@ enum clk_mux { LPASS_MCLK2, }; enum clk_enablement { CLK_DISABLE = 0, CLK_ENABLE, }; struct pinctrl_info { struct pinctrl *pinctrl; struct pinctrl_state *sleep; Loading Loading @@ -169,44 +174,56 @@ static void audio_ext_clk2_unprepare(struct clk *clk) pr_err("%s: failed to reset clock, ret = %d\n", __func__, ret); } static int audio_ext_lpass_mclk_prepare(struct clk *clk) static int audio_ext_set_lpass_mclk_v1(struct clk *clk, enum clk_enablement enable) { struct audio_ext_lpass_mclk *audio_lpass_mclk; struct pinctrl_info *pnctrl_info; struct afe_clk_cfg *lpass_clk = NULL; int ret, val = 0; struct pinctrl_state *pnctrl_state; struct afe_clk_cfg lpass_clks = lpass_default; int val = 0; int ret; audio_lpass_mclk = container_of(clk, struct audio_ext_lpass_mclk, c); pnctrl_info = &audio_lpass_mclk->pnctrl_info; pr_debug("%s: Setting clock using v1, enable(%d)\n", __func__, enable); lpass_clk = kzalloc(sizeof(struct afe_clk_cfg), GFP_KERNEL); if (!lpass_clk) return -ENOMEM; audio_lpass_mclk = container_of(clk, struct audio_ext_lpass_mclk, c); if (audio_lpass_mclk == NULL) { pr_err("%s: audio_lpass_mclk is NULL\n", __func__); ret = -EINVAL; goto done; } if (pnctrl_info->pinctrl) { ret = pinctrl_select_state(pnctrl_info->pinctrl, pnctrl_info->active); pnctrl_info = &audio_lpass_mclk->pnctrl_info; if (pnctrl_info && pnctrl_info->pinctrl) { pnctrl_state = enable ? pnctrl_info->active : pnctrl_info->sleep; ret = pinctrl_select_state(pnctrl_info->pinctrl, pnctrl_state); if (ret) { pr_err("%s: active state select failed with %d\n", __func__, ret); pr_err("%s: pinctrl state selection for %s failed with %d\n", __func__, (pnctrl_state == pnctrl_info->active) ? "active" : "sleep", ret); ret = -EIO; goto done; } } if (!audio_lpass_mclk->lpass_clock) { memcpy(lpass_clk, &lpass_default, sizeof(struct afe_clk_cfg)); lpass_clk->clk_val2 = Q6AFE_LPASS_OSR_CLK_12_P288_MHZ; lpass_clk->clk_set_mode = Q6AFE_LPASS_MODE_CLK2_VALID; lpass_clks.clk_val2 = enable ? Q6AFE_LPASS_OSR_CLK_12_P288_MHZ : 0; lpass_clks.clk_set_mode = Q6AFE_LPASS_MODE_CLK2_VALID; ret = afe_set_lpass_clock(AFE_PORT_ID_SECONDARY_MI2S_RX, lpass_clk); &lpass_clks); if (ret < 0) { pr_err("%s afe_set_lpass_clock failed, ret = %d\n", pr_err("%s: afe_set_lpass_clock failed with ret = %d\n", __func__, ret); kfree(lpass_clk); return -EINVAL; ret = -EINVAL; goto done; } } else { if (audio_lpass_mclk->lpass_csr_gpio_mux_spkrctl_vaddr) { if (audio_lpass_mclk->lpass_csr_gpio_mux_spkrctl_vaddr && enable) { val = ioread32(audio_lpass_mclk-> lpass_csr_gpio_mux_spkrctl_vaddr); val = val | 0x00000002; Loading @@ -214,65 +231,92 @@ static int audio_ext_lpass_mclk_prepare(struct clk *clk) lpass_csr_gpio_mux_spkrctl_vaddr); } digital_cdc_core_clk.enable = 1; digital_cdc_core_clk.enable = enable; ret = afe_set_lpass_clock_v2(AFE_PORT_ID_PRIMARY_MI2S_RX, &digital_cdc_core_clk); if (ret < 0) { pr_err("%s afe_set_digital_codec_core_clock failed\n", __func__); kfree(lpass_clk); return ret; pr_err("%s: afe_set_digital_codec_core_clock failed with ret %d\n", __func__, ret); goto done; } } ret = 0; done: kfree(lpass_clk); return 0; return ret; } static void audio_ext_lpass_mclk_unprepare(struct clk *clk) static int audio_ext_set_lpass_mclk_v2(enum clk_enablement enable) { struct audio_ext_lpass_mclk *audio_lpass_mclk; struct pinctrl_info *pnctrl_info; struct afe_clk_cfg *lpass_clk = NULL; int ret; struct afe_clk_set m_clk = lpass_default2; struct afe_clk_set ibit_clk = lpass_default2; int ret = 0; audio_lpass_mclk = container_of(clk, struct audio_ext_lpass_mclk, c); pnctrl_info = &audio_lpass_mclk->pnctrl_info; pr_debug("%s: Setting clock using v2, enable(%d)\n", __func__, enable); lpass_clk = kzalloc(sizeof(struct afe_clk_cfg), GFP_KERNEL); if (!lpass_clk) return; /* Set both mclk and ibit clocks when using LPASS_CLK_VER_2 */ m_clk.clk_id = Q6AFE_LPASS_CLK_ID_MCLK_3; m_clk.enable = enable; ret = afe_set_lpass_clock_v2(AFE_PORT_ID_PRIMARY_MI2S_RX, &m_clk); if (ret < 0) { pr_err("%s: afe_set_lpass_clock_v2 failed for mclk_3 with ret %d\n", __func__, ret); goto done; } if (pnctrl_info->pinctrl) { ret = pinctrl_select_state(pnctrl_info->pinctrl, pnctrl_info->sleep); if (ret) { pr_err("%s: active state select failed with %d\n", ibit_clk.clk_id = Q6AFE_LPASS_CLK_ID_PRI_MI2S_IBIT; ibit_clk.clk_freq_in_hz = Q6AFE_LPASS_IBIT_CLK_1_P536_MHZ; ibit_clk.enable = enable; ret = afe_set_lpass_clock_v2(AFE_PORT_ID_PRIMARY_MI2S_RX, &ibit_clk); if (ret < 0) { pr_err("%s: afe_set_lpass_clock_v2 failed for ibit with ret %d\n", __func__, ret); ret = -EIO; goto err; goto err_ibit_clk_set; } ret = 0; done: return ret; err_ibit_clk_set: m_clk.enable = CLK_DISABLE; if (afe_set_lpass_clock_v2(AFE_PORT_ID_PRIMARY_MI2S_RX, &m_clk)) { pr_err("%s: afe_set_lpass_clock_v2 failed to disable mclk_3\n", __func__); } return ret; } if (!audio_lpass_mclk->lpass_clock) { memcpy(lpass_clk, &lpass_default, sizeof(struct afe_clk_cfg)); lpass_clk->clk_val2 = 0; lpass_clk->clk_set_mode = Q6AFE_LPASS_MODE_CLK2_VALID; ret = afe_set_lpass_clock(AFE_PORT_ID_SECONDARY_MI2S_RX, lpass_clk); if (ret < 0) pr_err("%s: afe_set_lpass_clock failed, ret = %d\n", __func__, ret); } else { digital_cdc_core_clk.enable = 0; ret = afe_set_lpass_clock_v2(AFE_PORT_ID_PRIMARY_MI2S_RX, &digital_cdc_core_clk); if (ret < 0) pr_err("%s: afe_set_digital_codec_core_clock failed, ret = %d\n", __func__, ret); static int audio_ext_lpass_mclk_prepare(struct clk *clk) { enum lpass_clk_ver lpass_clk_ver; int ret; lpass_clk_ver = afe_get_lpass_clk_ver(); if (lpass_clk_ver >= LPASS_CLK_VER_2) ret = audio_ext_set_lpass_mclk_v2(CLK_ENABLE); else ret = audio_ext_set_lpass_mclk_v1(clk, CLK_ENABLE); return ret; } err: kfree(lpass_clk); static void audio_ext_lpass_mclk_unprepare(struct clk *clk) { enum lpass_clk_ver lpass_clk_ver; int ret; lpass_clk_ver = afe_get_lpass_clk_ver(); if (lpass_clk_ver >= LPASS_CLK_VER_2) ret = audio_ext_set_lpass_mclk_v2(CLK_DISABLE); else ret = audio_ext_set_lpass_mclk_v1(clk, CLK_DISABLE); pr_debug("%s: Unprepare of mclk returned %d\n", __func__, ret); } static int audio_ext_lpass_mclk2_prepare(struct clk *clk) Loading sound/soc/msm/qdsp6v2/q6afe.c +34 −0 Original line number Diff line number Diff line Loading @@ -23,6 +23,7 @@ #include <sound/apr_audio-v2.h> #include <sound/q6afe-v2.h> #include <sound/q6audio-v2.h> #include <sound/q6core.h> #include "msm-pcm-routing-v2.h" #include <sound/audio_cal_utils.h> #include <sound/adsp_err.h> Loading Loading @@ -5130,6 +5131,39 @@ int afe_set_lpass_clock_v2(u16 port_id, struct afe_clk_set *cfg) return ret; } static int afe_get_service_ver(void) { int ret; ret = q6core_get_avcs_fwk_ver_info(AVCS_SERVICE_ID_AFE, NULL); if (ret) pr_err("%s: failed to get version info for AFE service %d\n", __func__, AVCS_SERVICE_ID_AFE); return ret; } enum lpass_clk_ver afe_get_lpass_clk_ver(void) { enum lpass_clk_ver lpass_clk_ver; /* * Use different APIs to set the LPASS clock depending on the AFE * version. On success afe_get_service_ver returns 0 signyfing the * latest AFE version is supported. Use LPASS clock version 2 if the * latest AFE version is supported, otherwise use LPASS clock version 1. */ lpass_clk_ver = (afe_get_service_ver() == 0) ? LPASS_CLK_VER_2 : LPASS_CLK_VER_1; pr_debug("%s: returning %s\n", __func__, (lpass_clk_ver == LPASS_CLK_VER_2) ? "LPASS_CLK_VER_2" : "LPASS_CLK_VER_1"); return lpass_clk_ver; } EXPORT_SYMBOL(afe_get_lpass_clk_ver); int afe_set_lpass_internal_digital_codec_clock(u16 port_id, struct afe_digital_clk_cfg *cfg) { Loading Loading
include/sound/apr_audio-v2.h +68 −0 Original line number Diff line number Diff line Loading @@ -8353,6 +8353,74 @@ struct asm_aptx_dec_fmt_blk_v2 { */ } __packed; /* Q6Core Specific */ #define AVCS_CMD_GET_FWK_VERSION (0x0001292C) #define AVCS_CMDRSP_GET_FWK_VERSION (0x0001292D) #define AVCS_SERVICE_ID_ALL (0xFFFFFFFF) #define AVCS_SERVICE_ID_AFE (0x4) struct avcs_get_fwk_version { /* * Indicates the major version of the AVS build. * This value is incremented on chipset family boundaries. */ uint32_t build_major_version; /* * Minor version of the AVS build. * This value represents the mainline to which the AVS build belongs. */ uint32_t build_minor_version; /* Indicates the AVS branch version to which the image belongs. */ uint32_t build_branch_version; /* Indicates the AVS sub-branch or customer product line information. */ uint32_t build_subbranch_version; /* Number of supported AVS services in the current build. */ uint32_t num_services; }; struct avs_svc_api_info { /* * APRV2 service IDs for the individual static services. * * @values * - APRV2_IDS_SERVICE_ID_ADSP_CORE_V * - APRV2_IDS_SERVICE_ID_ADSP_AFE_V * - APRV2_IDS_SERVICE_ID_ADSP_ASM_V * - APRV2_IDS_SERVICE_ID_ADSP_ADM_V * - APRV2_IDS_SERVICE_ID_ADSP_MVM_V * - APRV2_IDS_SERVICE_ID_ADSP_CVS_V * - APRV2_IDS_SERVICE_ID_ADSP_CVP_V * - APRV2_IDS_SERVICE_ID_ADSP_LSM_V */ uint32_t service_id; /* * Indicates the API version of the service. * * Each new API update that warrants a change on the HLOS side triggers * an increment in the version. */ uint32_t api_version; /* * Indicates the API increments on a sub-branch (not on the mainline). * * API branch version numbers can increment independently on different * sub-branches. */ uint32_t api_branch_version; }; struct avcs_fwk_ver_info { struct avcs_get_fwk_version avcs_build; struct avs_svc_api_info services[0]; }; /* LSM Specific */ #define VW_FEAT_DIM (39) Loading
include/sound/q6afe-v2.h +6 −0 Original line number Diff line number Diff line Loading @@ -189,6 +189,11 @@ enum afe_cal_mode { AFE_CAL_MODE_NONE, }; enum lpass_clk_ver { LPASS_CLK_VER_1, LPASS_CLK_VER_2, }; struct afe_audio_buffer { dma_addr_t phys; void *data; Loading Loading @@ -234,6 +239,7 @@ struct aanc_data { int afe_open(u16 port_id, union afe_port_config *afe_config, int rate); int afe_close(int port_id); enum lpass_clk_ver afe_get_lpass_clk_ver(void); int afe_loopback(u16 enable, u16 rx_port, u16 tx_port); int afe_sidetone(u16 tx_port_id, u16 rx_port_id, u16 enable, uint16_t gain); int afe_loopback_gain(u16 port_id, u16 volume); Loading
include/sound/q6core.h +5 −1 Original line number Diff line number Diff line /* Copyright (c) 2012-2016, The Linux Foundation. All rights reserved. /* Copyright (c) 2012-2017, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and Loading @@ -13,6 +13,7 @@ #ifndef __Q6CORE_H__ #define __Q6CORE_H__ #include <linux/qdsp6v2/apr.h> #include <sound/apr_audio-v2.h> Loading @@ -21,6 +22,9 @@ bool q6core_is_adsp_ready(void); int q6core_get_avcs_fwk_ver_info(uint32_t service_id, struct avcs_fwk_ver_info *ver_info); #define ADSP_CMD_SET_DTS_EAGLE_DATA_ID 0x00012919 #define DTS_EAGLE_LICENSE_ID 0x00028346 struct adsp_dts_eagle { Loading
sound/soc/codecs/audio-ext-clk.c +111 −67 Original line number Diff line number Diff line Loading @@ -31,6 +31,11 @@ enum clk_mux { LPASS_MCLK2, }; enum clk_enablement { CLK_DISABLE = 0, CLK_ENABLE, }; struct pinctrl_info { struct pinctrl *pinctrl; struct pinctrl_state *sleep; Loading Loading @@ -169,44 +174,56 @@ static void audio_ext_clk2_unprepare(struct clk *clk) pr_err("%s: failed to reset clock, ret = %d\n", __func__, ret); } static int audio_ext_lpass_mclk_prepare(struct clk *clk) static int audio_ext_set_lpass_mclk_v1(struct clk *clk, enum clk_enablement enable) { struct audio_ext_lpass_mclk *audio_lpass_mclk; struct pinctrl_info *pnctrl_info; struct afe_clk_cfg *lpass_clk = NULL; int ret, val = 0; struct pinctrl_state *pnctrl_state; struct afe_clk_cfg lpass_clks = lpass_default; int val = 0; int ret; audio_lpass_mclk = container_of(clk, struct audio_ext_lpass_mclk, c); pnctrl_info = &audio_lpass_mclk->pnctrl_info; pr_debug("%s: Setting clock using v1, enable(%d)\n", __func__, enable); lpass_clk = kzalloc(sizeof(struct afe_clk_cfg), GFP_KERNEL); if (!lpass_clk) return -ENOMEM; audio_lpass_mclk = container_of(clk, struct audio_ext_lpass_mclk, c); if (audio_lpass_mclk == NULL) { pr_err("%s: audio_lpass_mclk is NULL\n", __func__); ret = -EINVAL; goto done; } if (pnctrl_info->pinctrl) { ret = pinctrl_select_state(pnctrl_info->pinctrl, pnctrl_info->active); pnctrl_info = &audio_lpass_mclk->pnctrl_info; if (pnctrl_info && pnctrl_info->pinctrl) { pnctrl_state = enable ? pnctrl_info->active : pnctrl_info->sleep; ret = pinctrl_select_state(pnctrl_info->pinctrl, pnctrl_state); if (ret) { pr_err("%s: active state select failed with %d\n", __func__, ret); pr_err("%s: pinctrl state selection for %s failed with %d\n", __func__, (pnctrl_state == pnctrl_info->active) ? "active" : "sleep", ret); ret = -EIO; goto done; } } if (!audio_lpass_mclk->lpass_clock) { memcpy(lpass_clk, &lpass_default, sizeof(struct afe_clk_cfg)); lpass_clk->clk_val2 = Q6AFE_LPASS_OSR_CLK_12_P288_MHZ; lpass_clk->clk_set_mode = Q6AFE_LPASS_MODE_CLK2_VALID; lpass_clks.clk_val2 = enable ? Q6AFE_LPASS_OSR_CLK_12_P288_MHZ : 0; lpass_clks.clk_set_mode = Q6AFE_LPASS_MODE_CLK2_VALID; ret = afe_set_lpass_clock(AFE_PORT_ID_SECONDARY_MI2S_RX, lpass_clk); &lpass_clks); if (ret < 0) { pr_err("%s afe_set_lpass_clock failed, ret = %d\n", pr_err("%s: afe_set_lpass_clock failed with ret = %d\n", __func__, ret); kfree(lpass_clk); return -EINVAL; ret = -EINVAL; goto done; } } else { if (audio_lpass_mclk->lpass_csr_gpio_mux_spkrctl_vaddr) { if (audio_lpass_mclk->lpass_csr_gpio_mux_spkrctl_vaddr && enable) { val = ioread32(audio_lpass_mclk-> lpass_csr_gpio_mux_spkrctl_vaddr); val = val | 0x00000002; Loading @@ -214,65 +231,92 @@ static int audio_ext_lpass_mclk_prepare(struct clk *clk) lpass_csr_gpio_mux_spkrctl_vaddr); } digital_cdc_core_clk.enable = 1; digital_cdc_core_clk.enable = enable; ret = afe_set_lpass_clock_v2(AFE_PORT_ID_PRIMARY_MI2S_RX, &digital_cdc_core_clk); if (ret < 0) { pr_err("%s afe_set_digital_codec_core_clock failed\n", __func__); kfree(lpass_clk); return ret; pr_err("%s: afe_set_digital_codec_core_clock failed with ret %d\n", __func__, ret); goto done; } } ret = 0; done: kfree(lpass_clk); return 0; return ret; } static void audio_ext_lpass_mclk_unprepare(struct clk *clk) static int audio_ext_set_lpass_mclk_v2(enum clk_enablement enable) { struct audio_ext_lpass_mclk *audio_lpass_mclk; struct pinctrl_info *pnctrl_info; struct afe_clk_cfg *lpass_clk = NULL; int ret; struct afe_clk_set m_clk = lpass_default2; struct afe_clk_set ibit_clk = lpass_default2; int ret = 0; audio_lpass_mclk = container_of(clk, struct audio_ext_lpass_mclk, c); pnctrl_info = &audio_lpass_mclk->pnctrl_info; pr_debug("%s: Setting clock using v2, enable(%d)\n", __func__, enable); lpass_clk = kzalloc(sizeof(struct afe_clk_cfg), GFP_KERNEL); if (!lpass_clk) return; /* Set both mclk and ibit clocks when using LPASS_CLK_VER_2 */ m_clk.clk_id = Q6AFE_LPASS_CLK_ID_MCLK_3; m_clk.enable = enable; ret = afe_set_lpass_clock_v2(AFE_PORT_ID_PRIMARY_MI2S_RX, &m_clk); if (ret < 0) { pr_err("%s: afe_set_lpass_clock_v2 failed for mclk_3 with ret %d\n", __func__, ret); goto done; } if (pnctrl_info->pinctrl) { ret = pinctrl_select_state(pnctrl_info->pinctrl, pnctrl_info->sleep); if (ret) { pr_err("%s: active state select failed with %d\n", ibit_clk.clk_id = Q6AFE_LPASS_CLK_ID_PRI_MI2S_IBIT; ibit_clk.clk_freq_in_hz = Q6AFE_LPASS_IBIT_CLK_1_P536_MHZ; ibit_clk.enable = enable; ret = afe_set_lpass_clock_v2(AFE_PORT_ID_PRIMARY_MI2S_RX, &ibit_clk); if (ret < 0) { pr_err("%s: afe_set_lpass_clock_v2 failed for ibit with ret %d\n", __func__, ret); ret = -EIO; goto err; goto err_ibit_clk_set; } ret = 0; done: return ret; err_ibit_clk_set: m_clk.enable = CLK_DISABLE; if (afe_set_lpass_clock_v2(AFE_PORT_ID_PRIMARY_MI2S_RX, &m_clk)) { pr_err("%s: afe_set_lpass_clock_v2 failed to disable mclk_3\n", __func__); } return ret; } if (!audio_lpass_mclk->lpass_clock) { memcpy(lpass_clk, &lpass_default, sizeof(struct afe_clk_cfg)); lpass_clk->clk_val2 = 0; lpass_clk->clk_set_mode = Q6AFE_LPASS_MODE_CLK2_VALID; ret = afe_set_lpass_clock(AFE_PORT_ID_SECONDARY_MI2S_RX, lpass_clk); if (ret < 0) pr_err("%s: afe_set_lpass_clock failed, ret = %d\n", __func__, ret); } else { digital_cdc_core_clk.enable = 0; ret = afe_set_lpass_clock_v2(AFE_PORT_ID_PRIMARY_MI2S_RX, &digital_cdc_core_clk); if (ret < 0) pr_err("%s: afe_set_digital_codec_core_clock failed, ret = %d\n", __func__, ret); static int audio_ext_lpass_mclk_prepare(struct clk *clk) { enum lpass_clk_ver lpass_clk_ver; int ret; lpass_clk_ver = afe_get_lpass_clk_ver(); if (lpass_clk_ver >= LPASS_CLK_VER_2) ret = audio_ext_set_lpass_mclk_v2(CLK_ENABLE); else ret = audio_ext_set_lpass_mclk_v1(clk, CLK_ENABLE); return ret; } err: kfree(lpass_clk); static void audio_ext_lpass_mclk_unprepare(struct clk *clk) { enum lpass_clk_ver lpass_clk_ver; int ret; lpass_clk_ver = afe_get_lpass_clk_ver(); if (lpass_clk_ver >= LPASS_CLK_VER_2) ret = audio_ext_set_lpass_mclk_v2(CLK_DISABLE); else ret = audio_ext_set_lpass_mclk_v1(clk, CLK_DISABLE); pr_debug("%s: Unprepare of mclk returned %d\n", __func__, ret); } static int audio_ext_lpass_mclk2_prepare(struct clk *clk) Loading
sound/soc/msm/qdsp6v2/q6afe.c +34 −0 Original line number Diff line number Diff line Loading @@ -23,6 +23,7 @@ #include <sound/apr_audio-v2.h> #include <sound/q6afe-v2.h> #include <sound/q6audio-v2.h> #include <sound/q6core.h> #include "msm-pcm-routing-v2.h" #include <sound/audio_cal_utils.h> #include <sound/adsp_err.h> Loading Loading @@ -5130,6 +5131,39 @@ int afe_set_lpass_clock_v2(u16 port_id, struct afe_clk_set *cfg) return ret; } static int afe_get_service_ver(void) { int ret; ret = q6core_get_avcs_fwk_ver_info(AVCS_SERVICE_ID_AFE, NULL); if (ret) pr_err("%s: failed to get version info for AFE service %d\n", __func__, AVCS_SERVICE_ID_AFE); return ret; } enum lpass_clk_ver afe_get_lpass_clk_ver(void) { enum lpass_clk_ver lpass_clk_ver; /* * Use different APIs to set the LPASS clock depending on the AFE * version. On success afe_get_service_ver returns 0 signyfing the * latest AFE version is supported. Use LPASS clock version 2 if the * latest AFE version is supported, otherwise use LPASS clock version 1. */ lpass_clk_ver = (afe_get_service_ver() == 0) ? LPASS_CLK_VER_2 : LPASS_CLK_VER_1; pr_debug("%s: returning %s\n", __func__, (lpass_clk_ver == LPASS_CLK_VER_2) ? "LPASS_CLK_VER_2" : "LPASS_CLK_VER_1"); return lpass_clk_ver; } EXPORT_SYMBOL(afe_get_lpass_clk_ver); int afe_set_lpass_internal_digital_codec_clock(u16 port_id, struct afe_digital_clk_cfg *cfg) { Loading