diff --git a/asoc/codecs/audio-ext-clk-up.c b/asoc/codecs/audio-ext-clk-up.c index b6cb2f6b4c..ba72fd8f61 100644 --- a/asoc/codecs/audio-ext-clk-up.c +++ b/asoc/codecs/audio-ext-clk-up.c @@ -21,6 +21,7 @@ #include #include #include +#include #include "audio-ext-clk-up.h" enum { @@ -33,6 +34,7 @@ enum { AUDIO_EXT_CLK_LPASS5, AUDIO_EXT_CLK_LPASS6, AUDIO_EXT_CLK_LPASS7, + AUDIO_EXT_CLK_LPASS_NPA_RSC_ISLAND, AUDIO_EXT_CLK_LPASS_MAX, AUDIO_EXT_CLK_MAX = AUDIO_EXT_CLK_LPASS_MAX, }; @@ -55,6 +57,7 @@ struct audio_ext_clk_priv { struct afe_clk_set clk_cfg; struct audio_ext_clk audio_clk; const char *clk_name; + uint32_t npa_rsc_client_handle; }; static inline struct audio_ext_clk_priv *to_audio_clk(struct clk_hw *hw) @@ -141,12 +144,58 @@ static u8 audio_ext_clk_get_parent(struct clk_hw *hw) return 0; } +static int lpass_npa_rsc_prepare(struct clk_hw *hw) +{ + struct audio_ext_clk_priv *clk_priv = to_audio_clk(hw); + int ret; + + if ((clk_priv->clk_src >= AUDIO_EXT_CLK_LPASS_NPA_RSC_ISLAND) && + (clk_priv->clk_src < AUDIO_EXT_CLK_LPASS_MAX)) { + if (q6core_get_avcs_api_version_per_service( + APRV2_IDS_SERVICE_ID_ADSP_CORE_V) >= AVCS_API_VERSION_V4) { + ret = q6core_request_island_transition( + clk_priv->npa_rsc_client_handle, false); + if (ret < 0) { + pr_err("%s q6core_request_island_transition failed %d\n", + __func__, ret); + return ret; + } + } + } + + return 0; +} + +static void lpass_npa_rsc_unprepare(struct clk_hw *hw) +{ + struct audio_ext_clk_priv *clk_priv = to_audio_clk(hw); + int ret = 0; + + if ((clk_priv->clk_src >= AUDIO_EXT_CLK_LPASS_NPA_RSC_ISLAND) && + (clk_priv->clk_src < AUDIO_EXT_CLK_LPASS_MAX)) { + if (q6core_get_avcs_api_version_per_service( + APRV2_IDS_SERVICE_ID_ADSP_CORE_V) >= AVCS_API_VERSION_V4) { + ret = q6core_request_island_transition( + clk_priv->npa_rsc_client_handle, true); + if (ret < 0) { + pr_err("%s q6core_request_island_transition failed %d\n", + __func__, ret); + } + } + } +} + static const struct clk_ops audio_ext_clk_ops = { .prepare = audio_ext_clk_prepare, .unprepare = audio_ext_clk_unprepare, .get_parent = audio_ext_clk_get_parent, }; +static const struct clk_ops lpass_npa_rsc_ops = { + .prepare = lpass_npa_rsc_prepare, + .unprepare = lpass_npa_rsc_unprepare, +}; + static const char * const audio_ext_pmi_div_clk[] = { "qpnp_clkdiv_1", "pms405_div_clk1", @@ -274,6 +323,15 @@ static struct audio_ext_clk audio_clk_array[] = { }, }, }, + { + .pnctrl_info = {NULL}, + .fact = { + .hw.init = &(struct clk_init_data){ + .name = "lpass_npa_rsc_island_clk", + .ops = &lpass_npa_rsc_ops, + }, + }, + }, }; static int audio_get_pinctrl(struct platform_device *pdev) @@ -476,11 +534,34 @@ static int audio_ref_clk_probe(struct platform_device *pdev) return ret; } + if (clk_priv->clk_src == AUDIO_EXT_CLK_LPASS_NPA_RSC_ISLAND) { + if (q6core_get_avcs_api_version_per_service( + APRV2_IDS_SERVICE_ID_ADSP_CORE_V) >= AVCS_API_VERSION_V4) { + ret = q6core_create_lpass_npa_client( + AVCS_SLEEP_NODE_ISLAND_TRANSITION_RESOURCE_ID, + "lpass_npa_rsc_mgr", + &clk_priv->npa_rsc_client_handle); + if (ret) { + dev_err(&pdev->dev, "%s: q6core_create_lpass_npa_client is failed %d\n", + __func__, ret); + audio_put_pinctrl(pdev); + return ret; + } + } + } return 0; } static int audio_ref_clk_remove(struct platform_device *pdev) { + struct audio_ext_clk_priv *clk_priv = platform_get_drvdata(pdev); + + if (clk_priv->clk_src == AUDIO_EXT_CLK_LPASS_NPA_RSC_ISLAND) { + if (q6core_get_avcs_api_version_per_service( + APRV2_IDS_SERVICE_ID_ADSP_CORE_V) >= AVCS_API_VERSION_V4) + q6core_destroy_lpass_npa_client( + clk_priv->npa_rsc_client_handle); + } audio_put_pinctrl(pdev); return 0;