From 8fc795775641339c6faafba0ff543f9eecfa4fbd Mon Sep 17 00:00:00 2001 From: Vignesh Kulothungan Date: Fri, 1 Nov 2019 18:21:11 -0700 Subject: [PATCH] ASoC: add hw_core voting via PRM module Change-Id: Ifa070caa6e5ff0263d0d471e5f0d7e7b09a41f0d Signed-off-by: Taha Azzaoui --- asoc/codecs/audio-ext-clk-up.c | 49 +++++++++++++++++++--------- dsp/audio_prm.c | 59 +++++++++++++++++++++++++++++++++- include/dsp/audio_prm.h | 15 +++++++++ 3 files changed, 107 insertions(+), 16 deletions(-) diff --git a/asoc/codecs/audio-ext-clk-up.c b/asoc/codecs/audio-ext-clk-up.c index 60cc971fab..b4e6d1555d 100644 --- a/asoc/codecs/audio-ext-clk-up.c +++ b/asoc/codecs/audio-ext-clk-up.c @@ -160,16 +160,19 @@ static u8 audio_ext_clk_get_parent(struct clk_hw *hw) static int lpass_hw_vote_prepare(struct clk_hw *hw) { -#if 0 - struct audio_ext_clk_priv *clk_priv = to_audio_clk(hw); - int ret; + struct audio_ext_clk_priv *clk_priv = to_audio_clk(hw); + int ret; if (clk_priv->clk_src == AUDIO_EXT_CLK_LPASS_CORE_HW_VOTE) { - trace_printk("%s: vote for %d clock\n", - __func__, clk_priv->clk_src); +#ifdef CONFIG_AUDIO_PRM + pr_debug("%s: clk_id %d ",__func__, clk_priv->prm_clk_cfg.clk_id); + ret = audio_prm_set_lpass_hw_core_req(&clk_priv->prm_clk_cfg, + HW_CORE_ID_LPASS, 1); +#else ret = afe_vote_lpass_core_hw(AFE_LPASS_CORE_HW_MACRO_BLOCK, "LPASS_HW_MACRO", &clk_priv->lpass_core_hwvote_client_handle); +#endif if (ret < 0) { pr_err("%s lpass core hw vote failed %d\n", __func__, ret); @@ -178,33 +181,40 @@ static int lpass_hw_vote_prepare(struct clk_hw *hw) } if (clk_priv->clk_src == AUDIO_EXT_CLK_LPASS_AUDIO_HW_VOTE) { - trace_printk("%s: vote for %d clock\n", - __func__, clk_priv->clk_src); +#ifdef CONFIG_AUDIO_PRM + pr_debug("%s: clk_id %d ",__func__, clk_priv->prm_clk_cfg.clk_id); + ret = audio_prm_set_lpass_hw_core_req(&clk_priv->prm_clk_cfg, + HW_CORE_ID_DCODEC, 1); +#else ret = afe_vote_lpass_core_hw(AFE_LPASS_CORE_HW_DCODEC_BLOCK, "LPASS_HW_DCODEC", &clk_priv->lpass_audio_hwvote_client_handle); +#endif if (ret < 0) { pr_err("%s lpass audio hw vote failed %d\n", __func__, ret); return ret; } } -#endif + return 0; } static void lpass_hw_vote_unprepare(struct clk_hw *hw) { -#if 0 struct audio_ext_clk_priv *clk_priv = to_audio_clk(hw); int ret = 0; if (clk_priv->clk_src == AUDIO_EXT_CLK_LPASS_CORE_HW_VOTE) { - trace_printk("%s: unvote for %d clock\n", - __func__, clk_priv->clk_src); +#ifdef CONFIG_AUDIO_PRM + pr_debug("%s: clk_id %d ",__func__, clk_priv->prm_clk_cfg.clk_id); + ret = audio_prm_set_lpass_hw_core_req(&clk_priv->prm_clk_cfg, + HW_CORE_ID_LPASS, 0); +#else ret = afe_unvote_lpass_core_hw( AFE_LPASS_CORE_HW_MACRO_BLOCK, clk_priv->lpass_core_hwvote_client_handle); +#endif if (ret < 0) { pr_err("%s lpass core hw vote failed %d\n", __func__, ret); @@ -212,17 +222,21 @@ static void lpass_hw_vote_unprepare(struct clk_hw *hw) } if (clk_priv->clk_src == AUDIO_EXT_CLK_LPASS_AUDIO_HW_VOTE) { - trace_printk("%s: unvote for %d clock\n", - __func__, clk_priv->clk_src); + +#ifdef CONFIG_AUDIO_PRM + pr_debug("%s: clk_id %d ",__func__, clk_priv->prm_clk_cfg.clk_id); + ret = audio_prm_set_lpass_hw_core_req(&clk_priv->prm_clk_cfg, + HW_CORE_ID_DCODEC, 0); +#else ret = afe_unvote_lpass_core_hw( AFE_LPASS_CORE_HW_DCODEC_BLOCK, clk_priv->lpass_audio_hwvote_client_handle); +#endif if (ret < 0) { pr_err("%s lpass audio hw unvote failed %d\n", __func__, ret); } } -#endif } static const struct clk_ops audio_ext_clk_ops = { @@ -583,7 +597,7 @@ static int audio_ref_clk_probe(struct platform_device *pdev) clk_priv->clk_cfg.clk_id = clk_id; #ifdef CONFIG_AUDIO_PRM clk_priv->prm_clk_cfg.clk_id = clk_id; - dev_info(&pdev->dev, "%s: ext-clk freq: %d, lpass clk_id: %d, clk_src: %d\n", + dev_info(&pdev->dev, "%s: PRM ext-clk freq: %d, lpass clk_id: %d, clk_src: %d\n", __func__, clk_priv->prm_clk_cfg.clk_freq_in_hz, clk_priv->prm_clk_cfg.clk_id, clk_priv->clk_src); #endif @@ -592,6 +606,11 @@ static int audio_ref_clk_probe(struct platform_device *pdev) dev_info(&pdev->dev, "%s: ext-clk freq: %d, lpass clk_id: %d, clk_src: %d\n", __func__, clk_priv->clk_cfg.clk_freq_in_hz, clk_priv->clk_cfg.clk_id, clk_priv->clk_src); + + dev_info(&pdev->dev, "%s: PRM2 ext-clk freq: %d, lpass clk_id: %d, clk_src: %d\n", + __func__, clk_priv->prm_clk_cfg.clk_freq_in_hz, + clk_priv->prm_clk_cfg.clk_id, clk_priv->clk_src); + platform_set_drvdata(pdev, clk_priv); ret = of_property_read_string(pdev->dev.of_node, "pmic-clock-names", diff --git a/dsp/audio_prm.c b/dsp/audio_prm.c index ee83513864..e2a1d69393 100644 --- a/dsp/audio_prm.c +++ b/dsp/audio_prm.c @@ -41,7 +41,7 @@ static int audio_prm_callback(struct gpr_device *adev, void *data) struct gpr_hdr *hdr = (struct gpr_hdr *)data; uint32_t *payload = GPR_PKT_GET_PAYLOAD(uint32_t, data); - dev_dbg(&adev->dev, "%s: Payload %x", __func__, hdr->opcode); + dev_err(&adev->dev, "%s: Payload %x", __func__, hdr->opcode); switch (hdr->opcode) { case GPR_IBASIC_RSP_RESULT: pr_err("%s: Failed response received",__func__); @@ -61,6 +61,7 @@ static int audio_prm_callback(struct gpr_device *adev, void *data) switch (payload[0]) { case PARAM_ID_RSC_AUDIO_HW_CLK: case PARAM_ID_RSC_LPASS_CORE: + case PARAM_ID_RSC_HW_CORE: if (payload[1] != 0) pr_err("%s: PRM command failed with error %d\n", __func__, payload[1]); @@ -68,6 +69,7 @@ static int audio_prm_callback(struct gpr_device *adev, void *data) wake_up(&g_prm.wait); break; default: + pr_err("%s: hit default case",__func__); break; }; default: @@ -129,6 +131,60 @@ static int prm_gpr_send_pkt(struct gpr_pkt *pkt, wait_queue_head_t *wait) return ret; } +/** + */ +int audio_prm_set_lpass_hw_core_req(struct clk_cfg *cfg, uint32_t hw_core_id, uint8_t enable) +{ + struct gpr_pkt *pkt; + prm_cmd_request_hw_core_t prm_rsc_request; + int ret = 0; + uint32_t size; + + size = GPR_HDR_SIZE + sizeof(prm_cmd_request_hw_core_t); + pkt = kzalloc(size, GFP_KERNEL); + if (!pkt) + return -ENOMEM; + + pkt->hdr.header = GPR_SET_FIELD(GPR_PKT_VERSION, GPR_PKT_VER) | + GPR_SET_FIELD(GPR_PKT_HEADER_SIZE, GPR_PKT_HEADER_WORD_SIZE_V) | + GPR_SET_FIELD(GPR_PKT_PACKET_SIZE, size); + + pkt->hdr.src_port = GPR_SVC_ASM; + pkt->hdr.dst_port = PRM_MODULE_INSTANCE_ID; + pkt->hdr.dst_domain_id = GPR_IDS_DOMAIN_ID_ADSP_V; + pkt->hdr.src_domain_id = GPR_IDS_DOMAIN_ID_APPS_V; + pkt->hdr.token = 0; /* TBD */ + if (enable) + pkt->hdr.opcode = PRM_CMD_REQUEST_HW_RSC; + else + pkt->hdr.opcode = PRM_CMD_RELEASE_HW_RSC; + + pr_err("%s: clk_id %d size of cmd_req %ld \n",__func__, cfg->clk_id, sizeof(prm_cmd_request_hw_core_t)); + + prm_rsc_request.payload_header.payload_address_lsw = 0; + prm_rsc_request.payload_header.payload_address_msw = 0; + prm_rsc_request.payload_header.mem_map_handle = 0; + prm_rsc_request.payload_header.payload_size = sizeof(prm_cmd_request_hw_core_t) - sizeof(apm_cmd_header_t); + + /** Populate the param payload */ + prm_rsc_request.module_payload_0.module_instance_id = PRM_MODULE_INSTANCE_ID; + prm_rsc_request.module_payload_0.error_code = 0; + prm_rsc_request.module_payload_0.param_id = PARAM_ID_RSC_HW_CORE; + prm_rsc_request.module_payload_0.param_size = + sizeof(prm_cmd_request_hw_core_t) - sizeof(apm_cmd_header_t) - sizeof(apm_module_param_data_t); + + + prm_rsc_request.hw_core_id = hw_core_id; // HW_CORE_ID_LPASS; + + memcpy(&pkt->payload, &prm_rsc_request, sizeof(prm_cmd_request_hw_core_t)); + + ret = prm_gpr_send_pkt(pkt, &g_prm.wait); + + kfree(pkt); + return ret; +} +EXPORT_SYMBOL(audio_prm_set_lpass_hw_core_req); + /** * prm_set_lpass_clk_cfg() - Set PRM clock * @@ -296,6 +352,7 @@ err: static int audio_prm_remove(struct gpr_device *adev) { int ret = 0; + mutex_lock(&g_prm.lock); ret = snd_event_client_deregister(&adev->dev); if (ret) { diff --git a/include/dsp/audio_prm.h b/include/dsp/audio_prm.h index 0109cb8612..0bdfe649b4 100644 --- a/include/dsp/audio_prm.h +++ b/include/dsp/audio_prm.h @@ -181,6 +181,13 @@ typedef struct prm_cmd_release_rsc_t audio_hw_clk_rel_cfg_t clock_ids_t[MAX_AUD_HW_CLK_NUM_REQ]; }prm_cmd_release_rsc_t; +typedef struct prm_cmd_request_hw_core_t +{ + apm_cmd_header_t payload_header; + apm_module_param_data_t module_payload_0; + uint32_t hw_core_id; +}prm_cmd_request_hw_core_t; + #define PRM_CMD_REQUEST_HW_RSC 0x0100100F @@ -197,6 +204,7 @@ typedef struct prm_cmd_release_rsc_t /* Param ID for lpass core clock */ #define PARAM_ID_RSC_LPASS_CORE 0x0800102B +#define PARAM_ID_RSC_HW_CORE 0x08001032 #define HW_RSC_ID_AUDIO_HW_CLK 0x0800102C @@ -494,6 +502,13 @@ typedef struct prm_cmd_release_rsc_t /** Default root clock source. */ #define CLOCK_ROOT_DEFAULT 0x0 +/** Hardware core identifier for LPASS. */ +#define HW_CORE_ID_LPASS 0x1 + +/** Hardware core identifier for digital codec. */ +#define HW_CORE_ID_DCODEC 0x2 + int audio_prm_set_lpass_clk_cfg(struct clk_cfg *cfg, uint8_t enable); +int audio_prm_set_lpass_hw_core_req(struct clk_cfg *cfg, uint32_t hw_core_id, uint8_t enable); #endif