From c15edd4c3d7f01bb0a5995a2fb87e69816b79149 Mon Sep 17 00:00:00 2001 From: Shravya Samala Date: Mon, 21 Dec 2020 13:28:38 +0530 Subject: [PATCH] msm: camera: isp: Maintain clock rate relation between CSIHPY, CSID and TFE Added checks to confirm CSID frequency greater than CSIPHY frequency, TFE frequency greater than CSID frequency. Also TFE frequency should be such that it can accommodate PHY data rate. CRs-Fixed: 2847155 Change-Id: I5d3dcc53a6f27129f4b82cba1254445f58f6d0cf Signed-off-by: Shravya Samala --- drivers/cam_core/cam_context.c | 25 +++ drivers/cam_core/cam_context.h | 26 ++- drivers/cam_core/cam_hw_mgr_intf.h | 3 + drivers/cam_isp/cam_isp_context.c | 34 ++++ drivers/cam_isp/cam_isp_dev.c | 17 ++ drivers/cam_isp/isp_hw_mgr/cam_tfe_hw_mgr.c | 178 ++++++++++++++++++ .../isp_hw_mgr/include/cam_isp_hw_mgr_intf.h | 2 +- .../isp_hw_mgr/isp_hw/include/cam_isp_hw.h | 2 + .../isp_hw/tfe_csid_hw/cam_tfe_csid_core.c | 52 +++++ .../isp_hw_mgr/isp_hw/tfe_hw/cam_tfe_core.c | 64 +++++++ drivers/cam_req_mgr/cam_subdev.h | 3 +- drivers/cam_utils/cam_soc_util.c | 17 ++ drivers/cam_utils/cam_soc_util.h | 13 ++ 13 files changed, 429 insertions(+), 7 deletions(-) diff --git a/drivers/cam_core/cam_context.c b/drivers/cam_core/cam_context.c index 5fc9387e339b..75424db0c16a 100644 --- a/drivers/cam_core/cam_context.c +++ b/drivers/cam_core/cam_context.c @@ -311,6 +311,31 @@ int cam_context_dump_pf_info(struct cam_context *ctx, return rc; } +int cam_context_handle_message(struct cam_context *ctx, + uint32_t msg_type, uint32_t *data) +{ + int rc = 0; + + if (!ctx->state_machine) { + CAM_ERR(CAM_CORE, "Context is not ready"); + return -EINVAL; + } + + if ((ctx->state > CAM_CTX_AVAILABLE) && + (ctx->state < CAM_CTX_STATE_MAX)) { + if (ctx->state_machine[ctx->state].msg_cb_ops) { + rc = ctx->state_machine[ctx->state].msg_cb_ops( + ctx, msg_type, data); + } else { + CAM_WARN(CAM_CORE, + "No message handler for ctx %d, state %d msg_type :%d", + ctx->dev_hdl, ctx->state, msg_type); + } + } + + return rc; +} + int cam_context_handle_acquire_dev(struct cam_context *ctx, struct cam_acquire_dev_cmd *cmd) { diff --git a/drivers/cam_core/cam_context.h b/drivers/cam_core/cam_context.h index d649b22167a1..5be078536ff5 100644 --- a/drivers/cam_core/cam_context.h +++ b/drivers/cam_core/cam_context.h @@ -158,14 +158,17 @@ struct cam_ctx_crm_ops { * @pagefault_ops: Function to be called on page fault * @dumpinfo_ops: Function to be invoked for dumping any * context info + * @msg_cb_ops: Function to be called on any message from + * other subdev notifications * */ struct cam_ctx_ops { - struct cam_ctx_ioctl_ops ioctl_ops; - struct cam_ctx_crm_ops crm_ops; - cam_hw_event_cb_func irq_ops; - cam_hw_pagefault_cb_func pagefault_ops; - cam_ctx_info_dump_cb_func dumpinfo_ops; + struct cam_ctx_ioctl_ops ioctl_ops; + struct cam_ctx_crm_ops crm_ops; + cam_hw_event_cb_func irq_ops; + cam_hw_pagefault_cb_func pagefault_ops; + cam_ctx_info_dump_cb_func dumpinfo_ops; + cam_ctx_message_cb_func msg_cb_ops; }; /** @@ -367,6 +370,19 @@ int cam_context_handle_crm_dump_req(struct cam_context *ctx, int cam_context_dump_pf_info(struct cam_context *ctx, struct cam_smmu_pf_info *pf_info); +/** + * cam_context_handle_message() + * + * @brief: Handle message callback command + * + * @ctx: Object pointer for cam_context + * @msg_type: message type sent from other subdev + * @data: data from other subdev + * + */ +int cam_context_handle_message(struct cam_context *ctx, + uint32_t msg_type, uint32_t *data); + /** * cam_context_handle_acquire_dev() * diff --git a/drivers/cam_core/cam_hw_mgr_intf.h b/drivers/cam_core/cam_hw_mgr_intf.h index 9b6942acab61..c7537b5f361b 100644 --- a/drivers/cam_core/cam_hw_mgr_intf.h +++ b/drivers/cam_core/cam_hw_mgr_intf.h @@ -53,6 +53,9 @@ typedef int (*cam_hw_pagefault_cb_func)(void *context, typedef int (*cam_ctx_info_dump_cb_func)(void *context, enum cam_context_dump_id dump_id); +/* message callback function type */ +typedef int (*cam_ctx_message_cb_func)(void *context, + uint32_t message_type, uint32_t *data); /** * struct cam_hw_update_entry - Entry for hardware config * diff --git a/drivers/cam_isp/cam_isp_context.c b/drivers/cam_isp/cam_isp_context.c index 713c6a23c4c1..e7e55e94b619 100644 --- a/drivers/cam_isp/cam_isp_context.c +++ b/drivers/cam_isp/cam_isp_context.c @@ -21,6 +21,7 @@ #include "cam_common_util.h" #include "cam_req_mgr_debug.h" #include "cam_cpas_api.h" +#include "cam_subdev.h" static const char isp_dev_name[] = "cam-isp"; @@ -33,6 +34,9 @@ static struct cam_isp_ctx_debug isp_ctx_debug; static int cam_isp_context_dump_requests(void *data, struct cam_smmu_pf_info *pf_info); +static int cam_isp_context_handle_message(void *context, + uint32_t msg_type, uint32_t *data); + static int __cam_isp_ctx_start_dev_in_ready(struct cam_context *ctx, struct cam_start_stop_dev_cmd *cmd); @@ -5772,6 +5776,7 @@ static struct cam_ctx_ops .irq_ops = NULL, .pagefault_ops = cam_isp_context_dump_requests, .dumpinfo_ops = cam_isp_context_info_dump, + .msg_cb_ops = cam_isp_context_handle_message, }, /* Activated */ { @@ -5791,6 +5796,7 @@ static struct cam_ctx_ops .irq_ops = __cam_isp_ctx_handle_irq_in_activated, .pagefault_ops = cam_isp_context_dump_requests, .dumpinfo_ops = cam_isp_context_info_dump, + .msg_cb_ops = cam_isp_context_handle_message, }, }; @@ -5933,6 +5939,34 @@ static int cam_isp_context_dump_requests(void *data, return rc; } +static int cam_isp_context_handle_message(void *context, + uint32_t msg_type, uint32_t *data) +{ + int rc = 0; + struct cam_hw_cmd_args hw_cmd_args; + struct cam_isp_hw_cmd_args isp_hw_cmd_args; + struct cam_context *ctx = (struct cam_context *)context; + + memset(&hw_cmd_args, 0, sizeof(hw_cmd_args)); + hw_cmd_args.ctxt_to_hw_map = ctx->ctxt_to_hw_map; + + switch (msg_type) { + case CAM_SUBDEV_MESSAGE_CLOCK_UPDATE: + hw_cmd_args.cmd_type = CAM_HW_MGR_CMD_INTERNAL; + isp_hw_cmd_args.cmd_type = CAM_ISP_HW_MGR_CMD_UPDATE_CLOCK; + isp_hw_cmd_args.cmd_data = (void *)data; + hw_cmd_args.u.internal_args = (void *)&isp_hw_cmd_args; + rc = ctx->hw_mgr_intf->hw_cmd(ctx->hw_mgr_intf->hw_mgr_priv, + &hw_cmd_args); + if (rc) + CAM_ERR(CAM_ISP, "Update clock rate failed rc: %d", rc); + break; + default: + CAM_ERR(CAM_ISP, "Invalid message type %d", msg_type); + } + return rc; +} + static int cam_isp_context_debug_register(void) { int rc = 0; diff --git a/drivers/cam_isp/cam_isp_dev.c b/drivers/cam_isp/cam_isp_dev.c index 68eb02e9b466..6908a0807acb 100644 --- a/drivers/cam_isp/cam_isp_dev.c +++ b/drivers/cam_isp/cam_isp_dev.c @@ -38,6 +38,22 @@ static void cam_isp_dev_iommu_fault_handler(struct cam_smmu_pf_info *pf_info) cam_context_dump_pf_info(&(node->ctx_list[i]), pf_info); } +static void cam_isp_subdev_handle_message( + struct v4l2_subdev *sd, + enum cam_subdev_message_type_t message_type, + uint32_t data) +{ + int i, rc = 0; + struct cam_node *node = v4l2_get_subdevdata(sd); + + CAM_DBG(CAM_ISP, "node name %s", node->name, data); + for (i = 0; i < node->ctx_size; i++) { + rc = cam_context_handle_message(&(node->ctx_list[i]), message_type, &data); + if (rc) + CAM_ERR(CAM_ISP, "Failed to handle message for %s", node->name); + } +} + static const struct of_device_id cam_isp_dt_match[] = { { .compatible = "qcom,cam-isp" @@ -113,6 +129,7 @@ static int cam_isp_dev_component_bind(struct device *dev, } else if (strnstr(compat_str, "tfe", strlen(compat_str))) { rc = cam_subdev_probe(&g_isp_dev.sd, pdev, CAM_ISP_DEV_NAME, CAM_TFE_DEVICE_TYPE); + g_isp_dev.sd.msg_cb = cam_isp_subdev_handle_message; g_isp_dev.isp_device_type = CAM_TFE_DEVICE_TYPE; g_isp_dev.max_context = CAM_TFE_CTX_MAX; } else { diff --git a/drivers/cam_isp/isp_hw_mgr/cam_tfe_hw_mgr.c b/drivers/cam_isp/isp_hw_mgr/cam_tfe_hw_mgr.c index e930f6addb65..245ef46d6b7a 100644 --- a/drivers/cam_isp/isp_hw_mgr/cam_tfe_hw_mgr.c +++ b/drivers/cam_isp/isp_hw_mgr/cam_tfe_hw_mgr.c @@ -306,6 +306,82 @@ err: return rc; } +static int cam_tfe_hw_mgr_get_clock_rate( + struct cam_isp_hw_mgr_res *isp_hw_res, + uint32_t *get_clock_rate) +{ + int i; + int rc = -EINVAL; + struct cam_hw_intf *hw_intf; + + for (i = 0; i < CAM_ISP_HW_SPLIT_MAX; i++) { + if (!isp_hw_res->hw_res[i]) + continue; + + hw_intf = isp_hw_res->hw_res[i]->hw_intf; + CAM_DBG(CAM_ISP, "hw type %d hw index:%d", + hw_intf->hw_type, hw_intf->hw_idx); + if (hw_intf && hw_intf->hw_ops.process_cmd) { + rc = hw_intf->hw_ops.process_cmd( + hw_intf->hw_priv, + CAM_ISP_HW_CMD_GET_CLOCK_RATE, + get_clock_rate, + sizeof(uint32_t)); + if (rc) { + CAM_ERR(CAM_ISP, "Failed to get Clock rate"); + return rc; + } + } + } + + return rc; +} + +static int cam_tfe_hw_mgr_update_clock_rate( + struct cam_isp_hw_mgr_res *isp_hw_res, + uint32_t *set_clock_rate, + uint32_t *updated_clock_rate) +{ + int i; + int rc = 0; + struct cam_hw_intf *hw_intf; + + for (i = 0; i < CAM_ISP_HW_SPLIT_MAX; i++) { + if (!isp_hw_res->hw_res[i]) + continue; + + hw_intf = isp_hw_res->hw_res[i]->hw_intf; + CAM_DBG(CAM_ISP, "hw type %d hw index:%d", + hw_intf->hw_type, hw_intf->hw_idx); + + if (hw_intf && hw_intf->hw_ops.process_cmd) { + rc = hw_intf->hw_ops.process_cmd( + hw_intf->hw_priv, + CAM_ISP_HW_CMD_DYNAMIC_CLOCK_UPDATE, + set_clock_rate, + sizeof(uint32_t)); + if (rc) { + CAM_ERR(CAM_ISP, "Failed to get Clock rate"); + return rc; + } + } + + if (hw_intf && hw_intf->hw_ops.process_cmd) { + rc = hw_intf->hw_ops.process_cmd( + hw_intf->hw_priv, + CAM_ISP_HW_CMD_GET_CLOCK_RATE, + updated_clock_rate, + sizeof(uint32_t)); + if (rc) { + CAM_ERR(CAM_ISP, "Failed to get Clock rate"); + return rc; + } + } + } + + return rc; +} + static int cam_tfe_hw_mgr_start_hw_res( struct cam_isp_hw_mgr_res *isp_hw_res, struct cam_tfe_hw_mgr_ctx *ctx) @@ -1824,6 +1900,105 @@ void cam_tfe_cam_cdm_callback(uint32_t handle, void *userdata, } } +int cam_tfe_cshiphy_callback( + struct cam_tfe_hw_mgr_ctx *ctx, void *cmd_args) +{ + int rc = -EINVAL; + struct cam_isp_hw_mgr_res *hw_mgr_res; + uint32_t *phy_clock_rate; + uint32_t clock_rate = 0; + uint32_t csid_clock_rate = 0, tfe_clock_rate = 0; + uint32_t updated_tfe_clk = 0, updated_csid_clk = 0; + + if (!ctx || !cmd_args) { + CAM_ERR(CAM_ISP, "Invalid arguments"); + return -EINVAL; + } + + phy_clock_rate = (uint32_t *)cmd_args; + CAM_DBG(CAM_ISP, "clk rate csid ... in ctx id:%d", + ctx->ctx_index); + list_for_each_entry(hw_mgr_res, &ctx->res_list_tfe_csid, list) { + rc = cam_tfe_hw_mgr_get_clock_rate(hw_mgr_res, + &clock_rate); + if (rc) { + CAM_ERR(CAM_ISP, + "Can not get CSID clock rate(id :%d)", + hw_mgr_res->res_id); + return rc; + } + + if (!csid_clock_rate) + csid_clock_rate = clock_rate; + + if (clock_rate < csid_clock_rate) + csid_clock_rate = clock_rate; + + CAM_DBG(CAM_ISP, "clk rate csid: %lld %lld", + clock_rate, csid_clock_rate); + } + + CAM_DBG(CAM_ISP, "clk rate TFE in resource ctx id:%d", + ctx->ctx_index); + list_for_each_entry(hw_mgr_res, &ctx->res_list_tfe_in, list) { + rc = cam_tfe_hw_mgr_get_clock_rate(hw_mgr_res, + &clock_rate); + if (rc) { + CAM_ERR(CAM_ISP, + "Can not get TFE clock rate (%d)", + hw_mgr_res->res_id); + return rc; + } + + if (!tfe_clock_rate) + tfe_clock_rate = clock_rate; + + if (clock_rate < tfe_clock_rate) + tfe_clock_rate = clock_rate; + + CAM_DBG(CAM_ISP, "clk rate tfe: %lld %lld", + clock_rate, tfe_clock_rate); + } + + if (*phy_clock_rate > csid_clock_rate) { + list_for_each_entry(hw_mgr_res, + &ctx->res_list_tfe_csid, list) { + rc = cam_tfe_hw_mgr_update_clock_rate(hw_mgr_res, + phy_clock_rate, &updated_csid_clk); + } + + if (updated_csid_clk > tfe_clock_rate) { + list_for_each_entry(hw_mgr_res, + &ctx->res_list_tfe_in, list) { + rc = cam_tfe_hw_mgr_update_clock_rate(hw_mgr_res, + &updated_csid_clk, &updated_tfe_clk); + } + } + goto end; + } + + if (csid_clock_rate > tfe_clock_rate) { + list_for_each_entry(hw_mgr_res, + &ctx->res_list_tfe_in, list) { + rc = cam_tfe_hw_mgr_update_clock_rate(hw_mgr_res, + &csid_clock_rate, &updated_tfe_clk); + } + } +end: + /* final check */ + if ((*phy_clock_rate > updated_csid_clk) || + (updated_csid_clk > updated_tfe_clk) || + (*phy_clock_rate > updated_tfe_clk)) { + CAM_ERR(CAM_ISP, + "improper clock rates, phy:%lld csid:%lld tfe:%lld", + *phy_clock_rate, updated_csid_clk, updated_tfe_clk); + + return -EINVAL; + } + + return 0; +} + /* entry function: acquire_hw */ static int cam_tfe_mgr_acquire_hw(void *hw_mgr_priv, void *acquire_hw_args) { @@ -4761,6 +4936,9 @@ static int cam_tfe_mgr_cmd(void *hw_mgr_priv, void *cmd_args) isp_hw_cmd_args->u.last_cdm_done = ctx->last_cdm_done_req; break; + case CAM_ISP_HW_MGR_CMD_UPDATE_CLOCK: + rc = cam_tfe_cshiphy_callback(ctx, isp_hw_cmd_args->cmd_data); + break; default: CAM_ERR(CAM_ISP, "Invalid HW mgr command:0x%x", hw_cmd_args->cmd_type); diff --git a/drivers/cam_isp/isp_hw_mgr/include/cam_isp_hw_mgr_intf.h b/drivers/cam_isp/isp_hw_mgr/include/cam_isp_hw_mgr_intf.h index e093a8bccfbc..cfac2f5b68ca 100644 --- a/drivers/cam_isp/isp_hw_mgr/include/cam_isp_hw_mgr_intf.h +++ b/drivers/cam_isp/isp_hw_mgr/include/cam_isp_hw_mgr_intf.h @@ -48,7 +48,6 @@ enum cam_isp_hw_event_type { CAM_ISP_HW_EVENT_MAX }; - /** * enum cam_isp_hw_err_type - Collection of the ISP error types for * ISP hardware event CAM_ISP_HW_EVENT_ERROR @@ -241,6 +240,7 @@ enum cam_isp_hw_mgr_command { CAM_ISP_HW_MGR_CMD_CTX_TYPE, CAM_ISP_HW_MGR_GET_PACKET_OPCODE, CAM_ISP_HW_MGR_GET_LAST_CDM_DONE, + CAM_ISP_HW_MGR_CMD_UPDATE_CLOCK, CAM_ISP_HW_MGR_CMD_MAX, }; diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/include/cam_isp_hw.h b/drivers/cam_isp/isp_hw_mgr/isp_hw/include/cam_isp_hw.h index 64b22f7d7b62..64b6cd3ed253 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/include/cam_isp_hw.h +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/include/cam_isp_hw.h @@ -135,6 +135,8 @@ enum cam_isp_hw_cmd_type { CAM_ISP_HW_CMD_CSID_CHANGE_HALT_MODE, CAM_ISP_HW_CMD_SET_SFE_DEBUG_CFG, CAM_ISP_HW_CMD_QUERY_BUS_CAP, + CAM_ISP_HW_CMD_GET_CLOCK_RATE, + CAM_ISP_HW_CMD_DYNAMIC_CLOCK_UPDATE, CAM_ISP_HW_CMD_MAX, }; diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_csid_hw/cam_tfe_csid_core.c b/drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_csid_hw/cam_tfe_csid_core.c index 136b4e382199..a22a68e1efe0 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_csid_hw/cam_tfe_csid_core.c +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_csid_hw/cam_tfe_csid_core.c @@ -2404,6 +2404,52 @@ static int cam_tfe_csid_set_csid_clock( return 0; } +static int cam_tfe_csid_get_csid_clock( + struct cam_tfe_csid_hw *csid_hw, void *cmd_args) +{ + struct cam_hw_soc_info *soc_info; + uint32_t *curr_clk_rate; + int src_clk_idx; + int rc = 0; + + if (!csid_hw) + return -EINVAL; + + soc_info = &csid_hw->hw_info->soc_info; + src_clk_idx = soc_info->src_clk_idx; + + curr_clk_rate = (uint32_t *)cmd_args; + + rc = cam_soc_util_get_clk_rate(soc_info->clk[src_clk_idx], + soc_info->clk_name[src_clk_idx], curr_clk_rate); + + CAM_DBG(CAM_ISP, "CSID clock rate %llu", *curr_clk_rate); + + return rc; +} + +static int cam_tfe_csid_set_csid_clock_dynamically( + struct cam_tfe_csid_hw *csid_hw, void *cmd_args) +{ + struct cam_hw_soc_info *soc_info; + uint32_t *clk_rate; + int rc = 0; + + soc_info = &csid_hw->hw_info->soc_info; + clk_rate = (uint32_t *)cmd_args; + + CAM_DBG(CAM_ISP, "CSID clock rate %lld", *clk_rate); + + rc = cam_soc_util_set_src_clk_rate(soc_info, *clk_rate); + if (rc) { + CAM_ERR(CAM_ISP, + "unable to set clock dynamically rate:%lld", *clk_rate); + return rc; + } + + return rc; +} + static int cam_tfe_csid_get_regdump(struct cam_tfe_csid_hw *csid_hw, void *cmd_args) { @@ -2676,6 +2722,12 @@ static int cam_tfe_csid_process_cmd(void *hw_priv, case CAM_TFE_CSID_LOG_ACQUIRE_DATA: rc = cam_tfe_csid_log_acquire_data(csid_hw, cmd_args); break; + case CAM_ISP_HW_CMD_GET_CLOCK_RATE: + rc = cam_tfe_csid_get_csid_clock(csid_hw, cmd_args); + break; + case CAM_ISP_HW_CMD_DYNAMIC_CLOCK_UPDATE: + rc = cam_tfe_csid_set_csid_clock_dynamically(csid_hw, cmd_args); + break; default: CAM_ERR(CAM_ISP, "CSID:%d unsupported cmd:%d", csid_hw->hw_intf->hw_idx, cmd_type); diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_hw/cam_tfe_core.c b/drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_hw/cam_tfe_core.c index 66f3ead97fed..74eae1a23ff3 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_hw/cam_tfe_core.c +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_hw/cam_tfe_core.c @@ -969,6 +969,62 @@ static int cam_tfe_top_set_hw_clk_rate( return rc; } +static int cam_tfe_top_get_hw_clk_rate( + struct cam_tfe_top_priv *top_priv, + void *cmd_args, + uint32_t arg_size) +{ + struct cam_hw_soc_info *soc_info; + uint32_t *curr_clk_rate; + int src_clk_idx; + int rc = 0; + + if (!top_priv) { + CAM_ERR(CAM_ISP, "Error top_private NULL"); + return -EINVAL; + } + + soc_info = top_priv->common_data.soc_info; + src_clk_idx = soc_info->src_clk_idx; + + curr_clk_rate = (uint32_t *)cmd_args; + + rc = cam_soc_util_get_clk_rate(soc_info->clk[src_clk_idx], + soc_info->clk_name[src_clk_idx], curr_clk_rate); + + CAM_DBG(CAM_ISP, "TFE clock rate %llu", *curr_clk_rate); + + return rc; +} + +static int cam_tfe_top_dynamic_clock_update( + struct cam_tfe_top_priv *top_priv, + void *cmd_args, + uint32_t arg_size) +{ + struct cam_hw_soc_info *soc_info; + int src_clk_idx; + uint32_t *clk_rate; + int rc = 0; + + soc_info = top_priv->common_data.soc_info; + src_clk_idx = soc_info->src_clk_idx; + + clk_rate = (uint32_t *)cmd_args; + + CAM_DBG(CAM_ISP, "TFE clock rate %lld", *clk_rate); + + rc = cam_soc_util_set_src_clk_rate(soc_info, *clk_rate); + if (rc) { + CAM_ERR(CAM_ISP, + "unable to set clock dynamically rate:%lld", + *clk_rate); + return rc; + } + + return rc; +} + static struct cam_axi_vote *cam_tfe_top_delay_bw_reduction( struct cam_tfe_top_priv *top_priv, uint64_t *to_be_applied_bw) @@ -2881,6 +2937,14 @@ int cam_tfe_process_cmd(void *hw_priv, uint32_t cmd_type, rc = cam_tfe_set_top_debug(core_info, cmd_args, arg_size); break; + case CAM_ISP_HW_CMD_GET_CLOCK_RATE: + rc = cam_tfe_top_get_hw_clk_rate(core_info->top_priv, cmd_args, + arg_size); + break; + case CAM_ISP_HW_CMD_DYNAMIC_CLOCK_UPDATE: + rc = cam_tfe_top_dynamic_clock_update(core_info->top_priv, cmd_args, + arg_size); + break; case CAM_ISP_HW_CMD_GET_BUF_UPDATE: case CAM_ISP_HW_CMD_GET_HFR_UPDATE: case CAM_ISP_HW_CMD_STRIPE_UPDATE: diff --git a/drivers/cam_req_mgr/cam_subdev.h b/drivers/cam_req_mgr/cam_subdev.h index c2ded0c9103e..ae22529ef2a1 100644 --- a/drivers/cam_req_mgr/cam_subdev.h +++ b/drivers/cam_req_mgr/cam_subdev.h @@ -17,7 +17,8 @@ #define CAM_SUBDEVICE_EVENT_MAX 30 enum cam_subdev_message_type_t { - CAM_SUBDEV_MESSAGE_IRQ_ERR = 0x1 + CAM_SUBDEV_MESSAGE_IRQ_ERR = 0x1, + CAM_SUBDEV_MESSAGE_CLOCK_UPDATE }; /** diff --git a/drivers/cam_utils/cam_soc_util.c b/drivers/cam_utils/cam_soc_util.c index 2371c5c1c068..474c7c34d9b1 100644 --- a/drivers/cam_utils/cam_soc_util.c +++ b/drivers/cam_utils/cam_soc_util.c @@ -346,6 +346,23 @@ int cam_soc_util_irq_disable(struct cam_hw_soc_info *soc_info) return 0; } +int cam_soc_util_get_clk_rate(struct clk *clk, const char *clk_name, + uint32_t *clk_rate) +{ + uint32_t clk_rate_round; + + clk_rate_round = clk_get_rate(clk); + if (clk_rate_round < 0) { + CAM_ERR(CAM_UTIL, "get_rate failed on %s", clk_name); + return clk_rate_round; + } + + *clk_rate = clk_rate_round; + CAM_DBG(CAM_UTIL, "get rate %lld on %s", *clk_rate, clk_name); + + return 0; +} + long cam_soc_util_get_clk_round_rate(struct cam_hw_soc_info *soc_info, uint32_t clk_index, unsigned long clk_rate) { diff --git a/drivers/cam_utils/cam_soc_util.h b/drivers/cam_utils/cam_soc_util.h index ff75fca12d5d..aea1a396e4fd 100644 --- a/drivers/cam_utils/cam_soc_util.h +++ b/drivers/cam_utils/cam_soc_util.h @@ -405,6 +405,19 @@ int cam_soc_util_disable_platform_resource(struct cam_hw_soc_info *soc_info, long cam_soc_util_get_clk_round_rate(struct cam_hw_soc_info *soc_info, uint32_t clk_index, unsigned long clk_rate); +/** + * cam_soc_util_get_clk_rate() + * + * @brief: Get the rate on the source clock. + * @clk: Src clock reference pointer to get clock rate + * @clk_name: Name of src clock + * @clk_rate: Clock rate associated with the src clk + * + * @return: success or failure + */ +int cam_soc_util_get_clk_rate(struct clk *clk, const char *clk_name, + uint32_t *clk_rate); + /** * cam_soc_util_set_src_clk_rate() *