浏览代码

msm: camera: tfe: Add support for epoch blob in TFE HW

In overlap SHDR, epoch irq from TFE need to configure in such
a way that request should be apply at epoch of shorter exposure frame
before start of the next frame of long exposure to make sure that
new settings should apply properly in time.

CRs-Fixed: 3396382
Change-Id: I1ddc3ce95c6d404a3f76a27cc58083e11b03bace
Signed-off-by: Ayush Kumar <[email protected]>
Ayush Kumar 2 年之前
父节点
当前提交
1b91ba1b2f

+ 67 - 2
drivers/cam_isp/isp_hw_mgr/cam_tfe_hw_mgr.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-2023 Qualcomm Innovation Center, Inc. All rights reserved.
+ * Copyright (c) 2022-2023, Qualcomm Innovation Center, Inc. All rights reserved.
  */
 
 #include <linux/slab.h>
@@ -4200,6 +4200,39 @@ static int cam_isp_tfe_blob_csid_clock_update(
 	return rc;
 }
 
+static int cam_isp_blob_tfe_init_config_update(
+	struct cam_hw_prepare_update_args    *prepare,
+	struct cam_isp_init_config           *init_config)
+{
+	int i, rc = 0;
+	struct cam_tfe_hw_mgr_ctx             *ctx = NULL;
+	struct cam_isp_hw_init_config_update   init_cfg_update;
+	struct cam_hw_intf                    *hw_intf;
+
+	ctx = prepare->ctxt_to_hw_map;
+	init_cfg_update.init_config = init_config;
+
+	for (i = 0; i < ctx->num_base; i++) {
+		if (ctx->base[i].hw_type != CAM_ISP_HW_TYPE_TFE)
+			continue;
+
+		hw_intf = g_tfe_hw_mgr.tfe_devices[ctx->base[i].idx]->hw_intf;
+		if (hw_intf && hw_intf->hw_ops.process_cmd) {
+			CAM_DBG(CAM_ISP, "Epoch/init config update for ctx %d",
+				ctx->ctx_index);
+			rc = hw_intf->hw_ops.process_cmd(hw_intf->hw_priv,
+				CAM_ISP_HW_CMD_INIT_CONFIG_UPDATE,
+				&init_cfg_update,
+				sizeof(struct cam_isp_hw_init_config_update));
+			if (rc)
+				CAM_ERR(CAM_ISP, "Epoch/init config failed rc %d ctx %d",
+					rc, ctx->ctx_index);
+		}
+	}
+
+	return rc;
+}
+
 static int cam_isp_tfe_blob_clock_update(
 	uint32_t                               blob_type,
 	struct cam_isp_generic_blob_info      *blob_info,
@@ -4673,8 +4706,40 @@ static int cam_isp_tfe_packet_generic_blob_handler(void *user_data,
 		prepare_hw_data->num_exp = mup_config->num_expoures;
 	}
 		break;
+	case CAM_ISP_TFE_GENERIC_BLOB_TYPE_INIT_CONFIG: {
+		struct cam_isp_init_config            *init_config;
+		struct cam_isp_prepare_hw_update_data *prepare_hw_data;
+
+		prepare_hw_data = (struct cam_isp_prepare_hw_update_data *)prepare->priv;
+
+		if (prepare_hw_data->packet_opcode_type != CAM_ISP_PACKET_INIT_DEV) {
+			CAM_ERR(CAM_ISP,
+				"Epoch config blob not supported packet type: %u req: %llu Ctx %d",
+				prepare_hw_data->packet_opcode_type,
+				prepare->packet->header.request_id,
+				tfe_mgr_ctx->ctx_index);
+			return -EINVAL;
+		}
+
+		if (blob_size != sizeof(struct cam_isp_init_config)) {
+			CAM_ERR(CAM_ISP,
+				"Invalid init config blob size %u expected %u ctx %d",
+				blob_size, sizeof(struct cam_isp_init_config),
+				tfe_mgr_ctx->ctx_index);
+			return -EINVAL;
+		}
+
+		init_config = (struct cam_isp_init_config *)blob_data;
+		rc = cam_isp_blob_tfe_init_config_update(prepare, init_config);
+		if (rc)
+			CAM_ERR(CAM_ISP,
+				"Init config failed for req: %llu 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", blob_type);
+		CAM_WARN(CAM_ISP, "Invalid blob type %d ctx %d", blob_type,
+			tfe_mgr_ctx->ctx_index);
 		break;
 	}
 

+ 62 - 4
drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_hw/cam_tfe_core.c

@@ -95,6 +95,7 @@ struct cam_tfe_camif_data {
 	uint32_t                           core_cfg;
 	bool                               shdr_en;
 	bool                               is_shdr_master;
+	uint32_t                           epoch_factor;
 };
 
 struct cam_tfe_rdi_data {
@@ -113,6 +114,7 @@ struct cam_tfe_rdi_data {
 	uint32_t                                     last_line;
 	bool                                         shdr_en;
 	bool                                         is_shdr_master;
+	uint32_t                                     epoch_factor;
 };
 
 struct cam_tfe_ppp_data {
@@ -1575,6 +1577,54 @@ static int cam_tfe_top_get_reg_update(
 	return 0;
 }
 
+static int cam_tfe_top_init_config_update(
+	struct cam_tfe_top_priv *top_priv,
+	void *cmd_args, uint32_t arg_size)
+{
+	int i = 0;
+	struct cam_isp_hw_init_config_update *init_cfg = NULL;
+	struct cam_isp_resource_node *rsrc_node = NULL;
+	struct cam_tfe_camif_data *camif_data;
+
+	init_cfg = (struct cam_isp_hw_init_config_update *)cmd_args;
+
+	if (arg_size != sizeof(struct cam_isp_hw_init_config_update)) {
+		CAM_ERR(CAM_ISP, "Invalid args size expected: %zu actual: %zu",
+			sizeof(struct cam_isp_hw_init_config_update), arg_size);
+		return -EINVAL;
+	}
+
+	for (i = 0; i < CAM_TFE_TOP_IN_PORT_MAX; i++) {
+		if (top_priv->in_rsrc[i].res_id == CAM_ISP_HW_TFE_IN_CAMIF) {
+			rsrc_node = &top_priv->in_rsrc[i];
+			break;
+		}
+	}
+
+	if (!rsrc_node) {
+		CAM_ERR(CAM_ISP, "TFE %d null input res node",
+			top_priv->common_data.hw_intf->hw_idx);
+		return -EINVAL;
+	}
+
+	if (rsrc_node->res_type != CAM_ISP_RESOURCE_TFE_IN) {
+		CAM_ERR(CAM_ISP, "TFE %d Invalid res_type %d res id %d ",
+			rsrc_node->hw_intf->hw_idx, rsrc_node->res_type,
+			rsrc_node->res_id);
+		return -EINVAL;
+	}
+
+	camif_data = (struct cam_tfe_camif_data *)rsrc_node->res_priv;
+	camif_data->epoch_factor = init_cfg->init_config->epoch_cfg.epoch_factor;
+
+	CAM_DBG(CAM_ISP,
+		"Init Update TFE %d res type: %d res id %d epoch_factor: %u",
+		rsrc_node->hw_intf->hw_idx, rsrc_node->res_type,
+		rsrc_node->res_id, camif_data->epoch_factor);
+
+	return 0;
+}
+
 static int cam_tfe_top_clock_update(
 	struct cam_tfe_top_priv *top_priv,
 	void *cmd_args, uint32_t arg_size)
@@ -2309,7 +2359,7 @@ static int cam_tfe_camif_resource_start(
 	struct cam_tfe_camif_data           *rsrc_data;
 	struct cam_tfe_soc_private          *soc_private;
 	struct cam_tfe_top_priv             *top_priv;
-	uint32_t                             val = 0;
+	uint32_t                             val = 0, epoch_factor = 50;
 	uint32_t                             epoch0_irq_mask;
 	uint32_t                             epoch1_irq_mask;
 	uint32_t                             computed_epoch_line_cfg;
@@ -2403,8 +2453,12 @@ static int cam_tfe_camif_resource_start(
 	}
 
 	/* Epoch config */
+	if ((rsrc_data->epoch_factor) && (rsrc_data->epoch_factor <= 100))
+		epoch_factor = rsrc_data->epoch_factor;
+
 	epoch0_irq_mask = (((rsrc_data->last_line + rsrc_data->vbi_value) -
-			rsrc_data->first_line) / 2);
+		rsrc_data->first_line) * epoch_factor / 100);
+
 	if (epoch0_irq_mask > (rsrc_data->last_line - rsrc_data->first_line))
 		epoch0_irq_mask = (rsrc_data->last_line -
 					rsrc_data->first_line);
@@ -2421,11 +2475,11 @@ static int cam_tfe_camif_resource_start(
 			rsrc_data->camif_reg->epoch_irq_cfg);
 	CAM_DBG(CAM_ISP, "TFE:%d first_line: %u\n"
 			"last_line: %u\n"
-			"epoch_line_cfg: 0x%x",
+			"epoch_line_cfg: 0x%x epoch factor %d",
 			core_info->core_index,
 			rsrc_data->first_line,
 			rsrc_data->last_line,
-			computed_epoch_line_cfg);
+			computed_epoch_line_cfg, epoch_factor);
 
 	camif_res->res_state = CAM_ISP_RESOURCE_STATE_STREAMING;
 
@@ -3344,6 +3398,10 @@ int cam_tfe_process_cmd(void *hw_priv, uint32_t cmd_type,
 		rc = cam_tfe_top_dynamic_clock_update(core_info->top_priv, cmd_args,
 			arg_size);
 		break;
+	case CAM_ISP_HW_CMD_INIT_CONFIG_UPDATE:
+		rc = cam_tfe_top_init_config_update(core_info->top_priv, cmd_args,
+			arg_size);
+		break;
 	case CAM_ISP_HW_CMD_GET_BUF_UPDATE:
 	case CAM_ISP_HW_CMD_GET_HFR_UPDATE:
 	case CAM_ISP_HW_CMD_STRIPE_UPDATE:

+ 1 - 0
include/uapi/camera/media/cam_tfe.h

@@ -72,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_INIT_CONFIG         4
 #define CAM_ISP_TFE_GENERIC_BLOB_TYPE_BW_LIMITER_CFG      16
 #define CAM_ISP_TFE_GENERIC_BLOB_TYPE_DYNAMIC_MODE_SWITCH 15