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() *