Просмотр исходного кода

msm: camera: ife: Configure epoch to exactly half of the frame

Some customers have sensor mode with more blanking width.
Due to this, time is not sufficient for applying
setting thus resulted in frame drops.
To avoid this situation, epoch is calculated on complete
frame and configured at half the frame.

CRs-Fixed: 2757095
Change-Id: I92927c23762f717d6ddca67a7e641422e8fb6d8f
Signed-off-by: Shravya Samala <[email protected]>
Shravya Samala 4 лет назад
Родитель
Сommit
762751a88c

+ 67 - 0
drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c

@@ -49,6 +49,7 @@ static uint32_t blob_type_hw_cmd_map[CAM_ISP_GENERIC_BLOB_TYPE_MAX] = {
 	CAM_ISP_HW_CMD_CORE_CONFIG,
 	CAM_ISP_HW_CMD_CORE_CONFIG,
 	CAM_ISP_HW_CMD_WM_CONFIG_UPDATE,
 	CAM_ISP_HW_CMD_WM_CONFIG_UPDATE,
 	CAM_ISP_HW_CMD_BW_UPDATE_V2,
 	CAM_ISP_HW_CMD_BW_UPDATE_V2,
+	CAM_ISP_HW_CMD_BLANKING_UPDATE,
 };
 };
 
 
 static struct cam_ife_hw_mgr g_ife_hw_mgr;
 static struct cam_ife_hw_mgr g_ife_hw_mgr;
@@ -5577,6 +5578,53 @@ static int cam_isp_blob_csid_config_update(
 
 
 	return rc;
 	return rc;
 }
 }
+
+static int cam_isp_blob_sensor_blanking_config(
+	uint32_t                               blob_type,
+	struct cam_isp_generic_blob_info      *blob_info,
+	struct cam_isp_sensor_blanking_config *sensor_blanking_config,
+	struct cam_hw_prepare_update_args     *prepare)
+
+{
+	struct cam_ife_hw_mgr_ctx       *ctx = NULL;
+	struct cam_isp_hw_mgr_res       *hw_mgr_res;
+	struct cam_hw_intf              *hw_intf;
+	struct cam_isp_blanking_config  blanking_config;
+	int                             rc = 0, i;
+
+	ctx = prepare->ctxt_to_hw_map;
+	if (list_empty(&ctx->res_list_ife_src)) {
+		CAM_ERR(CAM_ISP, "Mux List empty");
+		return -ENODEV;
+	}
+
+	list_for_each_entry(hw_mgr_res,
+		&ctx->res_list_ife_src, list) {
+		for (i = 0; i < CAM_ISP_HW_SPLIT_MAX; i++) {
+			if (!hw_mgr_res->hw_res[i])
+				continue;
+
+			hw_intf = hw_mgr_res->hw_res[i]->hw_intf;
+			blanking_config.node_res = hw_mgr_res->hw_res[i];
+			blanking_config.vbi = sensor_blanking_config->vbi;
+			blanking_config.hbi = sensor_blanking_config->hbi;
+
+			if (hw_intf && hw_intf->hw_ops.process_cmd) {
+				rc = hw_intf->hw_ops.process_cmd(
+					hw_intf->hw_priv,
+					CAM_ISP_HW_CMD_BLANKING_UPDATE,
+					&blanking_config,
+					sizeof(
+					struct cam_isp_blanking_config));
+				if (rc)
+					CAM_ERR(CAM_ISP,
+						"blanking update failed");
+			}
+		}
+	}
+	return rc;
+}
+
 static int cam_isp_packet_generic_blob_handler(void *user_data,
 static int cam_isp_packet_generic_blob_handler(void *user_data,
 	uint32_t blob_type, uint32_t blob_size, uint8_t *blob_data)
 	uint32_t blob_type, uint32_t blob_size, uint8_t *blob_data)
 {
 {
@@ -6057,6 +6105,25 @@ static int cam_isp_packet_generic_blob_handler(void *user_data,
 			CAM_ERR(CAM_ISP, "CSID Config failed rc: %d", rc);
 			CAM_ERR(CAM_ISP, "CSID Config failed rc: %d", rc);
 	}
 	}
 		break;
 		break;
+	case CAM_ISP_GENERIC_BLOB_TYPE_SENSOR_BLANKING_CONFIG: {
+		struct cam_isp_sensor_blanking_config  *sensor_blanking_config;
+
+		if (blob_size < sizeof(struct cam_isp_sensor_blanking_config)) {
+			CAM_ERR(CAM_ISP, "Invalid blob size %zu expected %zu",
+				blob_size,
+				sizeof(struct cam_isp_sensor_blanking_config));
+			return -EINVAL;
+		}
+		sensor_blanking_config =
+			(struct cam_isp_sensor_blanking_config *)blob_data;
+
+		rc = cam_isp_blob_sensor_blanking_config(blob_type, blob_info,
+			sensor_blanking_config, prepare);
+		if (rc)
+			CAM_ERR(CAM_ISP,
+				"Epoch Configuration Update Failed rc:%d", rc);
+	}
+		break;
 	case CAM_ISP_GENERIC_BLOB_TYPE_SENSOR_DIMENSION_CONFIG: {
 	case CAM_ISP_GENERIC_BLOB_TYPE_SENSOR_DIMENSION_CONFIG: {
 		struct cam_isp_sensor_config *csid_dim_config;
 		struct cam_isp_sensor_config *csid_dim_config;
 
 

+ 15 - 0
drivers/cam_isp/isp_hw_mgr/isp_hw/include/cam_isp_hw.h

@@ -124,6 +124,7 @@ enum cam_isp_hw_cmd_type {
 	CAM_ISP_HW_CMD_UNMASK_BUS_WR_IRQ,
 	CAM_ISP_HW_CMD_UNMASK_BUS_WR_IRQ,
 	CAM_ISP_HW_CMD_IS_CONSUMED_ADDR_SUPPORT,
 	CAM_ISP_HW_CMD_IS_CONSUMED_ADDR_SUPPORT,
 	CAM_ISP_HW_CMD_GET_RES_FOR_MID,
 	CAM_ISP_HW_CMD_GET_RES_FOR_MID,
+	CAM_ISP_HW_CMD_BLANKING_UPDATE,
 	CAM_ISP_HW_CMD_MAX,
 	CAM_ISP_HW_CMD_MAX,
 };
 };
 
 
@@ -178,6 +179,20 @@ struct cam_isp_resource_node {
 	CAM_IRQ_HANDLER_BOTTOM_HALF    bottom_half_handler;
 	CAM_IRQ_HANDLER_BOTTOM_HALF    bottom_half_handler;
 };
 };
 
 
+/*
+ * struct cam_isp_blanking_config:
+ *
+ * @Brief:          Structure to pass blanking details
+ * @hbi:            HBI Value
+ * @vbi:            VBI Value
+ * node_res:        Pointer to Resource Node object
+ */
+struct cam_isp_blanking_config {
+	uint32_t                           hbi;
+	uint32_t                           vbi;
+	struct cam_isp_resource_node       *node_res;
+};
+
 /*
 /*
  * struct cam_isp_hw_event_info:
  * struct cam_isp_hw_event_info:
  *
  *

+ 14 - 1
drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_hw/cam_tfe_core.c

@@ -79,6 +79,8 @@ struct cam_tfe_camif_data {
 	uint32_t                           camif_debug;
 	uint32_t                           camif_debug;
 	uint32_t                           camif_pd_enable;
 	uint32_t                           camif_pd_enable;
 	uint32_t                           dual_tfe_sync_sel;
 	uint32_t                           dual_tfe_sync_sel;
+	uint32_t                           hbi_value;
+	uint32_t                           vbi_value;
 };
 };
 
 
 struct cam_tfe_rdi_data {
 struct cam_tfe_rdi_data {
@@ -265,6 +267,10 @@ static void cam_tfe_log_tfe_in_debug_status(
 				"Acquired line start:0x%x line end:0x%x",
 				"Acquired line start:0x%x line end:0x%x",
 				camif_data->first_line,
 				camif_data->first_line,
 				camif_data->last_line);
 				camif_data->last_line);
+			CAM_INFO(CAM_ISP, "vbi_value:0x%x hbi_value:0x%x",
+				camif_data->vbi_value,
+				camif_data->hbi_value);
+
 		} else if ((top_priv->in_rsrc[i].res_id >=
 		} else if ((top_priv->in_rsrc[i].res_id >=
 			CAM_ISP_HW_TFE_IN_RDI0) ||
 			CAM_ISP_HW_TFE_IN_RDI0) ||
 			(top_priv->in_rsrc[i].res_id <=
 			(top_priv->in_rsrc[i].res_id <=
@@ -1815,6 +1821,10 @@ int cam_tfe_top_reserve(void *device_priv,
 					acquire_args->in_port->line_start;
 					acquire_args->in_port->line_start;
 				camif_data->last_line =
 				camif_data->last_line =
 					acquire_args->in_port->line_end;
 					acquire_args->in_port->line_end;
+				camif_data->vbi_value =
+					acquire_args->in_port->sensor_vbi;
+				camif_data->hbi_value =
+					acquire_args->in_port->sensor_hbi;
 				camif_data->camif_pd_enable =
 				camif_data->camif_pd_enable =
 					acquire_args->camif_pd_enable;
 					acquire_args->camif_pd_enable;
 				camif_data->dual_tfe_sync_sel =
 				camif_data->dual_tfe_sync_sel =
@@ -1978,9 +1988,12 @@ static int cam_tfe_camif_resource_start(
 	}
 	}
 
 
 	/* Epoch config */
 	/* Epoch config */
-	epoch0_irq_mask = ((rsrc_data->last_line -
+	epoch0_irq_mask = (((rsrc_data->last_line + rsrc_data->vbi_value) -
 			rsrc_data->first_line) / 2) +
 			rsrc_data->first_line) / 2) +
 			rsrc_data->first_line;
 			rsrc_data->first_line;
+	if (epoch0_irq_mask > rsrc_data->last_line)
+		epoch0_irq_mask = rsrc_data->last_line;
+
 	epoch1_irq_mask = rsrc_data->reg_data->epoch_line_cfg &
 	epoch1_irq_mask = rsrc_data->reg_data->epoch_line_cfg &
 			0xFFFF;
 			0xFFFF;
 	computed_epoch_line_cfg = (epoch0_irq_mask << 16) |
 	computed_epoch_line_cfg = (epoch0_irq_mask << 16) |

+ 1 - 0
drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/cam_vfe_core.c

@@ -601,6 +601,7 @@ int cam_vfe_process_cmd(void *hw_priv, uint32_t cmd_type,
 	case CAM_ISP_HW_CMD_ADD_WAIT:
 	case CAM_ISP_HW_CMD_ADD_WAIT:
 	case CAM_ISP_HW_CMD_ADD_WAIT_TRIGGER:
 	case CAM_ISP_HW_CMD_ADD_WAIT_TRIGGER:
 	case CAM_ISP_HW_CMD_CAMIF_DATA:
 	case CAM_ISP_HW_CMD_CAMIF_DATA:
+	case CAM_ISP_HW_CMD_BLANKING_UPDATE:
 		rc = core_info->vfe_top->hw_ops.process_cmd(
 		rc = core_info->vfe_top->hw_ops.process_cmd(
 			core_info->vfe_top->top_priv, cmd_type, cmd_args,
 			core_info->vfe_top->top_priv, cmd_type, cmd_args,
 			arg_size);
 			arg_size);

+ 3 - 0
drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_camif_lite_ver2.c

@@ -371,6 +371,9 @@ static int cam_vfe_camif_lite_process_cmd(
 		break;
 		break;
 	case CAM_ISP_HW_CMD_SET_CAMIF_DEBUG:
 	case CAM_ISP_HW_CMD_SET_CAMIF_DEBUG:
 		break;
 		break;
+	case CAM_ISP_HW_CMD_BLANKING_UPDATE:
+		rc = 0;
+		break;
 	default:
 	default:
 		CAM_ERR(CAM_ISP,
 		CAM_ERR(CAM_ISP,
 			"unsupported process command:%d", cmd_type);
 			"unsupported process command:%d", cmd_type);

+ 3 - 0
drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_camif_lite_ver3.c

@@ -772,6 +772,9 @@ static int cam_vfe_camif_lite_process_cmd(
 			rsrc_node->res_priv;
 			rsrc_node->res_priv;
 		camif_lite_priv->camif_debug = *((uint32_t *)cmd_args);
 		camif_lite_priv->camif_debug = *((uint32_t *)cmd_args);
 		break;
 		break;
+	case CAM_ISP_HW_CMD_BLANKING_UPDATE:
+		rc = 0;
+		break;
 	default:
 	default:
 		CAM_ERR(CAM_ISP,
 		CAM_ERR(CAM_ISP,
 			"unsupported process command:%d", cmd_type);
 			"unsupported process command:%d", cmd_type);

+ 31 - 2
drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_camif_ver2.c

@@ -45,6 +45,8 @@ struct cam_vfe_mux_camif_data {
 	uint32_t                           first_line;
 	uint32_t                           first_line;
 	uint32_t                           last_pixel;
 	uint32_t                           last_pixel;
 	uint32_t                           last_line;
 	uint32_t                           last_line;
+	uint32_t                           hbi_value;
+	uint32_t                           vbi_value;
 	bool                               enable_sof_irq_debug;
 	bool                               enable_sof_irq_debug;
 	uint32_t                           irq_debug_cnt;
 	uint32_t                           irq_debug_cnt;
 	uint32_t                           camif_debug;
 	uint32_t                           camif_debug;
@@ -269,6 +271,8 @@ int cam_vfe_camif_ver2_acquire_resource(
 	camif_data->event_cb    = acquire_data->event_cb;
 	camif_data->event_cb    = acquire_data->event_cb;
 	camif_data->priv        = acquire_data->priv;
 	camif_data->priv        = acquire_data->priv;
 	camif_data->is_dual     = acquire_data->vfe_in.is_dual;
 	camif_data->is_dual     = acquire_data->vfe_in.is_dual;
+	camif_data->hbi_value   = 0;
+	camif_data->vbi_value   = 0;
 
 
 	if (acquire_data->vfe_in.is_dual)
 	if (acquire_data->vfe_in.is_dual)
 		camif_data->dual_hw_idx =
 		camif_data->dual_hw_idx =
@@ -420,9 +424,13 @@ static int cam_vfe_camif_resource_start(
 				rsrc_data->camif_reg->epoch_irq);
 				rsrc_data->camif_reg->epoch_irq);
 		break;
 		break;
 	default:
 	default:
-		epoch0_irq_mask = ((rsrc_data->last_line -
+		epoch0_irq_mask = (((rsrc_data->last_line +
+				rsrc_data->vbi_value) -
 				rsrc_data->first_line) / 2) +
 				rsrc_data->first_line) / 2) +
 				rsrc_data->first_line;
 				rsrc_data->first_line;
+		if (epoch0_irq_mask > rsrc_data->last_line)
+			epoch0_irq_mask = rsrc_data->last_line;
+
 		epoch1_irq_mask = rsrc_data->reg_data->epoch_line_cfg &
 		epoch1_irq_mask = rsrc_data->reg_data->epoch_line_cfg &
 				0xFFFF;
 				0xFFFF;
 		computed_epoch_line_cfg = (epoch0_irq_mask << 16) |
 		computed_epoch_line_cfg = (epoch0_irq_mask << 16) |
@@ -431,10 +439,11 @@ static int cam_vfe_camif_resource_start(
 				rsrc_data->mem_base +
 				rsrc_data->mem_base +
 				rsrc_data->camif_reg->epoch_irq);
 				rsrc_data->camif_reg->epoch_irq);
 		CAM_DBG(CAM_ISP, "first_line: %u\n"
 		CAM_DBG(CAM_ISP, "first_line: %u\n"
-				"last_line: %u\n"
+				"last_line: %u vbi: %u\n"
 				"epoch_line_cfg: 0x%x",
 				"epoch_line_cfg: 0x%x",
 				rsrc_data->first_line,
 				rsrc_data->first_line,
 				rsrc_data->last_line,
 				rsrc_data->last_line,
+				rsrc_data->vbi_value,
 				computed_epoch_line_cfg);
 				computed_epoch_line_cfg);
 		break;
 		break;
 	}
 	}
@@ -669,6 +678,23 @@ int cam_vfe_camif_dump_timestamps(
 	return 0;
 	return 0;
 }
 }
 
 
+static int cam_vfe_camif_blanking_update(
+	struct cam_isp_resource_node *rsrc_node, void *cmd_args)
+{
+	struct cam_vfe_mux_camif_data *camif_priv =
+		(struct cam_vfe_mux_camif_data *)rsrc_node->res_priv;
+
+	struct cam_isp_blanking_config  *blanking_config =
+		(struct cam_isp_blanking_config *)cmd_args;
+
+	camif_priv->hbi_value = blanking_config->hbi;
+	camif_priv->vbi_value = blanking_config->vbi;
+
+	CAM_DBG(CAM_ISP, "hbi:%d vbi:%d",
+		camif_priv->hbi_value, camif_priv->vbi_value);
+	return 0;
+}
+
 static int cam_vfe_camif_process_cmd(struct cam_isp_resource_node *rsrc_node,
 static int cam_vfe_camif_process_cmd(struct cam_isp_resource_node *rsrc_node,
 	uint32_t cmd_type, void *cmd_args, uint32_t arg_size)
 	uint32_t cmd_type, void *cmd_args, uint32_t arg_size)
 {
 {
@@ -696,6 +722,9 @@ static int cam_vfe_camif_process_cmd(struct cam_isp_resource_node *rsrc_node,
 	case CAM_ISP_HW_CMD_CAMIF_DATA:
 	case CAM_ISP_HW_CMD_CAMIF_DATA:
 		rc = cam_vfe_camif_dump_timestamps(rsrc_node, cmd_args);
 		rc = cam_vfe_camif_dump_timestamps(rsrc_node, cmd_args);
 		break;
 		break;
+	case CAM_ISP_HW_CMD_BLANKING_UPDATE:
+		rc = cam_vfe_camif_blanking_update(rsrc_node, cmd_args);
+		break;
 	default:
 	default:
 		CAM_ERR(CAM_ISP,
 		CAM_ERR(CAM_ISP,
 			"unsupported process command:%d", cmd_type);
 			"unsupported process command:%d", cmd_type);

+ 28 - 1
drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_camif_ver3.c

@@ -48,6 +48,8 @@ struct cam_vfe_mux_camif_ver3_data {
 	uint32_t                           first_line;
 	uint32_t                           first_line;
 	uint32_t                           last_pixel;
 	uint32_t                           last_pixel;
 	uint32_t                           last_line;
 	uint32_t                           last_line;
+	uint32_t                           hbi_value;
+	uint32_t                           vbi_value;
 	bool                               enable_sof_irq_debug;
 	bool                               enable_sof_irq_debug;
 	uint32_t                           irq_debug_cnt;
 	uint32_t                           irq_debug_cnt;
 	uint32_t                           camif_debug;
 	uint32_t                           camif_debug;
@@ -276,6 +278,8 @@ int cam_vfe_camif_ver3_acquire_resource(
 	camif_data->qcfa_bin       = acquire_data->vfe_in.in_port->qcfa_bin;
 	camif_data->qcfa_bin       = acquire_data->vfe_in.in_port->qcfa_bin;
 	camif_data->horizontal_bin =
 	camif_data->horizontal_bin =
 		acquire_data->vfe_in.in_port->horizontal_bin;
 		acquire_data->vfe_in.in_port->horizontal_bin;
+	camif_data->hbi_value      = 0;
+	camif_data->vbi_value      = 0;
 
 
 	if (camif_data->is_dual)
 	if (camif_data->is_dual)
 		camif_data->dual_hw_idx = acquire_data->vfe_in.dual_hw_idx;
 		camif_data->dual_hw_idx = acquire_data->vfe_in.dual_hw_idx;
@@ -464,8 +468,11 @@ static int cam_vfe_camif_ver3_resource_start(
 	case CAM_CPAS_TITAN_480_V100:
 	case CAM_CPAS_TITAN_480_V100:
 	case CAM_CPAS_TITAN_580_V100:
 	case CAM_CPAS_TITAN_580_V100:
 	case CAM_CPAS_TITAN_570_V200:
 	case CAM_CPAS_TITAN_570_V200:
-		epoch0_line_cfg = (rsrc_data->last_line -
+		epoch0_line_cfg = ((rsrc_data->last_line +
+			rsrc_data->vbi_value) -
 			rsrc_data->first_line) / 4;
 			rsrc_data->first_line) / 4;
+		if (epoch0_line_cfg > rsrc_data->last_line)
+			epoch0_line_cfg = rsrc_data->last_line;
 	/* epoch line cfg will still be configured at midpoint of the
 	/* epoch line cfg will still be configured at midpoint of the
 	 * frame width. We use '/ 4' instead of '/ 2'
 	 * frame width. We use '/ 4' instead of '/ 2'
 	 * cause it is multipixel path
 	 * cause it is multipixel path
@@ -811,6 +818,23 @@ int cam_vfe_camif_ver3_dump_timestamps(
 	return 0;
 	return 0;
 }
 }
 
 
+static int cam_vfe_camif_ver3_blanking_update(
+	struct cam_isp_resource_node *rsrc_node, void *cmd_args)
+{
+	struct cam_vfe_mux_camif_ver3_data *camif_priv =
+		(struct cam_vfe_mux_camif_ver3_data *)rsrc_node->res_priv;
+
+	struct cam_isp_blanking_config  *blanking_config =
+		(struct cam_isp_blanking_config *)cmd_args;
+
+	camif_priv->hbi_value = blanking_config->hbi;
+	camif_priv->vbi_value = blanking_config->vbi;
+
+	CAM_DBG(CAM_ISP, "hbi:%d vbi:%d",
+		camif_priv->hbi_value, camif_priv->vbi_value);
+	return 0;
+}
+
 static int cam_vfe_camif_ver3_process_cmd(
 static int cam_vfe_camif_ver3_process_cmd(
 	struct cam_isp_resource_node *rsrc_node,
 	struct cam_isp_resource_node *rsrc_node,
 	uint32_t cmd_type, void *cmd_args, uint32_t arg_size)
 	uint32_t cmd_type, void *cmd_args, uint32_t arg_size)
@@ -850,6 +874,9 @@ static int cam_vfe_camif_ver3_process_cmd(
 	case CAM_ISP_HW_CMD_CAMIF_DATA:
 	case CAM_ISP_HW_CMD_CAMIF_DATA:
 		rc = cam_vfe_camif_ver3_dump_timestamps(rsrc_node, cmd_args);
 		rc = cam_vfe_camif_ver3_dump_timestamps(rsrc_node, cmd_args);
 		break;
 		break;
+	case CAM_ISP_HW_CMD_BLANKING_UPDATE:
+		rc = cam_vfe_camif_ver3_blanking_update(rsrc_node, cmd_args);
+		break;
 	default:
 	default:
 		CAM_ERR(CAM_ISP,
 		CAM_ERR(CAM_ISP,
 			"unsupported process command:%d", cmd_type);
 			"unsupported process command:%d", cmd_type);

+ 32 - 5
drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_fe_ver1.c

@@ -1,6 +1,6 @@
 // SPDX-License-Identifier: GPL-2.0-only
 // SPDX-License-Identifier: GPL-2.0-only
 /*
 /*
- * Copyright (c) 2018-2019, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2018-2020, The Linux Foundation. All rights reserved.
  */
  */
 
 
 #include <linux/slab.h>
 #include <linux/slab.h>
@@ -36,6 +36,8 @@ struct cam_vfe_mux_fe_data {
 	uint32_t                           first_line;
 	uint32_t                           first_line;
 	uint32_t                           last_pixel;
 	uint32_t                           last_pixel;
 	uint32_t                           last_line;
 	uint32_t                           last_line;
+	uint32_t                           hbi_value;
+	uint32_t                           vbi_value;
 	bool                               enable_sof_irq_debug;
 	bool                               enable_sof_irq_debug;
 	uint32_t                           irq_debug_cnt;
 	uint32_t                           irq_debug_cnt;
 	uint32_t                           fe_cfg_data;
 	uint32_t                           fe_cfg_data;
@@ -179,6 +181,8 @@ int cam_vfe_fe_ver1_acquire_resource(
 	fe_data->last_pixel  = acquire_data->vfe_in.in_port->left_stop;
 	fe_data->last_pixel  = acquire_data->vfe_in.in_port->left_stop;
 	fe_data->first_line  = acquire_data->vfe_in.in_port->line_start;
 	fe_data->first_line  = acquire_data->vfe_in.in_port->line_start;
 	fe_data->last_line   = acquire_data->vfe_in.in_port->line_stop;
 	fe_data->last_line   = acquire_data->vfe_in.in_port->line_stop;
+	fe_data->hbi_value   = 0;
+	fe_data->vbi_value   = 0;
 
 
 	CAM_DBG(CAM_ISP, "hw id:%d pix_pattern:%d dsp_mode=%d",
 	CAM_DBG(CAM_ISP, "hw id:%d pix_pattern:%d dsp_mode=%d",
 		fe_res->hw_intf->hw_idx,
 		fe_res->hw_intf->hw_idx,
@@ -302,16 +306,19 @@ static int cam_vfe_fe_resource_start(
 		CAM_VFE_TOP_VER2_MODULE_STATS]->cgc_ovd);
 		CAM_VFE_TOP_VER2_MODULE_STATS]->cgc_ovd);
 
 
 	/* epoch config */
 	/* epoch config */
-	epoch0_irq_mask = ((rsrc_data->last_line - rsrc_data->first_line) / 2) +
-		rsrc_data->first_line;
+	epoch0_irq_mask = (((rsrc_data->last_line + rsrc_data->vbi_value) -
+		rsrc_data->first_line) / 2) + rsrc_data->first_line;
+	if (epoch0_irq_mask > rsrc_data->last_line)
+		epoch0_irq_mask = rsrc_data->last_line;
 
 
 	epoch1_irq_mask = rsrc_data->reg_data->epoch_line_cfg & 0xFFFF;
 	epoch1_irq_mask = rsrc_data->reg_data->epoch_line_cfg & 0xFFFF;
 	computed_epoch_line_cfg = (epoch0_irq_mask << 16) | epoch1_irq_mask;
 	computed_epoch_line_cfg = (epoch0_irq_mask << 16) | epoch1_irq_mask;
 	cam_io_w_mb(computed_epoch_line_cfg,
 	cam_io_w_mb(computed_epoch_line_cfg,
 		rsrc_data->mem_base + rsrc_data->fe_reg->epoch_irq);
 		rsrc_data->mem_base + rsrc_data->fe_reg->epoch_irq);
-	CAM_DBG(CAM_ISP, "first_line:0x%x last_line:0x%x epoch_line_cfg: 0x%x",
+	CAM_DBG(CAM_ISP,
+		"first_line:0x%x last_line:0x%x vbi:0x%x epoch_line_cfg: 0x%x",
 		rsrc_data->first_line, rsrc_data->last_line,
 		rsrc_data->first_line, rsrc_data->last_line,
-		computed_epoch_line_cfg);
+		rsrc_data->vbi_value, computed_epoch_line_cfg);
 
 
 	fe_res->res_state = CAM_ISP_RESOURCE_STATE_STREAMING;
 	fe_res->res_state = CAM_ISP_RESOURCE_STATE_STREAMING;
 
 
@@ -446,6 +453,23 @@ static int cam_vfe_fe_sof_irq_debug(
 	return 0;
 	return 0;
 }
 }
 
 
+static int cam_vfe_fe_blanking_update(
+	struct cam_isp_resource_node *rsrc_node, void *cmd_args)
+{
+	struct cam_vfe_mux_fe_data *fe_priv =
+		(struct cam_vfe_mux_fe_data *)rsrc_node->res_priv;
+
+	struct cam_isp_blanking_config  *blanking_config =
+		(struct cam_isp_blanking_config *)cmd_args;
+
+	fe_priv->hbi_value = blanking_config->hbi;
+	fe_priv->vbi_value = blanking_config->vbi;
+	CAM_DBG(CAM_ISP, "hbi:%d vbi:%d",
+		fe_priv->hbi_value, fe_priv->vbi_value);
+
+	return 0;
+}
+
 static int cam_vfe_fe_process_cmd(struct cam_isp_resource_node *rsrc_node,
 static int cam_vfe_fe_process_cmd(struct cam_isp_resource_node *rsrc_node,
 	uint32_t cmd_type, void *cmd_args, uint32_t arg_size)
 	uint32_t cmd_type, void *cmd_args, uint32_t arg_size)
 {
 {
@@ -467,6 +491,9 @@ static int cam_vfe_fe_process_cmd(struct cam_isp_resource_node *rsrc_node,
 	case CAM_ISP_HW_CMD_FE_UPDATE_IN_RD:
 	case CAM_ISP_HW_CMD_FE_UPDATE_IN_RD:
 		rc = cam_vfe_fe_update(rsrc_node, cmd_args, arg_size);
 		rc = cam_vfe_fe_update(rsrc_node, cmd_args, arg_size);
 		break;
 		break;
+	case CAM_ISP_HW_CMD_BLANKING_UPDATE:
+		rc = cam_vfe_fe_blanking_update(rsrc_node, cmd_args);
+		break;
 	default:
 	default:
 		CAM_ERR(CAM_ISP,
 		CAM_ERR(CAM_ISP,
 			"unsupported process command:%d", cmd_type);
 			"unsupported process command:%d", cmd_type);

+ 28 - 0
drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_top_ver2.c

@@ -169,6 +169,31 @@ static int cam_vfe_top_clock_update(
 	return rc;
 	return rc;
 }
 }
 
 
+static int cam_vfe_top_blanking_update(uint32_t cmd_type,
+	void *cmd_args, uint32_t arg_size)
+{
+	struct cam_isp_blanking_config       *blanking_config = NULL;
+	struct cam_isp_resource_node         *node_res = NULL;
+
+	blanking_config =
+		(struct cam_isp_blanking_config *)cmd_args;
+	node_res = blanking_config->node_res;
+
+	if (!node_res) {
+		CAM_ERR(CAM_PERF, "Invalid input res %pK", node_res);
+		return -EINVAL;
+	}
+
+	if (!node_res->process_cmd) {
+		CAM_ERR(CAM_PERF, "Invalid input res process_cmd %pK",
+			node_res->process_cmd);
+		return -EINVAL;
+	}
+
+	return node_res->process_cmd(node_res,
+		cmd_type, cmd_args, arg_size);
+}
+
 static int cam_vfe_top_mux_get_reg_update(
 static int cam_vfe_top_mux_get_reg_update(
 	struct cam_vfe_top_ver2_priv *top_priv,
 	struct cam_vfe_top_ver2_priv *top_priv,
 	void *cmd_args, uint32_t arg_size)
 	void *cmd_args, uint32_t arg_size)
@@ -795,6 +820,9 @@ int cam_vfe_top_process_cmd(void *device_priv, uint32_t cmd_type,
 	case CAM_ISP_HW_CMD_ADD_WAIT_TRIGGER:
 	case CAM_ISP_HW_CMD_ADD_WAIT_TRIGGER:
 		rc = cam_vfe_top_add_wait_trigger(top_priv, cmd_args, arg_size);
 		rc = cam_vfe_top_add_wait_trigger(top_priv, cmd_args, arg_size);
 		break;
 		break;
+	case CAM_ISP_HW_CMD_BLANKING_UPDATE:
+		rc = cam_vfe_top_blanking_update(cmd_type, cmd_args, arg_size);
+		break;
 	default:
 	default:
 		rc = -EINVAL;
 		rc = -EINVAL;
 		CAM_ERR(CAM_ISP, "Error! Invalid cmd:%d", cmd_type);
 		CAM_ERR(CAM_ISP, "Error! Invalid cmd:%d", cmd_type);

+ 29 - 0
drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_top_ver3.c

@@ -189,6 +189,31 @@ static int cam_vfe_top_ver3_clock_update(
 	return rc;
 	return rc;
 }
 }
 
 
+static int cam_vfe_top_ver3_blanking_update(uint32_t cmd_type,
+	void *cmd_args, uint32_t arg_size)
+{
+	struct cam_isp_blanking_config       *blanking_config = NULL;
+	struct cam_isp_resource_node         *node_res = NULL;
+
+	blanking_config =
+		(struct cam_isp_blanking_config *)cmd_args;
+	node_res = blanking_config->node_res;
+
+	if (!node_res) {
+		CAM_ERR(CAM_PERF, "Invalid input res %pK", node_res);
+		return -EINVAL;
+	}
+
+	if (!node_res->process_cmd) {
+		CAM_ERR(CAM_PERF, "Invalid input res process_cmd %pK",
+			node_res->process_cmd);
+		return -EINVAL;
+	}
+
+	return node_res->process_cmd(node_res,
+		cmd_type, cmd_args, arg_size);
+}
+
 static int cam_vfe_core_config_control(
 static int cam_vfe_core_config_control(
 	struct cam_vfe_top_ver3_priv *top_priv,
 	struct cam_vfe_top_ver3_priv *top_priv,
 	 void *cmd_args, uint32_t arg_size)
 	 void *cmd_args, uint32_t arg_size)
@@ -727,6 +752,10 @@ int cam_vfe_top_ver3_process_cmd(void *device_priv, uint32_t cmd_type,
 	case CAM_ISP_HW_CMD_ADD_WAIT_TRIGGER:
 	case CAM_ISP_HW_CMD_ADD_WAIT_TRIGGER:
 		rc = cam_vfe_top_add_wait_trigger(top_priv, cmd_args, arg_size);
 		rc = cam_vfe_top_add_wait_trigger(top_priv, cmd_args, arg_size);
 		break;
 		break;
+	case CAM_ISP_HW_CMD_BLANKING_UPDATE:
+		rc = cam_vfe_top_ver3_blanking_update(cmd_type,
+			cmd_args, arg_size);
+		break;
 	default:
 	default:
 		rc = -EINVAL;
 		rc = -EINVAL;
 		CAM_ERR(CAM_ISP, "Error, Invalid cmd:%d", cmd_type);
 		CAM_ERR(CAM_ISP, "Error, Invalid cmd:%d", cmd_type);

+ 12 - 0
include/uapi/camera/media/cam_isp.h

@@ -107,6 +107,7 @@
 #define CAM_ISP_GENERIC_BLOB_TYPE_CSID_CONFIG               10
 #define CAM_ISP_GENERIC_BLOB_TYPE_CSID_CONFIG               10
 #define CAM_ISP_GENERIC_BLOB_TYPE_SENSOR_DIMENSION_CONFIG   11
 #define CAM_ISP_GENERIC_BLOB_TYPE_SENSOR_DIMENSION_CONFIG   11
 #define CAM_ISP_GENERIC_BLOB_TYPE_CSID_QCFA_CONFIG          12
 #define CAM_ISP_GENERIC_BLOB_TYPE_CSID_QCFA_CONFIG          12
+#define CAM_ISP_GENERIC_BLOB_TYPE_SENSOR_BLANKING_CONFIG    13
 
 
 #define CAM_ISP_VC_DT_CFG    4
 #define CAM_ISP_VC_DT_CFG    4
 
 
@@ -616,6 +617,17 @@ struct cam_isp_sensor_dimension {
 	__u32 measure_enabled;
 	__u32 measure_enabled;
 } __attribute__((packed));
 } __attribute__((packed));
 
 
+/**
+ * struct cam_isp_sensor_blanking_config
+ *
+ * @hbi             HBI value
+ * @vbi             VBI value
+ */
+struct cam_isp_sensor_blanking_config {
+	__u32 hbi;
+	__u32 vbi;
+} __attribute__((packed));
+
 /**
 /**
  * struct cam_isp_sensor_config - Sensor Dimension configuration
  * struct cam_isp_sensor_config - Sensor Dimension configuration
  *
  *