From c98bea4b04dd597d595959a48142d5667f445038 Mon Sep 17 00:00:00 2001 From: Yash Upadhyay Date: Mon, 12 Jun 2023 14:41:38 +0530 Subject: [PATCH] msm: camera: tfe: Add support for TFE BW limiter Add blob to allow userland to configure BW limter for TFE WMs. CRs-Fixed: 3505174 Change-Id: I5c671cbcfa5557082c4ae5302471a2ece45294ab Signed-off-by: Dharmender Sharma Signed-off-by: Yash Upadhyay --- drivers/cam_isp/isp_hw_mgr/cam_tfe_hw_mgr.c | 153 ++++++++++++++++++ .../isp_hw_mgr/include/cam_isp_hw_mgr_intf.h | 27 ++-- .../isp_hw_mgr/isp_hw/tfe_hw/cam_tfe530.h | 4 + .../isp_hw_mgr/isp_hw/tfe_hw/cam_tfe640.h | 4 + .../isp_hw_mgr/isp_hw/tfe_hw/cam_tfe_bus.c | 116 ++++++++++++- .../isp_hw_mgr/isp_hw/tfe_hw/cam_tfe_bus.h | 7 + .../isp_hw_mgr/isp_hw/tfe_hw/cam_tfe_core.c | 1 + include/uapi/camera/media/cam_tfe.h | 32 ++++ 8 files changed, 329 insertions(+), 15 deletions(-) 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 7dd7482b50..44a49d9ca5 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 @@ -3887,6 +3887,137 @@ static int cam_isp_tfe_blob_clock_update( return rc; } +static int cam_isp_tfe_blob_bw_limit_update( + uint32_t blob_type, + struct cam_isp_generic_blob_info *blob_info, + struct cam_isp_tfe_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_tfe_wm_bw_limiter_config *wm_bw_limit_cfg; + struct cam_kmd_buf_info *kmd_buf_info; + struct cam_tfe_hw_mgr_ctx *ctx = NULL; + struct cam_isp_hw_mgr_res *hw_mgr_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; + + CAM_DBG(CAM_ISP, "%s BW limit config idx: %d port: 0x%x enable: %d [0x%x:0x%x]", + "TFE", 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); + + hw_mgr_res = &ctx->res_list_tfe_out[res_id_out]; + + rc = cam_isp_add_cmd_buf_update( + hw_mgr_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", + "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) { + /* Update the HW entries */ + 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_tfe_validate_bw_limiter_blob( + uint32_t blob_size, + struct cam_isp_tfe_out_rsrc_bw_limiter_config *bw_limit_config) +{ + /* Check for blob version */ + if (bw_limit_config->version != CAM_TFE_BW_LIMITER_CONFIG_V1) { + CAM_ERR(CAM_ISP, "Invalid Blob config version:%d", bw_limit_config->version); + return -EINVAL; + } + /* Check for number of out ports*/ + if (bw_limit_config->num_ports > CAM_TFE_HW_OUT_RES_MAX) { + CAM_ERR(CAM_ISP, "Invalid num_ports:%u", bw_limit_config->num_ports); + return -EINVAL; + } + /* Check for integer overflow */ + if (bw_limit_config->num_ports != 1) { + if (sizeof(struct cam_isp_tfe_wm_bw_limiter_config) > ((UINT_MAX - + sizeof(struct cam_isp_tfe_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_tfe_wm_bw_limiter_config)); + return -EINVAL; + } + } + if (blob_size < (sizeof(struct cam_isp_tfe_out_rsrc_bw_limiter_config) + + (bw_limit_config->num_ports - 1) * + sizeof(struct cam_isp_tfe_wm_bw_limiter_config))) { + CAM_ERR(CAM_ISP, "Invalid blob size %u expected %lu", + blob_size, sizeof(struct cam_isp_tfe_out_rsrc_bw_limiter_config) + + (bw_limit_config->num_ports - 1) * + sizeof(struct cam_isp_tfe_wm_bw_limiter_config)); + return -EINVAL; + } + return 0; +} + static int cam_isp_tfe_packet_generic_blob_handler(void *user_data, uint32_t blob_type, uint32_t blob_size, uint8_t *blob_data) { @@ -4092,6 +4223,28 @@ static int cam_isp_tfe_packet_generic_blob_handler(void *user_data, CAM_ERR(CAM_ISP, "Clock Update Failed"); } break; + case CAM_ISP_TFE_GENERIC_BLOB_TYPE_BW_LIMITER_CFG: { + struct cam_isp_tfe_out_rsrc_bw_limiter_config *bw_limit_config; + + if (blob_size < + sizeof(struct cam_isp_tfe_out_rsrc_bw_limiter_config)) { + CAM_ERR(CAM_ISP, "Invalid blob size %u expected %lu", + blob_size, + sizeof(struct cam_isp_tfe_out_rsrc_bw_limiter_config)); + return -EINVAL; + } + + bw_limit_config = (struct cam_isp_tfe_out_rsrc_bw_limiter_config *)blob_data; + rc = cam_isp_tfe_validate_bw_limiter_blob(blob_size, bw_limit_config); + if (rc) + return rc; + + rc = cam_isp_tfe_blob_bw_limit_update(blob_type, blob_info, + bw_limit_config, prepare, CAM_ISP_HW_TYPE_TFE); + if (rc) + CAM_ERR(CAM_ISP, "BW limit update failed for TFE rc: %d", rc); + } + break; default: CAM_WARN(CAM_ISP, "Invalid blob type %d", blob_type); break; 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 ca736475f4..592877a941 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 @@ -16,19 +16,20 @@ #include "cam_cpas_api.h" /* MAX IFE instance */ -#define CAM_IFE_HW_NUM_MAX 8 -#define CAM_SFE_HW_NUM_MAX 3 -#define CAM_IFE_RDI_NUM_MAX 4 -#define CAM_SFE_RDI_NUM_MAX 5 -#define CAM_SFE_FE_RDI_NUM_MAX 3 -#define CAM_ISP_BW_CONFIG_V1 1 -#define CAM_ISP_BW_CONFIG_V2 2 -#define CAM_ISP_BW_CONFIG_V3 2 -#define CAM_TFE_HW_NUM_MAX 3 -#define CAM_TFE_RDI_NUM_MAX 3 -#define CAM_IFE_SCRATCH_NUM_MAX 2 -#define CAM_IFE_BUS_COMP_NUM_MAX 18 -#define CAM_SFE_BUS_COMP_NUM_MAX 12 +#define CAM_IFE_HW_NUM_MAX 8 +#define CAM_SFE_HW_NUM_MAX 3 +#define CAM_IFE_RDI_NUM_MAX 4 +#define CAM_SFE_RDI_NUM_MAX 5 +#define CAM_SFE_FE_RDI_NUM_MAX 3 +#define CAM_ISP_BW_CONFIG_V1 1 +#define CAM_ISP_BW_CONFIG_V2 2 +#define CAM_ISP_BW_CONFIG_V3 2 +#define CAM_TFE_HW_NUM_MAX 3 +#define CAM_TFE_RDI_NUM_MAX 3 +#define CAM_IFE_SCRATCH_NUM_MAX 2 +#define CAM_IFE_BUS_COMP_NUM_MAX 18 +#define CAM_SFE_BUS_COMP_NUM_MAX 12 +#define CAM_TFE_BW_LIMITER_CONFIG_V1 1 /* maximum context numbers for TFE */ #define CAM_TFE_CTX_MAX 4 diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_hw/cam_tfe530.h b/drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_hw/cam_tfe530.h index 030872e29c..bd9e868c48 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_hw/cam_tfe530.h +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_hw/cam_tfe530.h @@ -1,6 +1,7 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* * Copyright (c) 2019-2021, The Linux Foundation. All rights reserved. + * Copyright (c) 2023 Qualcomm Innovation Center, Inc. All rights reserved. */ @@ -855,6 +856,9 @@ static struct cam_tfe_bus_hw_info tfe530_bus_hw_info = { .support_consumed_addr = true, .pdaf_rdi2_mux_en = true, .rdi_width = 64, + .max_bw_counter_limit = 0xFF, + .counter_limit_shift = 1, + .counter_limit_mask = 0xF, }; struct cam_tfe_hw_info cam_tfe530 = { diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_hw/cam_tfe640.h b/drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_hw/cam_tfe640.h index 261d2c6b47..42b05515a0 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_hw/cam_tfe640.h +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_hw/cam_tfe640.h @@ -1,6 +1,7 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* * Copyright (c) 2021, The Linux Foundation. All rights reserved. + * Copyright (c) 2023 Qualcomm Innovation Center, Inc. All rights reserved. */ @@ -1170,6 +1171,9 @@ static struct cam_tfe_bus_hw_info tfe640_bus_hw_info = { .support_consumed_addr = true, .pdaf_rdi2_mux_en = false, .rdi_width = 128, + .max_bw_counter_limit = 0xFF, + .counter_limit_shift = 1, + .counter_limit_mask = 0xF, }; struct cam_tfe_hw_info cam_tfe640 = { 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 f70d5e4f22..b871dc565b 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 @@ -1,7 +1,7 @@ // SPDX-License-Identifier: GPL-2.0-only /* * Copyright (c) 2019-2021, The Linux Foundation. All rights reserved. - * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved. + * Copyright (c) 2022-2023 Qualcomm Innovation Center, Inc. All rights reserved. */ #include @@ -75,6 +75,9 @@ struct cam_tfe_bus_common_data { cam_hw_mgr_event_cb_func event_cb; bool rup_irq_enable[CAM_TFE_BUS_RUP_GRP_MAX]; bool pdaf_rdi2_mux_en; + uint32_t max_bw_counter_limit; + uint32_t counter_limit_shift; + uint32_t counter_limit_mask; }; struct cam_tfe_bus_wm_resource_data { @@ -104,6 +107,7 @@ struct cam_tfe_bus_wm_resource_data { uint32_t acquired_width; uint32_t acquired_height; uint32_t acquired_stride; + bool limiter_blob_status; }; struct cam_tfe_bus_comp_grp_data { @@ -848,6 +852,7 @@ static int cam_tfe_bus_release_wm(void *bus_priv, rsrc_data->framedrop_pattern = 0; rsrc_data->en_cfg = 0; rsrc_data->is_dual = 0; + rsrc_data->limiter_blob_status = false; wm_res->tasklet_info = NULL; wm_res->res_state = CAM_ISP_RESOURCE_STATE_AVAILABLE; @@ -865,7 +870,10 @@ static int cam_tfe_bus_start_wm(struct cam_isp_resource_node *wm_res) struct cam_tfe_bus_common_data *common_data = rsrc_data->common_data; - cam_io_w(0xf, common_data->mem_base + rsrc_data->hw_regs->bw_limit); + /* Skip to overwrite if wm bandwidth limiter blob already sent */ + if (!rsrc_data->limiter_blob_status) + cam_io_w(rsrc_data->common_data->counter_limit_mask, + common_data->mem_base + rsrc_data->hw_regs->bw_limit); cam_io_w((rsrc_data->height << 16) | rsrc_data->width, common_data->mem_base + rsrc_data->hw_regs->image_cfg_0); @@ -2309,6 +2317,104 @@ end: return 0; } +static int cam_tfe_bus_update_bw_limiter( + void *priv, void *cmd_args, uint32_t arg_size) +{ + struct cam_tfe_bus_priv *bus_priv; + struct cam_isp_hw_get_cmd_update *wm_config_update; + struct cam_tfe_bus_tfe_out_data *tfe_out_data = NULL; + struct cam_cdm_utils_ops *cdm_util_ops; + struct cam_tfe_bus_wm_resource_data *wm_data = NULL; + struct cam_isp_tfe_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_tfe_bus_priv *) priv; + wm_config_update = (struct cam_isp_hw_get_cmd_update *) cmd_args; + wm_bw_limit_cfg = (struct cam_isp_tfe_wm_bw_limiter_config *) wm_config_update->data; + + tfe_out_data = (struct cam_tfe_bus_tfe_out_data *) wm_config_update->res->res_priv; + if (!tfe_out_data || !tfe_out_data->cdm_util_ops) { + CAM_ERR(CAM_ISP, "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 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_tfe_bus_wm_resource_data *) tfe_out_data->wm_res[i]->res_priv; + if (!wm_data->hw_regs->bw_limit) { + CAM_ERR(CAM_ISP, + "WM: %d %s has no support for bw limiter", + wm_data->index, tfe_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 << wm_data->common_data->counter_limit_shift); + } else { + reg_val = 0; + } + + wm_data->limiter_blob_status = true; + + CAM_TFE_ADD_REG_VAL_PAIR(reg_val_pair, j, wm_data->hw_regs->bw_limit, reg_val); + CAM_DBG(CAM_ISP, "WM: %d for %s bw_limter: 0x%x", + wm_data->index, tfe_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", tfe_out_data->num_wm); + wm_config_update->cmd.used_bytes = 0; + } + + return 0; +} + static int cam_tfe_bus_dump_bus_info( struct cam_tfe_bus_priv *bus_priv, void *cmd_args, uint32_t arg_size) @@ -2484,6 +2590,9 @@ static int cam_tfe_bus_process_cmd(void *priv, pdaf_rdi2_mux_en = (bool *)cmd_args; *pdaf_rdi2_mux_en = bus_priv->common_data.pdaf_rdi2_mux_en; break; + case CAM_ISP_HW_CMD_WM_BW_LIMIT_CONFIG: + rc = cam_tfe_bus_update_bw_limiter(priv, cmd_args, arg_size); + break; default: CAM_ERR_RATE_LIMIT(CAM_ISP, "Invalid camif process command:%d", cmd_type); @@ -2550,6 +2659,9 @@ int cam_tfe_bus_init( hw_info->support_consumed_addr; bus_priv->common_data.pdaf_rdi2_mux_en = hw_info->pdaf_rdi2_mux_en; bus_priv->common_data.rdi_width = hw_info->rdi_width; + bus_priv->common_data.max_bw_counter_limit = hw_info->max_bw_counter_limit; + bus_priv->common_data.counter_limit_shift = hw_info->counter_limit_shift; + bus_priv->common_data.counter_limit_mask = hw_info->counter_limit_mask; for (i = 0; i < CAM_TFE_BUS_IRQ_REGISTERS_MAX; i++) bus_priv->bus_irq_error_mask[i] = diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_hw/cam_tfe_bus.h b/drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_hw/cam_tfe_bus.h index 62e3d5ab5a..58f65f9c7e 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_hw/cam_tfe_bus.h +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_hw/cam_tfe_bus.h @@ -1,6 +1,7 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* * Copyright (c) 2019-2021, The Linux Foundation. All rights reserved. + * Copyright (c) 2023 Qualcomm Innovation Center, Inc. All rights reserved. */ @@ -195,6 +196,9 @@ struct cam_tfe_bus_tfe_out_hw_info { * @rdi_width: RDI WM width * @support_consumed_addr: Indicate if bus support consumed address * @pdaf_rdi2_mux_en: Indicate is PDAF is muxed with RDI2 + * @max_bw_counter_limit: Max BW counter limit + * @counter_limit_shift: Mask shift for BW counter limit + * @counter_limit_mask: Default Mask of BW limit counter */ struct cam_tfe_bus_hw_info { struct cam_tfe_bus_reg_offset_common common_reg; @@ -214,6 +218,9 @@ struct cam_tfe_bus_hw_info { uint32_t rdi_width; bool support_consumed_addr; bool pdaf_rdi2_mux_en; + uint32_t max_bw_counter_limit; + uint32_t counter_limit_shift; + uint32_t counter_limit_mask; }; /* 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 bd69662dbb..38881228c1 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 @@ -2919,6 +2919,7 @@ int cam_tfe_process_cmd(void *hw_priv, uint32_t cmd_type, case CAM_ISP_HW_CMD_GET_RES_FOR_MID: case CAM_ISP_HW_CMD_DUMP_BUS_INFO: case CAM_ISP_HW_CMD_IS_PDAF_RDI2_MUX_EN: + case CAM_ISP_HW_CMD_WM_BW_LIMIT_CONFIG: rc = core_info->tfe_bus->hw_ops.process_cmd( core_info->tfe_bus->bus_priv, cmd_type, cmd_args, arg_size); diff --git a/include/uapi/camera/media/cam_tfe.h b/include/uapi/camera/media/cam_tfe.h index e384407881..7b9b008b22 100644 --- a/include/uapi/camera/media/cam_tfe.h +++ b/include/uapi/camera/media/cam_tfe.h @@ -1,6 +1,7 @@ /* SPDX-License-Identifier: GPL-2.0-only WITH Linux-syscall-note */ /* * Copyright (c) 2019-2021, The Linux Foundation. All rights reserved. + * Copyright (c) 2023, Qualcomm Innovation Center, Inc. All rights reserved. */ #ifndef __UAPI_CAM_TFE_H__ @@ -71,6 +72,7 @@ #define CAM_ISP_TFE_GENERIC_BLOB_TYPE_CLOCK_CONFIG 1 #define CAM_ISP_TFE_GENERIC_BLOB_TYPE_BW_CONFIG_V2 2 #define CAM_ISP_TFE_GENERIC_BLOB_TYPE_CSID_CLOCK_CONFIG 3 +#define CAM_ISP_TFE_GENERIC_BLOB_TYPE_BW_LIMITER_CFG 16 /* DSP mode */ #define CAM_ISP_TFE_DSP_MODE_NONE 0 @@ -473,6 +475,36 @@ struct cam_isp_tfe_acquire_hw_info { __u64 data; }; +/** + * struct cam_isp_tfe_wm_bw_limiter_config - ISP TFE write master + * BW limter config + * + * + * @res_type : output resource type defined in file cam_isp_tfe.h + * @enable_limiter : 0 for disable else enabled + * @counter_limit : Max counter value + */ +struct cam_isp_tfe_wm_bw_limiter_config { + __u32 res_type; + __u32 enable_limiter; + __u32 counter_limit[CAM_PACKET_MAX_PLANES]; +}; + +/** + * struct cam_isp_tfe_out_rsrc_bw_limiter_config - ISP TFE out rsrc BW limiter config + * + * Configure BW limiter for ISP TFE WMs + * + * @version : Version field + * @num_ports : Number of ports + * @bw_limit_config : WM BW limiter config + */ +struct cam_isp_tfe_out_rsrc_bw_limiter_config { + __u32 version; + __u32 num_ports; + struct cam_isp_tfe_wm_bw_limiter_config bw_limiter_config[1]; +}; + #define CAM_TFE_ACQUIRE_COMMON_VER0 0x1000 #define CAM_TFE_ACQUIRE_COMMON_SIZE_VER0 0x0