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 d8010fd902..74b2ccc1ef 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 @@ -4117,7 +4117,7 @@ static int cam_isp_tfe_blob_buffer_alignment_update( } hw_mgr_res = &ctx->res_list_tfe_out[res_id_out]; - res = hw_mgr_res->hw_res[i]; + res = hw_mgr_res->hw_res[0]; hw_intf = res->hw_intf; if (hw_intf && hw_intf->hw_ops.process_cmd) { cmd_update.res = res; @@ -4134,7 +4134,94 @@ static int cam_isp_tfe_blob_buffer_alignment_update( } else { CAM_ERR(CAM_ISP, "NULL hw_intf! ctx %d", ctx->ctx_index); } + } + return rc; +} + +static int cam_isp_tfe_blob_update_out_resource_config( + uint32_t blob_type, + struct cam_isp_generic_blob_info *blob_info, + struct cam_isp_tfe_out_resource_config *update_out_cfg, + struct cam_hw_prepare_update_args *prepare) +{ + struct cam_isp_tfe_wm_dimension_config *wm_dim_config; + 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; + struct cam_hw_intf *hw_intf; + 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", + prepare->num_hw_update_entries); + return -EINVAL; + } + + kmd_buf_info = blob_info->kmd_buf_info; + + for (i = 0; i < update_out_cfg->num_ports; i++) { + wm_dim_config = &update_out_cfg->dimension_config[i]; + + 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); + + res_id_out = wm_dim_config->res_id & 0xFF; + if (res_id_out >= CAM_TFE_HW_OUT_RES_MAX) { + CAM_ERR(CAM_ISP, "invalid out restype:%x", res_id_out); + return -EINVAL; + } + + hw_mgr_res = &ctx->res_list_tfe_out[res_id_out]; + + hw_intf = cam_tfe_hw_mgr_get_hw_intf(blob_info->base_info, ctx); + rc = cam_isp_add_cmd_buf_update( + hw_mgr_res->hw_res[blob_info->base_info->split_id], hw_intf, + blob_type, CAM_ISP_HW_CMD_WM_CONFIG_UPDATE, + (void *)cmd_buf_addr, + kmd_buf_remain_size, + (void *)wm_dim_config, + &bytes_used); + if (rc < 0) { + CAM_ERR(CAM_ISP, + "Failed to update %s Out out_type:0x%X base_idx:%d bytes_used:%u rc:%d", + "TFE", 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; @@ -4867,6 +4954,50 @@ static int cam_isp_tfe_packet_generic_blob_handler(void *user_data, prepare->packet->header.request_id, rc, tfe_mgr_ctx->ctx_index); } break; + case CAM_ISP_TFE_GENERIC_BLOB_TYPE_UPDATE_OUT_RES: { + struct cam_isp_tfe_out_resource_config *update_out_config = + (struct cam_isp_tfe_out_resource_config *)blob_data; + + if (update_out_config->num_ports > CAM_ISP_TFE_OUT_RES_MAX) { + CAM_ERR(CAM_ISP, "Invalid num_ports %u in update out config", + update_out_config->num_ports); + return -EINVAL; + } + + if (update_out_config->num_ports > 1) { + if (sizeof(struct cam_isp_tfe_out_resource_config) > + ((UINT_MAX - + sizeof(struct cam_isp_tfe_out_resource_config)) + / (update_out_config->num_ports - 1))) { + CAM_ERR(CAM_ISP, + "Max size exceeded in hfr config num_ports:%u size per port:%lu", + update_out_config->num_ports, + sizeof(struct cam_isp_tfe_out_resource_config)); + return -EINVAL; + } + } + + if ((update_out_config->num_ports != 0) && (blob_size < + (sizeof(struct cam_isp_tfe_out_resource_config) + + (update_out_config->num_ports - 1) * + sizeof(struct cam_isp_tfe_wm_dimension_config)))) { + + CAM_ERR(CAM_ISP, "Invalid blob size %u expected %lu", + blob_size, + sizeof(struct cam_isp_tfe_out_resource_config) + + (update_out_config->num_ports - 1) * + sizeof(struct cam_isp_tfe_wm_dimension_config)); + return -EINVAL; + } + + rc = cam_isp_tfe_blob_update_out_resource_config(blob_type, blob_info, + update_out_config, prepare); + if (rc) + CAM_ERR(CAM_ISP, + "Update out resource failed for req %lld rc %d ctx %d", + prepare->packet->header.request_id, rc, tfe_mgr_ctx->ctx_index); + } + break; default: CAM_WARN(CAM_ISP, "Invalid blob type %d ctx %d", blob_type, tfe_mgr_ctx->ctx_index); @@ -5098,6 +5229,8 @@ int cam_tfe_add_command_buffers( if (rc) return rc; break; + case CAM_ISP_TFE_PACKET_META_GENERIC_BLOB_LEFT: + case CAM_ISP_TFE_PACKET_META_GENERIC_BLOB_RIGHT: case CAM_ISP_TFE_PACKET_META_GENERIC_BLOB_COMMON: { struct cam_isp_generic_blob_info blob_info; diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_csid_hw/cam_tfe_csid770.h b/drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_csid_hw/cam_tfe_csid770.h index d832fb2019..c430416f1e 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_csid_hw/cam_tfe_csid770.h +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_csid_hw/cam_tfe_csid770.h @@ -342,6 +342,7 @@ static struct cam_tfe_csid_common_reg_offset .format_measure_height_shift_val = 16, .format_measure_height_mask_val = 0xe, .format_measure_width_mask_val = 0x10, + .sync_clk = true, }; static struct cam_tfe_csid_reg_offset cam_tfe_csid_770_reg_offset = { 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 202ef68ac6..ee04eea7c6 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 @@ -115,6 +115,8 @@ struct cam_tfe_bus_wm_resource_data { uint32_t buffer_offset; bool is_buffer_aligned; bool limiter_blob_status; + + bool is_dim_update; }; struct cam_tfe_bus_comp_grp_data { @@ -2168,6 +2170,39 @@ end: } +static int cam_tfe_bus_update_wm_config(void *priv, void *cmd_args, + uint32_t arg_size) +{ + struct cam_tfe_bus_priv *bus_priv; + struct cam_isp_hw_get_cmd_update *update_wm_cmd; + struct cam_tfe_bus_tfe_out_data *tfe_out_data = NULL; + struct cam_tfe_bus_wm_resource_data *wm_data = NULL; + struct cam_isp_tfe_wm_dimension_config *update_out_cfg; + uint32_t i, rc = 0; + + bus_priv = (struct cam_tfe_bus_priv *) priv; + update_wm_cmd = (struct cam_isp_hw_get_cmd_update *) cmd_args; + update_out_cfg = (struct cam_isp_tfe_wm_dimension_config *) update_wm_cmd->data; + + tfe_out_data = (struct cam_tfe_bus_tfe_out_data *) update_wm_cmd->res->res_priv; + + if (!tfe_out_data) { + CAM_ERR(CAM_ISP, "Failed! invalid data"); + return -EINVAL; + } + + for (i = 0; i < tfe_out_data->num_wm; i++) { + wm_data = tfe_out_data->wm_res[i]->res_priv; + wm_data->is_dim_update = true; + wm_data->width = update_out_cfg->width; + wm_data->height = update_out_cfg->height; + CAM_DBG(CAM_ISP, "WM %d width %lld height %lld", wm_data->index, + wm_data->width, wm_data->height); + } + + return rc; +} + static int cam_tfe_bus_diable_wm(void *priv, void *cmd_args, uint32_t arg_size) { @@ -2829,7 +2864,7 @@ static int cam_tfe_bus_process_cmd(void *priv, uint32_t cmd_type, void *cmd_args, uint32_t arg_size) { struct cam_tfe_bus_priv *bus_priv; - int rc = -EINVAL; + int rc = 0; uint32_t i, val; bool *support_consumed_addr; bool *pdaf_rdi2_mux_en; @@ -2900,9 +2935,13 @@ static int cam_tfe_bus_process_cmd(void *priv, case CAM_ISP_HW_CMD_BUFFER_ALIGNMENT_UPDATE: rc = cam_tfe_buffer_alignment_update(priv, cmd_args, arg_size); break; + case CAM_ISP_HW_CMD_WM_CONFIG_UPDATE: + rc = cam_tfe_bus_update_wm_config(priv, cmd_args, arg_size); + break; default: CAM_ERR_RATE_LIMIT(CAM_ISP, "Invalid camif process command:%d", cmd_type); + rc = -EINVAL; break; } 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 85b390d976..6a8d1e81cf 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 @@ -407,7 +407,7 @@ static void cam_tfe_log_error_irq_status( for (i = 0; i < common_reg->num_debug_reg; i++) { val_0 = cam_io_r(mem_base + common_reg->debug_reg[i]); - CAM_INFO(CAM_ISP, "Top debug [i]:0x%x", i, val_0); + CAM_INFO(CAM_ISP, "Top debug [%d]:0x%x", i, val_0); } cam_cpas_dump_camnoc_buff_fill_info(soc_private->cpas_handle); @@ -3442,6 +3442,7 @@ int cam_tfe_process_cmd(void *hw_priv, uint32_t cmd_type, case CAM_ISP_HW_CMD_GET_LAST_CONSUMED_ADDR: case CAM_ISP_HW_CMD_BUS_WM_DISABLE: case CAM_ISP_HW_CMD_BUFFER_ALIGNMENT_UPDATE: + case CAM_ISP_HW_CMD_WM_CONFIG_UPDATE: 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 8e92d6c678..71b62db40f 100644 --- a/include/uapi/camera/media/cam_tfe.h +++ b/include/uapi/camera/media/cam_tfe.h @@ -66,6 +66,8 @@ #define CAM_ISP_TFE_PACKET_META_REG_DUMP_PER_REQUEST 6 #define CAM_ISP_TFE_PACKET_META_REG_DUMP_ON_FLUSH 7 #define CAM_ISP_TFE_PACKET_META_REG_DUMP_ON_ERROR 8 +#define CAM_ISP_TFE_PACKET_META_GENERIC_BLOB_LEFT 9 +#define CAM_ISP_TFE_PACKET_META_GENERIC_BLOB_RIGHT 10 /* ISP TFE Generic Cmd Buffer Blob types */ #define CAM_ISP_TFE_GENERIC_BLOB_TYPE_HFR_CONFIG 0 @@ -76,6 +78,7 @@ #define CAM_ISP_TFE_GENERIC_BLOB_TYPE_DYNAMIC_MODE_SWITCH 15 #define CAM_ISP_TFE_GENERIC_BLOB_TYPE_BW_LIMITER_CFG 16 #define CAM_ISP_TFE_GENERIC_BLOB_TYPE_ALIGNMENT_OFFSET_INFO 17 +#define CAM_ISP_TFE_GENERIC_BLOB_TYPE_UPDATE_OUT_RES 18 /* DSP mode */ #define CAM_ISP_TFE_DSP_MODE_NONE 0 @@ -562,6 +565,35 @@ struct cam_isp_tfe_alignment_resource_info { struct cam_isp_tfe_alignment_offset_config port_alignment_cfg[1]; } __attribute__((packed)); +/** + * struct cam_isp_tfe_wm_dimension_config - ISP TFE res Dimension config + * + * @res_id : Resource id + * @mode : Mode of out resource + * @height : Out resource height + * @width : Out resource width + * + */ +struct cam_isp_tfe_wm_dimension_config { + __u32 res_id; + __u32 mode; + __u32 height; + __u32 width; +}; + +/** + * struct cam_isp_tfe_out_resource_config - ISP TFE out config + * + * @num_ports : Num of out res + * @reserved : Reserved field + * @dimention_config : Out resource dimension config + */ +struct cam_isp_tfe_out_resource_config { + __u32 num_ports; + __u32 reserved; + struct cam_isp_tfe_wm_dimension_config dimension_config[1]; +}; + #define CAM_TFE_ACQUIRE_COMMON_VER0 0x1000 #define CAM_TFE_ACQUIRE_COMMON_SIZE_VER0 0x0