Explorar o código

msm: camera: isp: Support TFE WM configuration update

This chages is to support blob to update TFE WM dimensions.
This is required as 3A lib allocates max buffer for pdaf ports
but per request dimension can differ from buffer dimension.

CRs-Fixed: 3546181
Change-Id: I98bffa9ef00a7fa2bb543cb0c89f7920ed6780c5
Signed-off-by: Ayush Kumar <[email protected]>
Ayush Kumar %!s(int64=2) %!d(string=hai) anos
pai
achega
c5dae62d39

+ 134 - 1
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;
 

+ 1 - 0
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 = {

+ 40 - 1
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;
 	}
 

+ 2 - 1
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);

+ 32 - 0
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