From 428c68409dfb9053d48ce635b4f716e76049c0a8 Mon Sep 17 00:00:00 2001 From: Ayush Kumar Date: Fri, 19 May 2023 18:29:02 +0530 Subject: [PATCH] msm: camera: isp: Disable TFE WM clients dynamically This commit adds support to disable acquired TFE WM clients if the client is not configured. CRs-Fixed: 3531808 Change-Id: Ie3be423dfd2ab35031677563d66fd811090148fe Signed-off-by: Ayush Kumar --- drivers/cam_isp/cam_isp_context.c | 6 +- drivers/cam_isp/isp_hw_mgr/cam_tfe_hw_mgr.c | 6 +- drivers/cam_isp/isp_hw_mgr/cam_tfe_hw_mgr.h | 2 + .../hw_utils/cam_isp_packet_parser.c | 87 ++++++++++++++++++- .../hw_utils/include/cam_isp_packet_parser.h | 21 +++++ .../isp_hw_mgr/include/cam_isp_hw_mgr_intf.h | 2 + .../isp_hw_mgr/isp_hw/include/cam_isp_hw.h | 1 + .../isp_hw_mgr/isp_hw/tfe_hw/cam_tfe_bus.c | 68 +++++++++++++++ .../isp_hw_mgr/isp_hw/tfe_hw/cam_tfe_core.c | 1 + 9 files changed, 188 insertions(+), 6 deletions(-) diff --git a/drivers/cam_isp/cam_isp_context.c b/drivers/cam_isp/cam_isp_context.c index bdfff772fb..3622f081bd 100644 --- a/drivers/cam_isp/cam_isp_context.c +++ b/drivers/cam_isp/cam_isp_context.c @@ -2431,11 +2431,13 @@ static int __cam_isp_ctx_handle_buf_done_for_request_verify_addr( continue; } else if (!req_isp->bubble_detected) { CAM_DBG(CAM_ISP, - "Sync with success: req %lld res 0x%x fd 0x%x, ctx:%u link[0x%x]", + "Sync with success: req %lld res 0x%x fd 0x%x, ctx %u res %s", req->request_id, req_isp->fence_map_out[j].resource_handle, req_isp->fence_map_out[j].sync_id, - ctx->ctx_id, ctx->link_hdl); + ctx->ctx_id, + __cam_isp_resource_handle_id_to_type(ctx_isp->isp_device_type, + req_isp->fence_map_out[j].resource_handle)); cam_smmu_buffer_tracker_buffer_putref( req_isp->fence_map_out[j].buffer_tracker); 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 9360fa554a..b6c11cd000 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 @@ -1011,6 +1011,7 @@ static int cam_tfe_hw_mgr_acquire_res_tfe_out_rdi( tfe_out_res->res_id = tfe_out_res_id; tfe_out_res->res_type = CAM_ISP_RESOURCE_TFE_OUT; tfe_in_res->num_children++; + tfe_ctx->acquired_wm_mask |= (1 << out_port->res_id); return 0; err: @@ -1104,6 +1105,7 @@ static int cam_tfe_hw_mgr_acquire_res_tfe_out_pixel( tfe_out_res->res_type = CAM_ISP_RESOURCE_TFE_OUT; tfe_out_res->res_id = out_port->res_id; tfe_in_res->num_children++; + tfe_ctx->acquired_wm_mask |= (1 << out_port->res_id); } return 0; @@ -4066,6 +4068,7 @@ static int cam_tfe_mgr_release_hw(void *hw_mgr_priv, ctx->tfe_bus_comp_grp = NULL; ctx->is_shdr = false; ctx->is_shdr_slave = false; + ctx->acquired_wm_mask = 0; atomic_set(&ctx->overflow_pending, 0); for (i = 0; i < ctx->last_submit_bl_cmd.bl_count; i++) { @@ -5129,7 +5132,6 @@ static int cam_tfe_mgr_prepare_hw_update(void *hw_mgr_priv, goto end; } - /* get command buffers */ if (ctx->base[i].split_id != CAM_ISP_HW_SPLIT_MAX) { rc = cam_tfe_add_command_buffers(prepare, @@ -5149,6 +5151,8 @@ static int cam_tfe_mgr_prepare_hw_update(void *hw_mgr_priv, sizeof(struct cam_isp_frame_header_info)); frame_header_info.frame_header_enable = false; + prepare_hw_data->wm_bitmask = ctx->acquired_wm_mask; + /* get IO buffers */ io_buf_info.frame_hdr = &frame_header_info; io_buf_info.scratch_check_cfg = &check_for_scratch; diff --git a/drivers/cam_isp/isp_hw_mgr/cam_tfe_hw_mgr.h b/drivers/cam_isp/isp_hw_mgr/cam_tfe_hw_mgr.h index 4d971d2b19..968c2a224a 100644 --- a/drivers/cam_isp/isp_hw_mgr/cam_tfe_hw_mgr.h +++ b/drivers/cam_isp/isp_hw_mgr/cam_tfe_hw_mgr.h @@ -129,6 +129,7 @@ struct cam_tfe_cdm_user_data { * @try_recovery_cnt Retry count for overflow recovery * @current_mup Current MUP val * @recovery_req_id The request id on which overflow recovery happens + * @acquired_wm_mask Bitmask of acquired out resource * @is_shdr Indicate if the usecase is SHDR * @is_shdr_slave Indicate whether context is slave in shdr usecase */ @@ -178,6 +179,7 @@ struct cam_tfe_hw_mgr_ctx { uint32_t current_mup; uint32_t try_recovery_cnt; uint64_t recovery_req_id; + uint64_t acquired_wm_mask; enum cam_cdm_id cdm_id; bool is_shdr; bool is_shdr_slave; diff --git a/drivers/cam_isp/isp_hw_mgr/hw_utils/cam_isp_packet_parser.c b/drivers/cam_isp/isp_hw_mgr/hw_utils/cam_isp_packet_parser.c index f422217c33..102e913f0c 100644 --- a/drivers/cam_isp/isp_hw_mgr/hw_utils/cam_isp_packet_parser.c +++ b/drivers/cam_isp/isp_hw_mgr/hw_utils/cam_isp_packet_parser.c @@ -1123,7 +1123,7 @@ int cam_isp_add_io_buffers(struct cam_isp_io_buf_info *io_info) int rc = 0; struct cam_buf_io_cfg *io_cfg = NULL; struct cam_isp_hw_mgr_res *hw_mgr_res = NULL; - uint32_t i; + uint32_t i, j; uint32_t curr_used_bytes = 0; uint32_t bytes_updated = 0; struct cam_isp_resource_node *res = NULL; @@ -1132,6 +1132,8 @@ int cam_isp_add_io_buffers(struct cam_isp_io_buf_info *io_info) uint8_t max_out_res = 0; uint64_t *mc_cfg = NULL; uint32_t major_version = 0; + struct cam_isp_prepare_hw_update_data *prepare_hw_data; + uint64_t cfg_io_mask = 0, disabled_wm_mask = 0; io_cfg = (struct cam_buf_io_cfg *) ((uint8_t *) &io_info->prepare->packet->payload + @@ -1158,6 +1160,7 @@ int cam_isp_add_io_buffers(struct cam_isp_io_buf_info *io_info) } } + prepare_hw_data = (struct cam_isp_prepare_hw_update_data *) io_info->prepare->priv; for (i = 0; i < io_info->prepare->packet->num_io_configs; i++) { if (major_version == 3) { @@ -1192,6 +1195,8 @@ int cam_isp_add_io_buffers(struct cam_isp_io_buf_info *io_info) if (!res) continue; + cfg_io_mask |= (1 << (res->res_id & 0xFF)); + rc = cam_isp_add_io_buffers_util(io_info, &io_cfg[i], res); if (rc) { CAM_ERR(CAM_ISP, "io_cfg[%d] add buf failed rc %d", i, rc); @@ -1214,9 +1219,25 @@ int cam_isp_add_io_buffers(struct cam_isp_io_buf_info *io_info) vfree(mc_cfg); } + disabled_wm_mask = (prepare_hw_data->wm_bitmask ^ cfg_io_mask); + if ((io_info->base->hw_type == CAM_ISP_HW_TYPE_TFE) && disabled_wm_mask) { + for (j = 0; j < io_info->out_max; j++) { + rc = cam_isp_add_disable_wm_update(io_info->prepare, + &io_info->res_list_isp_out[j], + io_info->base->idx, io_info->kmd_buf_info, + disabled_wm_mask, + &io_info->kmd_buf_info->used_bytes); + if (rc) { + CAM_ERR_RATE_LIMIT(CAM_ISP, "Disable out res %d failed", + j, rc); + return rc; + } + } + } + bytes_updated = io_info->kmd_buf_info->used_bytes - curr_used_bytes; - CAM_DBG(CAM_ISP, "io_cfg_used_bytes %d, fill_fence %d", - bytes_updated, io_info->fill_fence); + CAM_DBG(CAM_ISP, "io_cfg_used_bytes %d, fill_fence %d acuired mask %x cfg mask %x", + bytes_updated, io_info->fill_fence, prepare_hw_data->wm_bitmask, cfg_io_mask); if (bytes_updated) { /** @@ -1237,6 +1258,66 @@ err: return rc; } +int cam_isp_add_disable_wm_update( + struct cam_hw_prepare_update_args *prepare, + struct cam_isp_hw_mgr_res *isp_hw_res, + uint32_t base_idx, + struct cam_kmd_buf_info *kmd_buf_info, + uint64_t wm_mask, + uint32_t *io_cfg_used_bytes) +{ + int rc = 0; + struct cam_hw_intf *hw_intf; + struct cam_isp_resource_node *res; + struct cam_isp_hw_get_cmd_update wm_update; + uint32_t kmd_buf_remain_size, i; + + if (prepare->packet->header.request_id == 0) + return 0; + 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; + res = isp_hw_res->hw_res[i]; + if (res->hw_intf->hw_idx != base_idx) + continue; + if (!(wm_mask & (1 << res->res_id))) { + CAM_DBG(CAM_ISP, "No need to disable out res %d", res->res_id); + continue; + } + if (kmd_buf_info->size > (kmd_buf_info->used_bytes + + (*io_cfg_used_bytes))) { + kmd_buf_remain_size = kmd_buf_info->size - + (kmd_buf_info->used_bytes + + (*io_cfg_used_bytes)); + } else { + CAM_ERR(CAM_ISP, "no free mem %d %d", kmd_buf_info->size, + kmd_buf_info->used_bytes + (*io_cfg_used_bytes)); + rc = -EINVAL; + return rc; + } + wm_update.cmd.cmd_buf_addr = kmd_buf_info->cpu_addr + + kmd_buf_info->used_bytes/4 + (*io_cfg_used_bytes)/4; + wm_update.cmd.size = kmd_buf_remain_size; + wm_update.cmd_type = CAM_ISP_HW_CMD_BUS_WM_DISABLE; + wm_update.res = res; + rc = res->hw_intf->hw_ops.process_cmd( + res->hw_intf->hw_priv, + CAM_ISP_HW_CMD_BUS_WM_DISABLE, &wm_update, + sizeof(struct cam_isp_hw_get_cmd_update)); + if (rc) { + CAM_ERR(CAM_ISP, "Diaable res %d failed split %d", + res->res_id, i); + return rc; + } + CAM_DBG(CAM_ISP, + "Out res %d disable update added hw_id %d cdm_idx %d", + res->res_id, res->hw_intf->hw_idx, base_idx); + (*io_cfg_used_bytes) += wm_update.cmd.used_bytes; + } + return rc; +} + int cam_isp_add_reg_update( struct cam_hw_prepare_update_args *prepare, struct list_head *res_list_isp_src, diff --git a/drivers/cam_isp/isp_hw_mgr/hw_utils/include/cam_isp_packet_parser.h b/drivers/cam_isp/isp_hw_mgr/hw_utils/include/cam_isp_packet_parser.h index f0ceb18909..bdf56756e8 100644 --- a/drivers/cam_isp/isp_hw_mgr/hw_utils/include/cam_isp_packet_parser.h +++ b/drivers/cam_isp/isp_hw_mgr/hw_utils/include/cam_isp_packet_parser.h @@ -278,6 +278,27 @@ int cam_isp_add_command_buffers( */ int cam_isp_add_io_buffers(struct cam_isp_io_buf_info *io_info); +/* + * cam_isp_add_disable_wm_update() + * + * @brief Add disable wm command + * + * @prepare: Contain the packet and HW update variables + * @isp_hw_res: Resource list for IFE/VFE out resource + * @base_idx: Base or dev index of the IFE/VFE HW instance + * @kmd_buf_info: Kmd buffer to store the change base command + * @wm_mask Bit mask of unconfigured resource + * @io_cfg_used_bytes IO cfg size used in bytes + * + */ +int cam_isp_add_disable_wm_update( + struct cam_hw_prepare_update_args *prepare, + struct cam_isp_hw_mgr_res *isp_hw_res, + uint32_t base_idx, + struct cam_kmd_buf_info *kmd_buf_info, + uint64_t wm_mask, + uint32_t *io_cfg_used_bytes); + /* * cam_isp_add_reg_update() * 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 877d7f823a..beaaa38e9d 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 @@ -348,6 +348,7 @@ struct cam_isp_fcg_config_info { * @packet: CSL packet from user mode driver * @mup_val: MUP value if configured * @num_exp: Num of exposures + * @wm_bitmask: Bitmask of acquired out resource * @mup_en: Flag if dynamic sensor switch is enabled * @fcg_info: Track FCG config for further usage in config stage * @@ -370,6 +371,7 @@ struct cam_isp_prepare_hw_update_data { struct cam_kmd_buf_info kmd_cmd_buff_info; uint32_t mup_val; uint32_t num_exp; + uint64_t wm_bitmask; bool mup_en; struct cam_isp_fcg_config_info fcg_info; }; 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 c3a9543d0d..96ec903ffe 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 @@ -258,6 +258,7 @@ enum cam_isp_hw_cmd_type { CAM_ISP_HW_CMD_GET_SET_PRIM_SOF_TS_ADDR, CAM_ISP_HW_CMD_DYNAMIC_CLOCK_UPDATE, CAM_ISP_HW_CMD_SET_SYNC_HW_IDX, + CAM_ISP_HW_CMD_BUS_WM_DISABLE, CAM_ISP_HW_CMD_MAX, }; diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_hw/cam_tfe_bus.c b/drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_hw/cam_tfe_bus.c index b57feb1e0a..e3ded4bd16 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_hw/cam_tfe_bus.c +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_hw/cam_tfe_bus.c @@ -653,6 +653,7 @@ static int cam_tfe_bus_acquire_rdi_wm( int pack_fmt = 0; int rdi_width = rsrc_data->common_data->rdi_width; int mode_cfg_shift = rsrc_data->common_data->mode_cfg_shift; + if (rdi_width == 64) pack_fmt = 0xa; else if (rdi_width == 128) @@ -2164,6 +2165,70 @@ end: } +static int cam_tfe_bus_diable_wm(void *priv, void *cmd_args, + uint32_t arg_size) +{ + struct cam_tfe_bus_priv *bus_priv; + struct cam_isp_hw_get_cmd_update *update_buf; + struct cam_tfe_bus_tfe_out_data *tfe_out_data = NULL; + struct cam_tfe_bus_wm_resource_data *wm_data = NULL; + struct cam_cdm_utils_ops *cdm_util_ops = NULL; + uint32_t *reg_val_pair; + uint32_t num_regval_pairs = 0; + uint32_t i, j, size = 0; + + bus_priv = (struct cam_tfe_bus_priv *) priv; + update_buf = (struct cam_isp_hw_get_cmd_update *) cmd_args; + tfe_out_data = (struct cam_tfe_bus_tfe_out_data *) update_buf->res->res_priv; + + if (!tfe_out_data || !(tfe_out_data->cdm_util_ops)) { + CAM_ERR(CAM_ISP, "Failed! invalid data"); + return -EINVAL; + } + + cdm_util_ops = tfe_out_data->cdm_util_ops; + + reg_val_pair = &tfe_out_data->common_data->io_buf_update[0]; + for (i = 0, j = 0; i < tfe_out_data->num_wm; i++) { + if (j >= (MAX_REG_VAL_PAIR_SIZE - MAX_BUF_UPDATE_REG_NUM * 2)) { + CAM_ERR(CAM_ISP, + "reg_val_pair %d exceeds the array limit %zu", + j, MAX_REG_VAL_PAIR_SIZE); + return -ENOMEM; + } + wm_data = tfe_out_data->wm_res[i]->res_priv; + + CAM_TFE_ADD_REG_VAL_PAIR(reg_val_pair, j, wm_data->hw_regs->cfg, 0); + CAM_DBG(CAM_ISP, "WM:%d disabled cfg %x", wm_data->index, wm_data->hw_regs->cfg); + } + + num_regval_pairs = j / 2; + + if (num_regval_pairs) { + size = cdm_util_ops->cdm_required_size_reg_random(num_regval_pairs); + + /* cdm util returns dwords, need to convert to bytes */ + if ((size * 4) > update_buf->cmd.size) { + CAM_ERR(CAM_ISP, + "Failed! Buf size:%d insufficient, expected size:%d", + update_buf->cmd.size, size); + return -ENOMEM; + } + + cdm_util_ops->cdm_write_regrandom( + update_buf->cmd.cmd_buf_addr, + num_regval_pairs, reg_val_pair); + + /* cdm util returns dwords, need to convert to bytes */ + update_buf->cmd.used_bytes = size * 4; + } else { + update_buf->cmd.used_bytes = 0; + CAM_DBG(CAM_ISP, "No reg val pairs. num_wms: %u", tfe_out_data->num_wm); + } + + return 0; +} + static int cam_tfe_bus_update_wm(void *priv, void *cmd_args, uint32_t arg_size) { @@ -2753,6 +2818,9 @@ static int cam_tfe_bus_process_cmd(void *priv, done->last_consumed_addr = cam_tfe_bus_get_last_consumed_addr( bus_priv, done->resource_handle); break; + case CAM_ISP_HW_CMD_BUS_WM_DISABLE: + rc = cam_tfe_bus_diable_wm(priv, cmd_args, arg_size); + break; default: CAM_ERR_RATE_LIMIT(CAM_ISP, "Invalid camif process command:%d", 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 bb453a3984..73e786bbca 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 @@ -3439,6 +3439,7 @@ int cam_tfe_process_cmd(void *hw_priv, uint32_t cmd_type, case CAM_ISP_HW_CMD_IS_PDAF_RDI2_MUX_EN: case CAM_ISP_HW_CMD_WM_BW_LIMIT_CONFIG: case CAM_ISP_HW_CMD_GET_LAST_CONSUMED_ADDR: + case CAM_ISP_HW_CMD_BUS_WM_DISABLE: rc = core_info->tfe_bus->hw_ops.process_cmd( core_info->tfe_bus->bus_priv, cmd_type, cmd_args, arg_size);