diff --git a/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c b/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c index 7f58ac4ec0..7cf78a69ba 100644 --- a/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c +++ b/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c @@ -8035,6 +8035,161 @@ static int cam_isp_blob_sensor_blanking_config( return rc; } +static int cam_isp_blob_bw_limit_update( + uint32_t blob_type, + struct cam_isp_generic_blob_info *blob_info, + struct cam_isp_out_rsrc_bw_limiter_config *bw_limit_cfg, + struct cam_hw_prepare_update_args *prepare, + enum cam_isp_hw_type hw_type) +{ + struct cam_isp_wm_bw_limiter_config *wm_bw_limit_cfg; + struct cam_kmd_buf_info *kmd_buf_info; + struct cam_ife_hw_mgr_ctx *ctx = NULL; + struct cam_isp_hw_mgr_res *isp_out_res; + uint32_t res_id_out, i; + uint32_t total_used_bytes = 0; + uint32_t kmd_buf_remain_size; + uint32_t *cmd_buf_addr; + uint32_t bytes_used = 0; + int num_ent, rc = 0; + + ctx = prepare->ctxt_to_hw_map; + + if ((prepare->num_hw_update_entries + 1) >= + prepare->max_hw_update_entries) { + CAM_ERR(CAM_ISP, "Insufficient HW entries: %d max: %d", + prepare->num_hw_update_entries, + prepare->max_hw_update_entries); + return -EINVAL; + } + + kmd_buf_info = blob_info->kmd_buf_info; + for (i = 0; i < bw_limit_cfg->num_ports; i++) { + wm_bw_limit_cfg = &bw_limit_cfg->bw_limiter_config[i]; + res_id_out = wm_bw_limit_cfg->res_type & 0xFF; + + if ((hw_type == CAM_ISP_HW_TYPE_SFE) && + !((wm_bw_limit_cfg->res_type >= + CAM_ISP_SFE_OUT_RES_BASE) && + (wm_bw_limit_cfg->res_type < + CAM_ISP_SFE_OUT_RES_MAX))) + continue; + + if ((hw_type == CAM_ISP_HW_TYPE_VFE) && + !((wm_bw_limit_cfg->res_type >= + CAM_ISP_IFE_OUT_RES_BASE) && + (wm_bw_limit_cfg->res_type < + (CAM_ISP_IFE_OUT_RES_BASE + max_ife_out_res)))) + continue; + + CAM_DBG(CAM_ISP, "%s BW limit config idx: %d port: 0x%x enable: %d [0x%x:0x%x]", + (hw_type == CAM_ISP_HW_TYPE_SFE ? "SFE" : "VFE"), + i, wm_bw_limit_cfg->res_type, + wm_bw_limit_cfg->enable_limiter, + wm_bw_limit_cfg->counter_limit[0], + wm_bw_limit_cfg->counter_limit[1]); + + if ((kmd_buf_info->used_bytes + + total_used_bytes) < kmd_buf_info->size) { + kmd_buf_remain_size = kmd_buf_info->size - + (kmd_buf_info->used_bytes + + total_used_bytes); + } else { + CAM_ERR(CAM_ISP, + "No free kmd memory for base idx: %d", + blob_info->base_info->idx); + rc = -ENOMEM; + return rc; + } + + cmd_buf_addr = kmd_buf_info->cpu_addr + + (kmd_buf_info->used_bytes / 4) + + (total_used_bytes / 4); + + if (hw_type == CAM_ISP_HW_TYPE_SFE) + isp_out_res = &ctx->res_list_sfe_out[res_id_out]; + else + isp_out_res = &ctx->res_list_ife_out[res_id_out]; + + rc = cam_isp_add_cmd_buf_update( + isp_out_res, blob_type, + CAM_ISP_HW_CMD_WM_BW_LIMIT_CONFIG, + blob_info->base_info->idx, + (void *)cmd_buf_addr, + kmd_buf_remain_size, + (void *)wm_bw_limit_cfg, + &bytes_used); + if (rc < 0) { + CAM_ERR(CAM_ISP, + "Failed to update %s BW limiter config for res:0x%x enable:%d [0x%x:0x%x] base_idx:%d bytes_used:%u rc:%d", + ((hw_type == CAM_ISP_HW_TYPE_SFE) ? + "SFE" : "VFE"), + wm_bw_limit_cfg->res_type, + wm_bw_limit_cfg->enable_limiter, + wm_bw_limit_cfg->counter_limit[0], + wm_bw_limit_cfg->counter_limit[1], + blob_info->base_info->idx, bytes_used, rc); + return rc; + } + + total_used_bytes += bytes_used; + } + + if (total_used_bytes) { + num_ent = prepare->num_hw_update_entries; + prepare->hw_update_entries[num_ent].handle = + kmd_buf_info->handle; + prepare->hw_update_entries[num_ent].len = total_used_bytes; + prepare->hw_update_entries[num_ent].offset = + kmd_buf_info->offset; + num_ent++; + kmd_buf_info->used_bytes += total_used_bytes; + kmd_buf_info->offset += total_used_bytes; + prepare->num_hw_update_entries = num_ent; + } + + return rc; +} + +static inline int cam_isp_validate_bw_limiter_blob( + uint32_t blob_size, + struct cam_isp_out_rsrc_bw_limiter_config *bw_limit_config) +{ + if ((bw_limit_config->num_ports > (max_ife_out_res + + g_ife_hw_mgr.isp_bus_caps.max_sfe_out_res_type)) || + (bw_limit_config->num_ports == 0)) { + CAM_ERR(CAM_ISP, + "Invalid num_ports:%u in bw limit config", + bw_limit_config->num_ports); + return -EINVAL; + } + + /* Check for integer overflow */ + if (bw_limit_config->num_ports != 1) { + if (sizeof(struct cam_isp_wm_bw_limiter_config) > ((UINT_MAX - + sizeof(struct cam_isp_out_rsrc_bw_limiter_config)) / + (bw_limit_config->num_ports - 1))) { + CAM_ERR(CAM_ISP, + "Max size exceeded in bw limit config num_ports:%u size per port:%lu", + bw_limit_config->num_ports, + sizeof(struct cam_isp_wm_bw_limiter_config)); + return -EINVAL; + } + } + + if (blob_size < (sizeof(struct cam_isp_out_rsrc_bw_limiter_config) + + (bw_limit_config->num_ports - 1) * + sizeof(struct cam_isp_wm_bw_limiter_config))) { + CAM_ERR(CAM_ISP, "Invalid blob size %u expected %lu", + blob_size, sizeof(struct cam_isp_out_rsrc_bw_limiter_config) + + (bw_limit_config->num_ports - 1) * + sizeof(struct cam_isp_wm_bw_limiter_config)); + return -EINVAL; + } + + return 0; +} + static int cam_isp_packet_generic_blob_handler(void *user_data, uint32_t blob_type, uint32_t blob_size, uint8_t *blob_data) { @@ -8586,6 +8741,32 @@ static int cam_isp_packet_generic_blob_handler(void *user_data, CAM_ERR(CAM_ISP, "MUP Update Failed"); } break; + case CAM_ISP_GENERIC_BLOB_TYPE_BW_LIMITER_CFG: { + struct cam_isp_out_rsrc_bw_limiter_config *bw_limit_config; + + if (blob_size < + sizeof(struct cam_isp_out_rsrc_bw_limiter_config)) { + CAM_ERR(CAM_ISP, "Invalid blob size %u", + blob_size, + sizeof(struct cam_isp_out_rsrc_bw_limiter_config)); + return -EINVAL; + } + + bw_limit_config = + (struct cam_isp_out_rsrc_bw_limiter_config *)blob_data; + + rc = cam_isp_validate_bw_limiter_blob(blob_size, + bw_limit_config); + if (rc) + return rc; + + rc = cam_isp_blob_bw_limit_update(blob_type, blob_info, + bw_limit_config, prepare, CAM_ISP_HW_TYPE_VFE); + if (rc) + CAM_ERR(CAM_ISP, + "BW limit update failed for IFE rc: %d", rc); + } + break; default: CAM_WARN(CAM_ISP, "Invalid blob type %d", blob_type); break; @@ -8984,6 +9165,32 @@ static int cam_sfe_packet_generic_blob_handler(void *user_data, CAM_ERR(CAM_ISP, "SFE exp order update failed"); } break; + case CAM_ISP_GENERIC_BLOB_TYPE_BW_LIMITER_CFG: { + struct cam_isp_out_rsrc_bw_limiter_config *bw_limit_config; + + if (blob_size < + sizeof(struct cam_isp_out_rsrc_bw_limiter_config)) { + CAM_ERR(CAM_ISP, "Invalid blob size %u", + blob_size, + sizeof(struct cam_isp_out_rsrc_bw_limiter_config)); + return -EINVAL; + } + + bw_limit_config = + (struct cam_isp_out_rsrc_bw_limiter_config *)blob_data; + + rc = cam_isp_validate_bw_limiter_blob(blob_size, + bw_limit_config); + if (rc) + return rc; + + rc = cam_isp_blob_bw_limit_update(blob_type, blob_info, + bw_limit_config, prepare, CAM_ISP_HW_TYPE_SFE); + if (rc) + CAM_ERR(CAM_ISP, + "BW limit update failed for SFE rc: %d", rc); + } + break; case CAM_ISP_GENERIC_BLOB_TYPE_HFR_CONFIG: case CAM_ISP_GENERIC_BLOB_TYPE_CLOCK_CONFIG: case CAM_ISP_GENERIC_BLOB_TYPE_BW_CONFIG: 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 2b302984c9..978e071943 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 @@ -160,6 +160,7 @@ enum cam_isp_hw_cmd_type { CAM_ISP_HW_CMD_IFE_BUS_DEBUG_CFG, CAM_ISP_HW_SFE_SYS_CACHE_WM_CONFIG, CAM_ISP_HW_SFE_SYS_CACHE_RM_CONFIG, + CAM_ISP_HW_CMD_WM_BW_LIMIT_CONFIG, CAM_ISP_HW_CMD_MAX, }; diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/sfe_hw/cam_sfe680.h b/drivers/cam_isp/isp_hw_mgr/isp_hw/sfe_hw/cam_sfe680.h index c89aa34ec8..eb38559fde 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/sfe_hw/cam_sfe680.h +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/sfe_hw/cam_sfe680.h @@ -425,6 +425,7 @@ static struct cam_sfe_bus_wr_hw_info sfe680_bus_wr_hw_info = { .debug_status_1 = 0x00000A88, .mmu_prefetch_cfg = 0x00000A60, .mmu_prefetch_max_offset = 0x00000A64, + .bw_limiter_addr = 0x00000A1C, .comp_group = CAM_SFE_BUS_WR_COMP_GRP_0, }, /* BUS Client 1 LCR */ @@ -454,6 +455,7 @@ static struct cam_sfe_bus_wr_hw_info sfe680_bus_wr_hw_info = { .debug_status_1 = 0x00000B88, .mmu_prefetch_cfg = 0x00000B60, .mmu_prefetch_max_offset = 0x00000B64, + .bw_limiter_addr = 0x00000B1C, .comp_group = CAM_SFE_BUS_WR_COMP_GRP_1, }, /* BUS Client 2 STATS_BE_0 */ @@ -483,6 +485,7 @@ static struct cam_sfe_bus_wr_hw_info sfe680_bus_wr_hw_info = { .debug_status_1 = 0x00000C88, .mmu_prefetch_cfg = 0x00000C60, .mmu_prefetch_max_offset = 0x00000C64, + .bw_limiter_addr = 0x00000C1C, .comp_group = CAM_SFE_BUS_WR_COMP_GRP_2, }, /* BUS Client 3 STATS_BHIST_0 */ @@ -512,6 +515,7 @@ static struct cam_sfe_bus_wr_hw_info sfe680_bus_wr_hw_info = { .debug_status_1 = 0x00000D88, .mmu_prefetch_cfg = 0x00000D60, .mmu_prefetch_max_offset = 0x00000D64, + .bw_limiter_addr = 0x00000D1C, .comp_group = CAM_SFE_BUS_WR_COMP_GRP_2, }, /* BUS Client 4 STATS_BE_1 */ @@ -541,6 +545,7 @@ static struct cam_sfe_bus_wr_hw_info sfe680_bus_wr_hw_info = { .debug_status_1 = 0x00000E88, .mmu_prefetch_cfg = 0x00000E60, .mmu_prefetch_max_offset = 0x00000E64, + .bw_limiter_addr = 0x00000E1C, .comp_group = CAM_SFE_BUS_WR_COMP_GRP_3, }, /* BUS Client 5 STATS_BHIST_1 */ @@ -570,6 +575,7 @@ static struct cam_sfe_bus_wr_hw_info sfe680_bus_wr_hw_info = { .debug_status_1 = 0x00000F88, .mmu_prefetch_cfg = 0x00000F60, .mmu_prefetch_max_offset = 0x00000F64, + .bw_limiter_addr = 0x00000F1C, .comp_group = CAM_SFE_BUS_WR_COMP_GRP_3, }, /* BUS Client 6 STATS_BE_2 */ @@ -599,6 +605,7 @@ static struct cam_sfe_bus_wr_hw_info sfe680_bus_wr_hw_info = { .debug_status_1 = 0x00001088, .mmu_prefetch_cfg = 0x00001060, .mmu_prefetch_max_offset = 0x00001064, + .bw_limiter_addr = 0x0000101C, .comp_group = CAM_SFE_BUS_WR_COMP_GRP_4, }, /* BUS Client 7 STATS_BHIST_2 */ @@ -628,6 +635,7 @@ static struct cam_sfe_bus_wr_hw_info sfe680_bus_wr_hw_info = { .debug_status_1 = 0x00001188, .mmu_prefetch_cfg = 0x00001160, .mmu_prefetch_max_offset = 0x00001164, + .bw_limiter_addr = 0x0000111C, .comp_group = CAM_SFE_BUS_WR_COMP_GRP_4, }, /* BUS Client 8 RDI0 */ @@ -657,6 +665,7 @@ static struct cam_sfe_bus_wr_hw_info sfe680_bus_wr_hw_info = { .debug_status_1 = 0x00001288, .mmu_prefetch_cfg = 0x00001260, .mmu_prefetch_max_offset = 0x00001264, + .bw_limiter_addr = 0x0000121C, .comp_group = CAM_SFE_BUS_WR_COMP_GRP_5, }, /* BUS Client 9 RDI1 */ @@ -686,6 +695,7 @@ static struct cam_sfe_bus_wr_hw_info sfe680_bus_wr_hw_info = { .debug_status_1 = 0x00001388, .mmu_prefetch_cfg = 0x00001360, .mmu_prefetch_max_offset = 0x00001364, + .bw_limiter_addr = 0x0000131C, .comp_group = CAM_SFE_BUS_WR_COMP_GRP_6, }, /* BUS Client 10 RDI2 */ @@ -715,6 +725,7 @@ static struct cam_sfe_bus_wr_hw_info sfe680_bus_wr_hw_info = { .debug_status_1 = 0x00001488, .mmu_prefetch_cfg = 0x00001460, .mmu_prefetch_max_offset = 0x00001464, + .bw_limiter_addr = 0x0000141C, .comp_group = CAM_SFE_BUS_WR_COMP_GRP_7, }, /* BUS Client 11 RDI3 */ @@ -744,6 +755,7 @@ static struct cam_sfe_bus_wr_hw_info sfe680_bus_wr_hw_info = { .debug_status_1 = 0x00001588, .mmu_prefetch_cfg = 0x00001560, .mmu_prefetch_max_offset = 0x00001564, + .bw_limiter_addr = 0x0000151C, .comp_group = CAM_SFE_BUS_WR_COMP_GRP_8, }, /* BUS Client 12 RDI4 */ @@ -773,6 +785,7 @@ static struct cam_sfe_bus_wr_hw_info sfe680_bus_wr_hw_info = { .debug_status_1 = 0x00001688, .mmu_prefetch_cfg = 0x00001660, .mmu_prefetch_max_offset = 0x00001664, + .bw_limiter_addr = 0x0000161C, .comp_group = CAM_SFE_BUS_WR_COMP_GRP_9, }, }, @@ -980,10 +993,11 @@ static struct cam_sfe_bus_wr_hw_info sfe680_bus_wr_hw_info = { .error_description = "Meta Stride unalign" }, }, - .num_comp_grp = 10, - .comp_done_shift = 17, - .line_done_cfg = 0x11, - .top_irq_shift = 0x0, + .num_comp_grp = 10, + .comp_done_shift = 17, + .line_done_cfg = 0x11, + .top_irq_shift = 0x0, + .max_bw_counter_limit = 0xFF, }; static struct cam_irq_register_set sfe680_top_irq_reg_set[1] = { diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/sfe_hw/cam_sfe_core.c b/drivers/cam_isp/isp_hw_mgr/isp_hw/sfe_hw/cam_sfe_core.c index 085cf1780c..17f68456ba 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/sfe_hw/cam_sfe_core.c +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/sfe_hw/cam_sfe_core.c @@ -335,6 +335,7 @@ int cam_sfe_process_cmd(void *hw_priv, uint32_t cmd_type, case CAM_ISP_HW_CMD_GET_SECURE_MODE: case CAM_ISP_HW_CMD_QUERY_BUS_CAP: case CAM_ISP_HW_SFE_SYS_CACHE_WM_CONFIG: + case CAM_ISP_HW_CMD_WM_BW_LIMIT_CONFIG: rc = core_info->sfe_bus_wr->hw_ops.process_cmd( core_info->sfe_bus_wr->bus_priv, cmd_type, cmd_args, arg_size); diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/sfe_hw/sfe_bus/cam_sfe_bus_wr.c b/drivers/cam_isp/isp_hw_mgr/isp_hw/sfe_hw/sfe_bus/cam_sfe_bus_wr.c index 2b29df7ff2..8e74fd314c 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/sfe_hw/sfe_bus/cam_sfe_bus_wr.c +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/sfe_hw/sfe_bus/cam_sfe_bus_wr.c @@ -89,6 +89,7 @@ struct cam_sfe_bus_wr_common_data { uint32_t addr_no_sync; uint32_t comp_done_shift; uint32_t line_done_cfg; + uint32_t max_bw_counter_limit; bool err_irq_subscribe; cam_hw_mgr_event_cb_func event_cb; @@ -2626,6 +2627,119 @@ static int cam_sfe_bus_wr_update_wm_config( return 0; } +static int cam_sfe_bus_wr_update_bw_limiter( + void *priv, void *cmd_args, uint32_t arg_size) +{ + struct cam_sfe_bus_wr_priv *bus_priv; + struct cam_isp_hw_get_cmd_update *wm_config_update; + struct cam_sfe_bus_wr_out_data *sfe_out_data = NULL; + struct cam_cdm_utils_ops *cdm_util_ops; + struct cam_sfe_bus_wr_wm_resource_data *wm_data = NULL; + struct cam_isp_wm_bw_limiter_config *wm_bw_limit_cfg = NULL; + uint32_t counter_limit = 0, reg_val = 0; + uint32_t *reg_val_pair, num_regval_pairs = 0; + uint32_t i, j, size = 0; + + bus_priv = (struct cam_sfe_bus_wr_priv *) priv; + wm_config_update = (struct cam_isp_hw_get_cmd_update *) cmd_args; + wm_bw_limit_cfg = (struct cam_isp_wm_bw_limiter_config *) + wm_config_update->data; + + sfe_out_data = (struct cam_sfe_bus_wr_out_data *) + wm_config_update->res->res_priv; + + cdm_util_ops = sfe_out_data->cdm_util_ops; + + if (!sfe_out_data || !cdm_util_ops) { + CAM_ERR(CAM_SFE, + "Failed invalid data out_data: %pK cdm_utils_ops: %pK", + sfe_out_data, cdm_util_ops); + return -EINVAL; + } + + reg_val_pair = &sfe_out_data->common_data->io_buf_update[0]; + for (i = 0, j = 0; i < sfe_out_data->num_wm; i++) { + if (j >= (MAX_REG_VAL_PAIR_SIZE - (MAX_BUF_UPDATE_REG_NUM * 2))) { + CAM_ERR(CAM_SFE, + "reg_val_pair %d exceeds the array limit %zu for WM idx %d", + j, MAX_REG_VAL_PAIR_SIZE, i); + return -ENOMEM; + } + + /* Num WMs needs to match max planes */ + if (i >= CAM_PACKET_MAX_PLANES) { + CAM_WARN(CAM_SFE, + "Num of WMs: %d exceeded max planes", i); + goto add_reg_pair; + } + + wm_data = (struct cam_sfe_bus_wr_wm_resource_data *) + sfe_out_data->wm_res[i].res_priv; + if (!wm_data->hw_regs->bw_limiter_addr) { + CAM_ERR(CAM_SFE, + "WM: %d %s has no support for bw limiter", + wm_data->index, sfe_out_data->wm_res[i].res_name); + return -EINVAL; + } + + counter_limit = wm_bw_limit_cfg->counter_limit[i]; + + /* Validate max counter limit */ + if (counter_limit > + wm_data->common_data->max_bw_counter_limit) { + CAM_WARN(CAM_SFE, + "Invalid counter limit: 0x%x capping to max: 0x%x", + wm_bw_limit_cfg->counter_limit[i], + wm_data->common_data->max_bw_counter_limit); + counter_limit = wm_data->common_data->max_bw_counter_limit; + } + + if (wm_bw_limit_cfg->enable_limiter && counter_limit) { + reg_val = 1; + reg_val |= (counter_limit << 1); + } else { + reg_val = 0; + } + + CAM_SFE_ADD_REG_VAL_PAIR(reg_val_pair, j, + wm_data->hw_regs->bw_limiter_addr, reg_val); + CAM_DBG(CAM_SFE, "WM: %d %s bw_limter: 0x%x", + wm_data->index, sfe_out_data->wm_res[i].res_name, + reg_val_pair[j-1]); + } + +add_reg_pair: + + 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) > wm_config_update->cmd.size) { + CAM_ERR(CAM_SFE, + "Failed! Buf size:%d insufficient, expected size:%d", + wm_config_update->cmd.size, size); + return -ENOMEM; + } + + cdm_util_ops->cdm_write_regrandom( + wm_config_update->cmd.cmd_buf_addr, num_regval_pairs, + reg_val_pair); + + /* cdm util returns dwords, need to convert to bytes */ + wm_config_update->cmd.used_bytes = size * 4; + } else { + CAM_DBG(CAM_SFE, + "No reg val pairs. num_wms: %u", + sfe_out_data->num_wm); + wm_config_update->cmd.used_bytes = 0; + } + + return 0; +} + static int cam_sfe_bus_wr_start_hw(void *hw_priv, void *start_hw_args, uint32_t arg_size) { @@ -2783,6 +2897,9 @@ static int cam_sfe_bus_wr_process_cmd( case CAM_ISP_HW_CMD_SET_SFE_DEBUG_CFG: rc = cam_sfe_bus_wr_set_debug_cfg(priv, cmd_args); break; + case CAM_ISP_HW_CMD_WM_BW_LIMIT_CONFIG: + rc = cam_sfe_bus_wr_update_bw_limiter(priv, cmd_args, arg_size); + break; default: CAM_ERR_RATE_LIMIT(CAM_SFE, "Invalid HW command type:%d", cmd_type); @@ -2832,21 +2949,22 @@ int cam_sfe_bus_wr_init( } sfe_bus_local->bus_priv = bus_priv; - bus_priv->num_client = hw_info->num_client; - bus_priv->num_out = hw_info->num_out; - bus_priv->num_comp_grp = hw_info->num_comp_grp; - bus_priv->top_irq_shift = hw_info->top_irq_shift; - bus_priv->common_data.num_sec_out = 0; - bus_priv->common_data.secure_mode = CAM_SECURE_MODE_NON_SECURE; - bus_priv->common_data.core_index = soc_info->index; - bus_priv->common_data.mem_base = + bus_priv->num_client = hw_info->num_client; + bus_priv->num_out = hw_info->num_out; + bus_priv->num_comp_grp = hw_info->num_comp_grp; + bus_priv->top_irq_shift = hw_info->top_irq_shift; + bus_priv->common_data.num_sec_out = 0; + bus_priv->common_data.secure_mode = CAM_SECURE_MODE_NON_SECURE; + bus_priv->common_data.core_index = soc_info->index; + bus_priv->common_data.mem_base = CAM_SOC_GET_REG_MAP_START(soc_info, SFE_CORE_BASE_IDX); - bus_priv->common_data.hw_intf = hw_intf; - bus_priv->common_data.common_reg = &hw_info->common_reg; - bus_priv->common_data.comp_done_shift = hw_info->comp_done_shift; - bus_priv->common_data.line_done_cfg = hw_info->line_done_cfg; - bus_priv->common_data.err_irq_subscribe = false; - bus_priv->common_data.sfe_irq_controller = sfe_irq_controller; + bus_priv->common_data.hw_intf = hw_intf; + bus_priv->common_data.common_reg = &hw_info->common_reg; + bus_priv->common_data.comp_done_shift = hw_info->comp_done_shift; + bus_priv->common_data.line_done_cfg = hw_info->line_done_cfg; + bus_priv->common_data.max_bw_counter_limit = hw_info->max_bw_counter_limit; + bus_priv->common_data.err_irq_subscribe = false; + bus_priv->common_data.sfe_irq_controller = sfe_irq_controller; bus_priv->constraint_error_list = hw_info->constraint_error_list; rc = cam_cpas_get_cpas_hw_version(&bus_priv->common_data.hw_version); if (rc) { diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/sfe_hw/sfe_bus/cam_sfe_bus_wr.h b/drivers/cam_isp/isp_hw_mgr/isp_hw/sfe_hw/sfe_bus/cam_sfe_bus_wr.h index c380d21da8..a8a8f9db99 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/sfe_hw/sfe_bus/cam_sfe_bus_wr.h +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/sfe_hw/sfe_bus/cam_sfe_bus_wr.h @@ -116,6 +116,7 @@ struct cam_sfe_bus_reg_offset_bus_client { uint32_t debug_status_1; uint32_t mmu_prefetch_cfg; uint32_t mmu_prefetch_max_offset; + uint32_t bw_limiter_addr; uint32_t comp_group; }; @@ -140,15 +141,16 @@ struct cam_sfe_bus_sfe_out_hw_info { * * @Brief: HW register info for entire Bus * - * @common_reg: Common register details - * @num_client: Total number of write clients - * @bus_client_reg: Bus client register info - * @sfe_out_hw_info: SFE output capability + * @common_reg: Common register details + * @num_client: Total number of write clients + * @bus_client_reg: Bus client register info + * @sfe_out_hw_info: SFE output capability * @constraint_error_list: Static list of all constraint errors - * @num_comp_grp: Number of composite groups - * @comp_done_shift: Mask shift for comp done mask - * @line_done_cfg: Line done cfg for wr/rd sync - * @top_irq_shift: Mask shift for top level BUS WR irq + * @num_comp_grp: Number of composite groups + * @comp_done_shift: Mask shift for comp done mask + * @line_done_cfg: Line done cfg for wr/rd sync + * @top_irq_shift: Mask shift for top level BUS WR irq + * @max_bw_counter_limit: Max BW counter limit */ struct cam_sfe_bus_wr_hw_info { struct cam_sfe_bus_reg_offset_common common_reg; @@ -164,6 +166,7 @@ struct cam_sfe_bus_wr_hw_info { uint32_t comp_done_shift; uint32_t line_done_cfg; uint32_t top_irq_shift; + uint32_t max_bw_counter_limit; }; /* diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/cam_vfe_core.c b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/cam_vfe_core.c index 31d93efe93..4ef53508ca 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/cam_vfe_core.c +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/cam_vfe_core.c @@ -532,6 +532,7 @@ int cam_vfe_process_cmd(void *hw_priv, uint32_t cmd_type, case CAM_ISP_HW_CMD_GET_RES_FOR_MID: case CAM_ISP_HW_CMD_QUERY_BUS_CAP: case CAM_ISP_HW_CMD_IFE_BUS_DEBUG_CFG: + case CAM_ISP_HW_CMD_WM_BW_LIMIT_CONFIG: rc = core_info->vfe_bus->hw_ops.process_cmd( core_info->vfe_bus->bus_priv, cmd_type, cmd_args, arg_size); diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe680.h b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe680.h index cfcdda6dcc..96712371c6 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe680.h +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe680.h @@ -676,6 +676,7 @@ static struct cam_vfe_bus_ver3_hw_info vfe680_bus_hw_info = { .debug_status_cfg = 0x00000E80, .debug_status_0 = 0x00000E84, .debug_status_1 = 0x00000E88, + .bw_limiter_addr = 0x00000E1C, .comp_group = CAM_VFE_BUS_VER3_COMP_GRP_0, .ubwc_regs = &vfe680_ubwc_regs_client_0, }, @@ -705,6 +706,7 @@ static struct cam_vfe_bus_ver3_hw_info vfe680_bus_hw_info = { .debug_status_cfg = 0x00000F80, .debug_status_0 = 0x00000F84, .debug_status_1 = 0x00000F88, + .bw_limiter_addr = 0x00000F1C, .comp_group = CAM_VFE_BUS_VER3_COMP_GRP_0, .ubwc_regs = &vfe680_ubwc_regs_client_1, }, @@ -731,6 +733,7 @@ static struct cam_vfe_bus_ver3_hw_info vfe680_bus_hw_info = { .debug_status_cfg = 0x00001080, .debug_status_0 = 0x00001084, .debug_status_1 = 0x00001088, + .bw_limiter_addr = 0x0000101C, .comp_group = CAM_VFE_BUS_VER3_COMP_GRP_0, .ubwc_regs = NULL, }, @@ -757,6 +760,7 @@ static struct cam_vfe_bus_ver3_hw_info vfe680_bus_hw_info = { .debug_status_cfg = 0x00001180, .debug_status_0 = 0x00001184, .debug_status_1 = 0x00001188, + .bw_limiter_addr = 0x0000111C, .comp_group = CAM_VFE_BUS_VER3_COMP_GRP_0, .ubwc_regs = NULL, }, @@ -786,6 +790,7 @@ static struct cam_vfe_bus_ver3_hw_info vfe680_bus_hw_info = { .debug_status_cfg = 0x00001280, .debug_status_0 = 0x00001284, .debug_status_1 = 0x00001288, + .bw_limiter_addr = 0x0000121C, .comp_group = CAM_VFE_BUS_VER3_COMP_GRP_1, .ubwc_regs = &vfe680_ubwc_regs_client_4, }, @@ -815,6 +820,7 @@ static struct cam_vfe_bus_ver3_hw_info vfe680_bus_hw_info = { .debug_status_cfg = 0x00001380, .debug_status_0 = 0x00001384, .debug_status_1 = 0x00001388, + .bw_limiter_addr = 0x0000131C, .comp_group = CAM_VFE_BUS_VER3_COMP_GRP_1, .ubwc_regs = &vfe680_ubwc_regs_client_5, }, @@ -841,6 +847,7 @@ static struct cam_vfe_bus_ver3_hw_info vfe680_bus_hw_info = { .debug_status_cfg = 0x00001480, .debug_status_0 = 0x00001484, .debug_status_1 = 0x00001488, + .bw_limiter_addr = 0x0000141C, .comp_group = CAM_VFE_BUS_VER3_COMP_GRP_1, .ubwc_regs = NULL, }, @@ -867,6 +874,7 @@ static struct cam_vfe_bus_ver3_hw_info vfe680_bus_hw_info = { .debug_status_cfg = 0x00001580, .debug_status_0 = 0x00001584, .debug_status_1 = 0x00001588, + .bw_limiter_addr = 0x0000151C, .comp_group = CAM_VFE_BUS_VER3_COMP_GRP_1, .ubwc_regs = NULL, }, @@ -896,6 +904,7 @@ static struct cam_vfe_bus_ver3_hw_info vfe680_bus_hw_info = { .debug_status_cfg = 0x00001680, .debug_status_0 = 0x00001684, .debug_status_1 = 0x00001688, + .bw_limiter_addr = 0x0000161C, .comp_group = CAM_VFE_BUS_VER3_COMP_GRP_2, .ubwc_regs = NULL, }, @@ -922,6 +931,7 @@ static struct cam_vfe_bus_ver3_hw_info vfe680_bus_hw_info = { .debug_status_cfg = 0x00001780, .debug_status_0 = 0x00001784, .debug_status_1 = 0x00001788, + .bw_limiter_addr = 0x0000171C, .comp_group = CAM_VFE_BUS_VER3_COMP_GRP_2, .ubwc_regs = NULL, }, @@ -951,6 +961,7 @@ static struct cam_vfe_bus_ver3_hw_info vfe680_bus_hw_info = { .debug_status_cfg = 0x00001880, .debug_status_0 = 0x00001884, .debug_status_1 = 0x00001888, + .bw_limiter_addr = 0x0000181C, .comp_group = CAM_VFE_BUS_VER3_COMP_GRP_3, .ubwc_regs = NULL, }, @@ -980,6 +991,7 @@ static struct cam_vfe_bus_ver3_hw_info vfe680_bus_hw_info = { .debug_status_cfg = 0x00001980, .debug_status_0 = 0x00001984, .debug_status_1 = 0x00001988, + .bw_limiter_addr = 0x0000191C, .comp_group = CAM_VFE_BUS_VER3_COMP_GRP_4, .ubwc_regs = NULL, }, @@ -1009,6 +1021,7 @@ static struct cam_vfe_bus_ver3_hw_info vfe680_bus_hw_info = { .debug_status_cfg = 0x00001A80, .debug_status_0 = 0x00001A84, .debug_status_1 = 0x00001A88, + .bw_limiter_addr = 0x00001A1C, .comp_group = CAM_VFE_BUS_VER3_COMP_GRP_4, .ubwc_regs = NULL, }, @@ -1038,6 +1051,7 @@ static struct cam_vfe_bus_ver3_hw_info vfe680_bus_hw_info = { .debug_status_cfg = 0x00001B80, .debug_status_0 = 0x00001B84, .debug_status_1 = 0x00001B88, + .bw_limiter_addr = 0x00001B1C, .comp_group = CAM_VFE_BUS_VER3_COMP_GRP_5, .ubwc_regs = NULL, }, @@ -1067,6 +1081,7 @@ static struct cam_vfe_bus_ver3_hw_info vfe680_bus_hw_info = { .debug_status_cfg = 0x00001C80, .debug_status_0 = 0x00001C84, .debug_status_1 = 0x00001C88, + .bw_limiter_addr = 0x00001C1C, .comp_group = CAM_VFE_BUS_VER3_COMP_GRP_6, .ubwc_regs = NULL, }, @@ -1096,6 +1111,7 @@ static struct cam_vfe_bus_ver3_hw_info vfe680_bus_hw_info = { .debug_status_cfg = 0x00001D80, .debug_status_0 = 0x00001D84, .debug_status_1 = 0x00001D88, + .bw_limiter_addr = 0x00001D1C, .comp_group = CAM_VFE_BUS_VER3_COMP_GRP_6, .ubwc_regs = NULL, }, @@ -1125,6 +1141,7 @@ static struct cam_vfe_bus_ver3_hw_info vfe680_bus_hw_info = { .debug_status_cfg = 0x00001E80, .debug_status_0 = 0x00001E84, .debug_status_1 = 0x00001E88, + .bw_limiter_addr = 0x00001E1C, .comp_group = CAM_VFE_BUS_VER3_COMP_GRP_7, .ubwc_regs = NULL, }, @@ -1154,6 +1171,7 @@ static struct cam_vfe_bus_ver3_hw_info vfe680_bus_hw_info = { .debug_status_cfg = 0x00001F80, .debug_status_0 = 0x00001F84, .debug_status_1 = 0x00001F88, + .bw_limiter_addr = 0x00001F1C, .comp_group = CAM_VFE_BUS_VER3_COMP_GRP_8, .ubwc_regs = NULL, }, @@ -1183,6 +1201,7 @@ static struct cam_vfe_bus_ver3_hw_info vfe680_bus_hw_info = { .debug_status_cfg = 0x00002080, .debug_status_0 = 0x00002084, .debug_status_1 = 0x00002088, + .bw_limiter_addr = 0x0000201C, .comp_group = CAM_VFE_BUS_VER3_COMP_GRP_9, .ubwc_regs = NULL, }, @@ -1212,6 +1231,7 @@ static struct cam_vfe_bus_ver3_hw_info vfe680_bus_hw_info = { .debug_status_cfg = 0x00002180, .debug_status_0 = 0x00002184, .debug_status_1 = 0x00002188, + .bw_limiter_addr = 0x0000211C, .comp_group = CAM_VFE_BUS_VER3_COMP_GRP_10, .ubwc_regs = NULL, }, @@ -1241,6 +1261,7 @@ static struct cam_vfe_bus_ver3_hw_info vfe680_bus_hw_info = { .debug_status_cfg = 0x00002280, .debug_status_0 = 0x00002284, .debug_status_1 = 0x00002288, + .bw_limiter_addr = 0x0000221C, .comp_group = CAM_VFE_BUS_VER3_COMP_GRP_12, .ubwc_regs = NULL, }, @@ -1270,6 +1291,7 @@ static struct cam_vfe_bus_ver3_hw_info vfe680_bus_hw_info = { .debug_status_cfg = 0x00002380, .debug_status_0 = 0x00002384, .debug_status_1 = 0x00002388, + .bw_limiter_addr = 0x0000231C, .comp_group = CAM_VFE_BUS_VER3_COMP_GRP_13, .ubwc_regs = NULL, }, @@ -1299,6 +1321,7 @@ static struct cam_vfe_bus_ver3_hw_info vfe680_bus_hw_info = { .debug_status_cfg = 0x00002480, .debug_status_0 = 0x00002484, .debug_status_1 = 0x00002488, + .bw_limiter_addr = 0x0000241C, .comp_group = CAM_VFE_BUS_VER3_COMP_GRP_13, .ubwc_regs = NULL, }, @@ -1328,6 +1351,7 @@ static struct cam_vfe_bus_ver3_hw_info vfe680_bus_hw_info = { .debug_status_cfg = 0x00002580, .debug_status_0 = 0x00002584, .debug_status_1 = 0x00002588, + .bw_limiter_addr = 0x0000251C, .comp_group = CAM_VFE_BUS_VER3_COMP_GRP_11, .ubwc_regs = NULL, }, @@ -1357,6 +1381,7 @@ static struct cam_vfe_bus_ver3_hw_info vfe680_bus_hw_info = { .debug_status_cfg = 0x00002680, .debug_status_0 = 0x00002684, .debug_status_1 = 0x00002688, + .bw_limiter_addr = 0x0000261C, .comp_group = CAM_VFE_BUS_VER3_COMP_GRP_14, .ubwc_regs = NULL, }, @@ -1386,6 +1411,7 @@ static struct cam_vfe_bus_ver3_hw_info vfe680_bus_hw_info = { .debug_status_cfg = 0x00002780, .debug_status_0 = 0x00002784, .debug_status_1 = 0x00002788, + .bw_limiter_addr = 0x0000271C, .comp_group = CAM_VFE_BUS_VER3_COMP_GRP_15, .ubwc_regs = NULL, }, @@ -1415,6 +1441,7 @@ static struct cam_vfe_bus_ver3_hw_info vfe680_bus_hw_info = { .debug_status_cfg = 0x00002880, .debug_status_0 = 0x00002884, .debug_status_1 = 0x00002888, + .bw_limiter_addr = 0x0000281C, .comp_group = CAM_VFE_BUS_VER3_COMP_GRP_16, .ubwc_regs = NULL, }, @@ -1444,6 +1471,7 @@ static struct cam_vfe_bus_ver3_hw_info vfe680_bus_hw_info = { .debug_status_cfg = 0x00002980, .debug_status_0 = 0x00002984, .debug_status_1 = 0x00002988, + .bw_limiter_addr = 0x0000291C, .comp_group = CAM_VFE_BUS_VER3_COMP_GRP_3, .ubwc_regs = NULL, }, @@ -1909,12 +1937,13 @@ static struct cam_vfe_bus_ver3_hw_info vfe680_bus_hw_info = { .error_description = "Meta Stride unalign" }, }, - .num_comp_grp = 17, + .num_comp_grp = 17, .support_consumed_addr = true, - .comp_done_shift = 0, - .top_irq_shift = 1, - .max_out_res = CAM_ISP_IFE_OUT_RES_BASE + 33, - .pack_align_shift = 5, + .comp_done_shift = 0, + .top_irq_shift = 1, + .max_out_res = CAM_ISP_IFE_OUT_RES_BASE + 33, + .pack_align_shift = 5, + .max_bw_counter_limit = 0xFF, }; static struct cam_vfe_irq_hw_info vfe680_irq_hw_info = { diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver3.c b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver3.c index 45722161c0..6653d11ba3 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver3.c +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver3.c @@ -104,6 +104,7 @@ struct cam_vfe_bus_ver3_common_data { cam_hw_mgr_event_cb_func event_cb; int rup_irq_handle[CAM_VFE_BUS_VER3_SRC_GRP_MAX]; uint32_t pack_align_shift; + uint32_t max_bw_counter_limit; }; struct cam_vfe_bus_ver3_wm_resource_data { @@ -2948,7 +2949,11 @@ static int cam_vfe_bus_ver3_update_ubwc_regs( CAM_DBG(CAM_ISP, "WM:%d off_lossy_var 0x%X", wm_data->index, reg_val_pair[*j-1]); - if (wm_data->ubwc_bandwidth_limit) { + /* + * If limit value >= 0xFFFF, limit configured by + * generic limiter blob + */ + if (wm_data->ubwc_bandwidth_limit < 0xFFFF) { CAM_VFE_ADD_REG_VAL_PAIR(reg_val_pair, *j, ubwc_regs->bw_limit, wm_data->ubwc_bandwidth_limit); CAM_DBG(CAM_ISP, "WM:%d ubwc bw limit 0x%X", @@ -3540,6 +3545,120 @@ static int cam_vfe_bus_ver3_update_wm_config( return 0; } +static int cam_vfe_bus_update_bw_limiter( + void *priv, void *cmd_args, uint32_t arg_size) +{ + struct cam_vfe_bus_ver3_priv *bus_priv; + struct cam_isp_hw_get_cmd_update *wm_config_update; + struct cam_vfe_bus_ver3_vfe_out_data *vfe_out_data = NULL; + struct cam_cdm_utils_ops *cdm_util_ops; + struct cam_vfe_bus_ver3_wm_resource_data *wm_data = NULL; + struct cam_isp_wm_bw_limiter_config *wm_bw_limit_cfg = NULL; + uint32_t counter_limit = 0, reg_val = 0; + uint32_t *reg_val_pair, num_regval_pairs = 0; + uint32_t i, j, size = 0; + + bus_priv = (struct cam_vfe_bus_ver3_priv *) priv; + wm_config_update = (struct cam_isp_hw_get_cmd_update *) cmd_args; + wm_bw_limit_cfg = (struct cam_isp_wm_bw_limiter_config *) + wm_config_update->data; + + vfe_out_data = (struct cam_vfe_bus_ver3_vfe_out_data *) + wm_config_update->res->res_priv; + + cdm_util_ops = vfe_out_data->cdm_util_ops; + + if (!vfe_out_data || !cdm_util_ops) { + CAM_ERR(CAM_ISP, + "Failed invalid data out_data: %pK cdm_utils_ops: %pK", + vfe_out_data, cdm_util_ops); + return -EINVAL; + } + + reg_val_pair = &vfe_out_data->common_data->io_buf_update[0]; + for (i = 0, j = 0; i < vfe_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 for WM idx %d", + j, MAX_REG_VAL_PAIR_SIZE, i); + return -ENOMEM; + } + + /* Num WMs needs to match max planes */ + if (i >= CAM_PACKET_MAX_PLANES) { + CAM_WARN(CAM_ISP, + "Num of WMs: %d exceeded max planes", i); + goto add_reg_pair; + } + + wm_data = (struct cam_vfe_bus_ver3_wm_resource_data *) + vfe_out_data->wm_res[i].res_priv; + if (!wm_data->hw_regs->bw_limiter_addr) { + CAM_ERR(CAM_ISP, + "WM: %d %s has no support for bw limiter", + wm_data->index, vfe_out_data->wm_res[i].res_name); + return -EINVAL; + } + + counter_limit = wm_bw_limit_cfg->counter_limit[i]; + + /* Validate max counter limit */ + if (counter_limit > + wm_data->common_data->max_bw_counter_limit) { + CAM_WARN(CAM_ISP, + "Invalid counter limit: 0x%x capping to max: 0x%x", + wm_bw_limit_cfg->counter_limit[i], + wm_data->common_data->max_bw_counter_limit); + counter_limit = + wm_data->common_data->max_bw_counter_limit; + } + + if (wm_bw_limit_cfg->enable_limiter && counter_limit) { + reg_val = 1; + reg_val |= (counter_limit << 1); + } else { + reg_val = 0; + } + + CAM_VFE_ADD_REG_VAL_PAIR(reg_val_pair, j, + wm_data->hw_regs->bw_limiter_addr, reg_val); + CAM_DBG(CAM_ISP, "WM: %d for %s bw_limter: 0x%x", + wm_data->index, vfe_out_data->wm_res[i].res_name, + reg_val_pair[j-1]); + } + +add_reg_pair: + + 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) > wm_config_update->cmd.size) { + CAM_ERR(CAM_ISP, + "Failed! Buf size:%d insufficient, expected size:%d", + wm_config_update->cmd.size, size); + return -ENOMEM; + } + + cdm_util_ops->cdm_write_regrandom( + wm_config_update->cmd.cmd_buf_addr, num_regval_pairs, + reg_val_pair); + + /* cdm util returns dwords, need to convert to bytes */ + wm_config_update->cmd.used_bytes = size * 4; + } else { + CAM_DBG(CAM_ISP, + "No reg val pairs. num_wms: %u", + vfe_out_data->num_wm); + wm_config_update->cmd.used_bytes = 0; + } + + return 0; +} + static int cam_vfe_bus_ver3_start_hw(void *hw_priv, void *start_hw_args, uint32_t arg_size) { @@ -3739,6 +3858,9 @@ static int cam_vfe_bus_ver3_process_cmd( "disabled" : "enabled"); rc = 0; break; + case CAM_ISP_HW_CMD_WM_BW_LIMIT_CONFIG: + rc = cam_vfe_bus_update_bw_limiter(priv, cmd_args, arg_size); + break; default: CAM_ERR_RATE_LIMIT(CAM_ISP, "Invalid camif process command:%d", cmd_type); @@ -3823,6 +3945,8 @@ int cam_vfe_bus_ver3_init( bus_priv->common_data.disable_mmu_prefetch = false; bus_priv->common_data.pack_align_shift = ver3_hw_info->pack_align_shift; + bus_priv->common_data.max_bw_counter_limit = + ver3_hw_info->max_bw_counter_limit; bus_priv->constraint_error_list = ver3_hw_info->constraint_error_list; if (bus_priv->num_out >= CAM_VFE_BUS_VER3_VFE_OUT_MAX) { diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver3.h b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver3.h index b1f85c87c0..64a4745e03 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver3.h +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver3.h @@ -174,6 +174,7 @@ struct cam_vfe_bus_ver3_reg_offset_bus_client { uint32_t debug_status_cfg; uint32_t debug_status_0; uint32_t debug_status_1; + uint32_t bw_limiter_addr; uint32_t comp_group; }; @@ -212,6 +213,7 @@ struct cam_vfe_bus_ver3_vfe_out_hw_info { * @supported_irq: Mask to indicate the IRQ supported * @comp_cfg_needed: Composite group config is needed for hw * @pack_align_shift: Shift value for alignment of packer format + * @max_bw_counter_limit: Max BW counter limit */ struct cam_vfe_bus_ver3_hw_info { struct cam_vfe_bus_ver3_reg_offset_common common_reg; @@ -231,6 +233,7 @@ struct cam_vfe_bus_ver3_hw_info { uint32_t supported_irq; bool comp_cfg_needed; uint32_t pack_align_shift; + uint32_t max_bw_counter_limit; }; /* diff --git a/include/uapi/camera/media/cam_defs.h b/include/uapi/camera/media/cam_defs.h index a6372cab29..da4eb13d61 100644 --- a/include/uapi/camera/media/cam_defs.h +++ b/include/uapi/camera/media/cam_defs.h @@ -333,6 +333,10 @@ struct cam_ubwc_plane_cfg_v1 { * @lossy_threshold0 UBWC lossy threshold 0 * @lossy_threshold1 UBWC lossy threshold 1 * @lossy_var_offset UBWC offset variance thrshold + * @bandwidth_limit: BW counter limit + * BW limiter config skipped if value is 0xFFFF or more + * If skipped here, use generic BW limiter blob to + * configure the appropriate value. * */ struct cam_ubwc_plane_cfg_v2 { diff --git a/include/uapi/camera/media/cam_isp.h b/include/uapi/camera/media/cam_isp.h index a48a0500a4..5716aea8bf 100644 --- a/include/uapi/camera/media/cam_isp.h +++ b/include/uapi/camera/media/cam_isp.h @@ -121,6 +121,7 @@ #define CAM_ISP_GENERIC_BLOB_TYPE_SENSOR_BLANKING_CONFIG 13 #define CAM_ISP_GENERIC_BLOB_TYPE_TPG_CORE_CONFIG 14 #define CAM_ISP_GENERIC_BLOB_TYPE_DYNAMIC_MODE_SWITCH 15 +#define CAM_ISP_GENERIC_BLOB_TYPE_BW_LIMITER_CFG 16 #define CAM_ISP_GENERIC_BLOB_TYPE_SFE_CLOCK_CONFIG 21 #define CAM_ISP_GENERIC_BLOB_TYPE_SFE_CORE_CONFIG 22 #define CAM_ISP_GENERIC_BLOB_TYPE_SFE_OUT_CONFIG 23 @@ -932,6 +933,39 @@ struct cam_isp_discard_initial_frames { __u32 discard_params[5]; } __attribute__((packed)); +/** + * struct cam_isp_wm_bw_limiter_config - ISP write master + * BW limter config + * + * + * @res_type : output resource type defined in file + * cam_isp_sfe.h or cam_isp_ife.h + * @enable_limiter : 0 for disable else enabled + * @counter_limit : Max counter value + * @additional_params : Params for future use + */ +struct cam_isp_wm_bw_limiter_config { + __u32 res_type; + __u32 enable_limiter; + __u32 counter_limit[CAM_PACKET_MAX_PLANES]; + __u32 additional_params[5]; +}; + +/** + * struct cam_isp_out_rsrc_bw_limiter_config - ISP out rsrc BW limiter config + * + * Configure BW limiter for ISP WMs + * + * @num_ports : Number of ports + * @reserved : Reserved field + * @bw_limit_config : WM BW limiter config + */ +struct cam_isp_out_rsrc_bw_limiter_config { + __u32 num_ports; + __u32 reserved; + struct cam_isp_wm_bw_limiter_config bw_limiter_config[1]; +}; + #define CAM_ISP_ACQUIRE_COMMON_VER0 0x1000 #define CAM_ISP_ACQUIRE_COMMON_SIZE_VER0 0x0