Explorar el Código

msm: camera: sensor: Add bubble update packet support

This change adds bubble update packet support, when the
sensor mode or feature mask of bubble req is different
with last applied, we can use bubble update packet to
recovery the sensor mode and feature, then the bubble
req can get frame from correct sensor mode and feature.

CRs-Fixed: 3317352
Change-Id: Ia80b578044e74cc5062f9f6c12c5ae8edd2049ac
Signed-off-by: Depeng Shao <[email protected]>
Signed-off-by: Karthik Anantha Ram <[email protected]>
Depeng Shao hace 2 años
padre
commit
4d1434445f

+ 5 - 0
drivers/cam_req_mgr/cam_req_mgr_core.c

@@ -1066,6 +1066,11 @@ static int __cam_req_mgr_send_req(struct cam_req_mgr_core_link *link,
 			apply_req.re_apply = true;
 	}
 
+	if (link->state == CAM_CRM_LINK_STATE_ERR)
+		apply_req.recovery = true;
+	else
+		apply_req.recovery = false;
+
 	apply_data = link->req.apply_data;
 
 	/*

+ 3 - 1
drivers/cam_req_mgr/cam_req_mgr_interface.h

@@ -352,15 +352,17 @@ struct cam_req_mgr_core_dev_link_setup {
  * @report_if_bubble : report to crm if failure in applying
  * @trigger_point    : the trigger point of this apply
  * @re_apply         : to skip re_apply for buf_done request
+ * @recovery         : Indicate if it is recovery req
  *
  */
 struct cam_req_mgr_apply_request {
 	int32_t    link_hdl;
 	int32_t    dev_hdl;
-	uint64_t   request_id;
+	int64_t    request_id;
 	int32_t    report_if_bubble;
 	uint32_t   trigger_point;
 	bool       re_apply;
+	bool       recovery;
 };
 
 /**

+ 154 - 21
drivers/cam_sensor_module/cam_sensor/cam_sensor_core.c

@@ -121,7 +121,7 @@ static void cam_sensor_release_per_frame_resource(
 				rc = delete_request(i2c_set);
 				if (rc < 0)
 					CAM_ERR(CAM_SENSOR,
-						"delete request: %lld rc: %d",
+						"delete per frame setting for request: %lld rc: %d",
 						i2c_set->request_id, rc);
 			}
 		}
@@ -135,7 +135,21 @@ static void cam_sensor_release_per_frame_resource(
 				rc = delete_request(i2c_set);
 				if (rc < 0)
 					CAM_ERR(CAM_SENSOR,
-						"delete request: %lld rc: %d",
+						"delete frame skip setting for request: %lld rc: %d",
+						i2c_set->request_id, rc);
+			}
+		}
+	}
+
+	if (s_ctrl->i2c_data.bubble_update != NULL) {
+		for (i = 0; i < MAX_PER_FRAME_ARRAY; i++) {
+			i2c_set = &(s_ctrl->i2c_data.bubble_update[i]);
+			if (i2c_set->is_settings_valid == 1) {
+				i2c_set->is_settings_valid = -1;
+				rc = delete_request(i2c_set);
+				if (rc < 0)
+					CAM_ERR(CAM_SENSOR,
+						"delete bubble update setting for request: %lld rc: %d",
 						i2c_set->request_id, rc);
 			}
 		}
@@ -146,6 +160,7 @@ static int cam_sensor_handle_res_info(struct cam_sensor_res_info *res_info,
 	struct cam_sensor_ctrl_t *s_ctrl)
 {
 	int rc = 0;
+	uint32_t idx = 0;
 
 	if (!s_ctrl || !res_info) {
 		CAM_ERR(CAM_SENSOR, "Invalid params: res_info: %s, s_ctrl: %s",
@@ -154,19 +169,30 @@ static int cam_sensor_handle_res_info(struct cam_sensor_res_info *res_info,
 		return -EINVAL;
 	}
 
-	s_ctrl->sensor_res.res_index = res_info->res_index;
-	strscpy(s_ctrl->sensor_res.caps, res_info->caps,
-		sizeof(s_ctrl->sensor_res.caps));
-	s_ctrl->sensor_res.width = res_info->width;
-	s_ctrl->sensor_res.height = res_info->height;
-	s_ctrl->sensor_res.fps = res_info->fps;
+	idx = s_ctrl->last_updated_req % MAX_PER_FRAME_ARRAY;
+
+	s_ctrl->sensor_res[idx].res_index = res_info->res_index;
+	strscpy(s_ctrl->sensor_res[idx].caps, res_info->caps,
+		sizeof(s_ctrl->sensor_res[idx].caps));
+	s_ctrl->sensor_res[idx].width = res_info->width;
+	s_ctrl->sensor_res[idx].height = res_info->height;
+	s_ctrl->sensor_res[idx].fps = res_info->fps;
+
+	if (res_info->num_valid_params > 0) {
+		if (res_info->valid_param_mask & CAM_SENSOR_FEATURE_MASK)
+			s_ctrl->sensor_res[idx].feature_mask =
+				res_info->params[0];
+	}
+
+	s_ctrl->is_res_info_updated = true;
 
 	/* If request id is 0, it will be during an initial config/acquire */
-	CAM_INFO(CAM_SENSOR,
-		"Res index switch for request id: %lu, index: %u, width: 0x%x, height: 0x%x, capability: %s, fps: %u",
-		s_ctrl->sensor_res.request_id, s_ctrl->sensor_res.res_index,
-		s_ctrl->sensor_res.width, s_ctrl->sensor_res.height,
-		s_ctrl->sensor_res.caps, s_ctrl->sensor_res.fps);
+	CAM_DBG(CAM_SENSOR,
+		"Feature: 0x%x updated for request id: %lu, res index: %u, width: 0x%x, height: 0x%x, capability: %s, fps: %u",
+		s_ctrl->sensor_res[idx].feature_mask,
+		s_ctrl->sensor_res[idx].request_id, s_ctrl->sensor_res[idx].res_index,
+		s_ctrl->sensor_res[idx].width, s_ctrl->sensor_res[idx].height,
+		s_ctrl->sensor_res[idx].caps, s_ctrl->sensor_res[idx].fps);
 
 	return rc;
 }
@@ -219,7 +245,8 @@ static int32_t cam_sensor_i2c_pkt_parse(struct cam_sensor_ctrl_t *s_ctrl,
 	size_t len_of_buff = 0;
 	size_t remain_len = 0;
 	uint32_t *offset = NULL;
-	uint32_t cmd_buf_type;
+	int64_t prev_updated_req;
+	uint32_t cmd_buf_type, idx;
 	struct cam_config_dev_cmd config;
 	struct i2c_data_settings *i2c_data = NULL;
 
@@ -280,6 +307,10 @@ static int32_t cam_sensor_i2c_pkt_parse(struct cam_sensor_ctrl_t *s_ctrl,
 	if (csl_packet->header.request_id > s_ctrl->last_flush_req)
 		s_ctrl->last_flush_req = 0;
 
+	prev_updated_req = s_ctrl->last_updated_req;
+	s_ctrl->last_updated_req = csl_packet->header.request_id;
+	s_ctrl->is_res_info_updated = false;
+
 	i2c_data = &(s_ctrl->i2c_data);
 	CAM_DBG(CAM_SENSOR, "Header OpCode: %d", csl_packet->header.op_code);
 	switch (csl_packet->header.op_code & 0xFFFFFF) {
@@ -385,6 +416,22 @@ static int32_t cam_sensor_i2c_pkt_parse(struct cam_sensor_ctrl_t *s_ctrl,
 			csl_packet->header.request_id);
 		break;
 	}
+	case CAM_SENSOR_PACKET_OPCODE_SENSOR_BUBBLE_UPDATE: {
+		if ((s_ctrl->sensor_state == CAM_SENSOR_INIT) ||
+			(s_ctrl->sensor_state == CAM_SENSOR_ACQUIRE)) {
+			CAM_WARN(CAM_SENSOR,
+				"Rxed Update packets without linking");
+			goto end;
+		}
+
+		i2c_reg_settings =
+			&i2c_data->bubble_update[csl_packet->header.request_id %
+				MAX_PER_FRAME_ARRAY];
+		CAM_DBG(CAM_SENSOR, "Received bubble update packet: %lld req: %lld",
+			csl_packet->header.request_id % MAX_PER_FRAME_ARRAY,
+			csl_packet->header.request_id);
+		break;
+	}
 	case CAM_SENSOR_PACKET_OPCODE_SENSOR_NOP: {
 		if ((s_ctrl->sensor_state == CAM_SENSOR_INIT) ||
 			(s_ctrl->sensor_state == CAM_SENSOR_ACQUIRE)) {
@@ -434,7 +481,9 @@ static int32_t cam_sensor_i2c_pkt_parse(struct cam_sensor_ctrl_t *s_ctrl,
 				csl_packet->header.op_code & 0xFFFFFF);
 			goto end;
 		}
-		s_ctrl->sensor_res.request_id = csl_packet->header.request_id;
+
+		idx = s_ctrl->last_updated_req % MAX_PER_FRAME_ARRAY;
+		s_ctrl->sensor_res[idx].request_id = csl_packet->header.request_id;
 
 		/**
 		 * is_settings_valid is set to false for this case, as generic
@@ -450,11 +499,19 @@ static int32_t cam_sensor_i2c_pkt_parse(struct cam_sensor_ctrl_t *s_ctrl,
 		rc = cam_packet_util_process_generic_cmd_buffer(cmd_desc,
 			cam_sensor_generic_blob_handler, s_ctrl);
 		if (rc)
-			s_ctrl->sensor_res.request_id = 0;
+			s_ctrl->sensor_res[idx].request_id = 0;
 
 		break;
 	}
 
+	/*
+	 * If no res info in current request, then we pick previous
+	 * resolution info as current resolution info.
+	 */
+	if (!s_ctrl->is_res_info_updated)
+		s_ctrl->sensor_res[s_ctrl->last_updated_req % MAX_PER_FRAME_ARRAY] =
+			s_ctrl->sensor_res[prev_updated_req % MAX_PER_FRAME_ARRAY];
+
 	if ((csl_packet->header.op_code & 0xFFFFFF) ==
 		CAM_SENSOR_PACKET_OPCODE_SENSOR_UPDATE) {
 		i2c_reg_settings->request_id =
@@ -473,6 +530,12 @@ static int32_t cam_sensor_i2c_pkt_parse(struct cam_sensor_ctrl_t *s_ctrl,
 			csl_packet->header.request_id;
 	}
 
+	if ((csl_packet->header.op_code & 0xFFFFFF) ==
+		CAM_SENSOR_PACKET_OPCODE_SENSOR_BUBBLE_UPDATE) {
+		i2c_reg_settings->request_id =
+			csl_packet->header.request_id;
+	}
+
 end:
 	return rc;
 }
@@ -943,7 +1006,7 @@ int cam_sensor_stream_off(struct cam_sensor_ctrl_t *s_ctrl)
 	cam_sensor_release_per_frame_resource(s_ctrl);
 	s_ctrl->last_flush_req = 0;
 	s_ctrl->sensor_state = CAM_SENSOR_ACQUIRE;
-	memset(&s_ctrl->sensor_res, 0, sizeof(s_ctrl->sensor_res));
+	memset(s_ctrl->sensor_res, 0, sizeof(s_ctrl->sensor_res));
 
 	CAM_GET_TIMESTAMP(ts);
 	CAM_CONVERT_TIMESTAMP_FORMAT(ts, hrs, min, sec, ms);
@@ -1183,6 +1246,9 @@ int32_t cam_sensor_driver_cmd(struct cam_sensor_ctrl_t *s_ctrl,
 		s_ctrl->sensor_state = CAM_SENSOR_ACQUIRE;
 		s_ctrl->last_flush_req = 0;
 		s_ctrl->is_stopped_by_user = false;
+		s_ctrl->last_updated_req = 0;
+		s_ctrl->last_applied_req = 0;
+		memset(s_ctrl->sensor_res, 0, sizeof(s_ctrl->sensor_res));
 		CAM_INFO(CAM_SENSOR,
 			"CAM_ACQUIRE_DEV Success for %s sensor_id:0x%x,sensor_slave_addr:0x%x",
 			s_ctrl->sensor_name,
@@ -1653,7 +1719,7 @@ int cam_sensor_power_down(struct cam_sensor_ctrl_t *s_ctrl)
 }
 
 int cam_sensor_apply_settings(struct cam_sensor_ctrl_t *s_ctrl,
-	uint64_t req_id, enum cam_sensor_packet_opcodes opcode)
+	int64_t req_id, enum cam_sensor_packet_opcodes opcode)
 {
 	int rc = 0, offset, i;
 	uint64_t top = 0, del_req_id = 0;
@@ -1712,7 +1778,16 @@ int cam_sensor_apply_settings(struct cam_sensor_ctrl_t *s_ctrl,
 
 		if (opcode == CAM_SENSOR_PACKET_OPCODE_SENSOR_FRAME_SKIP_UPDATE)
 			i2c_set = s_ctrl->i2c_data.frame_skip;
-		else
+		else if (opcode == CAM_SENSOR_PACKET_OPCODE_SENSOR_BUBBLE_UPDATE) {
+			i2c_set = s_ctrl->i2c_data.bubble_update;
+			/*
+			 * If bubble update isn't valid, then we just use
+			 * per frame update.
+			 */
+			if (!(i2c_set[offset].is_settings_valid == 1) &&
+				(i2c_set[offset].request_id == req_id))
+				i2c_set = s_ctrl->i2c_data.per_frame;
+		} else
 			i2c_set = s_ctrl->i2c_data.per_frame;
 
 		if (i2c_set[offset].is_settings_valid == 1 &&
@@ -1736,6 +1811,9 @@ int cam_sensor_apply_settings(struct cam_sensor_ctrl_t *s_ctrl,
 		}
 
 		s_ctrl->last_applied_req = req_id;
+		CAM_DBG(CAM_REQ,
+			"Sensor[%d] updating last_applied [req id: %lld last_applied: %lld] with opcode:%d",
+			s_ctrl->soc_info.index, req_id, s_ctrl->last_applied_req, opcode);
 
 		/* Change the logic dynamically */
 		for (i = 0; i < MAX_PER_FRAME_ARRAY; i++) {
@@ -1778,6 +1856,34 @@ int cam_sensor_apply_settings(struct cam_sensor_ctrl_t *s_ctrl,
 						del_req_id, rc);
 			}
 		}
+
+		/*
+		 * If the op code is bubble update, then we also need to delete
+		 * req for per frame update, vice versa.
+		 */
+		if (opcode == CAM_SENSOR_PACKET_OPCODE_SENSOR_BUBBLE_UPDATE)
+			i2c_set = s_ctrl->i2c_data.per_frame;
+		else if (opcode == CAM_SENSOR_PACKET_OPCODE_SENSOR_UPDATE)
+			i2c_set = s_ctrl->i2c_data.bubble_update;
+		else
+			i2c_set = NULL;
+
+		if (i2c_set) {
+			for (i = 0; i < MAX_PER_FRAME_ARRAY; i++) {
+				if ((del_req_id >
+					 i2c_set[i].request_id) && (
+					 i2c_set[i].is_settings_valid
+						== 1)) {
+					i2c_set[i].request_id = 0;
+					rc = delete_request(
+						&(i2c_set[i]));
+					if (rc < 0)
+						CAM_ERR(CAM_SENSOR,
+							"Delete request Fail:%lld rc:%d",
+							del_req_id, rc);
+				}
+			}
+		}
 	}
 
 	return rc;
@@ -1787,6 +1893,7 @@ int32_t cam_sensor_apply_request(struct cam_req_mgr_apply_request *apply)
 {
 	int32_t rc = 0;
 	struct cam_sensor_ctrl_t *s_ctrl = NULL;
+	int32_t curr_idx, last_applied_idx;
 	enum cam_sensor_packet_opcodes opcode =
 		CAM_SENSOR_PACKET_OPCODE_SENSOR_UPDATE;
 
@@ -1800,9 +1907,35 @@ int32_t cam_sensor_apply_request(struct cam_req_mgr_apply_request *apply)
 		return -EINVAL;
 	}
 
-	CAM_DBG(CAM_REQ, " Sensor[%d] update req id: %lld",
-		s_ctrl->soc_info.index, apply->request_id);
+	if ((apply->recovery) && (apply->request_id > 0)) {
+		curr_idx = apply->request_id % MAX_PER_FRAME_ARRAY;
+		last_applied_idx = s_ctrl->last_applied_req % MAX_PER_FRAME_ARRAY;
+
+		/*
+		 * If the sensor resolution index in current req isn't same with
+		 * last applied index, we should apply bubble update.
+		 */
+
+		if ((s_ctrl->sensor_res[curr_idx].res_index !=
+			s_ctrl->sensor_res[last_applied_idx].res_index) ||
+			(s_ctrl->sensor_res[curr_idx].feature_mask !=
+			s_ctrl->sensor_res[last_applied_idx].feature_mask)) {
+			opcode = CAM_SENSOR_PACKET_OPCODE_SENSOR_BUBBLE_UPDATE;
+			CAM_INFO(CAM_REQ,
+				"Sensor[%d] update req id: %lld [last_applied: %lld] with opcode:%d recovery: %d last_applied_res_idx: %u current_res_idx: %u",
+				s_ctrl->soc_info.index, apply->request_id,
+				s_ctrl->last_applied_req, opcode, apply->recovery,
+				s_ctrl->sensor_res[last_applied_idx].res_index,
+				s_ctrl->sensor_res[curr_idx].res_index);
+		}
+	}
+
+	CAM_DBG(CAM_REQ,
+		"Sensor[%d] update req id: %lld [last_applied: %lld] with opcode:%d recovery: %d",
+		s_ctrl->soc_info.index, apply->request_id,
+		s_ctrl->last_applied_req, opcode, apply->recovery);
 	trace_cam_apply_req("Sensor", s_ctrl->soc_info.index, apply->request_id, apply->link_hdl);
+
 	mutex_lock(&(s_ctrl->cam_sensor_mutex));
 	rc = cam_sensor_apply_settings(s_ctrl, apply->request_id,
 		opcode);

+ 1 - 1
drivers/cam_sensor_module/cam_sensor/cam_sensor_core.h

@@ -38,7 +38,7 @@ int cam_sensor_power(struct v4l2_subdev *sd, int on);
  *
  * This API applies the req_id settings to sensor
  */
-int cam_sensor_apply_settings(struct cam_sensor_ctrl_t *s_ctrl, uint64_t req_id,
+int cam_sensor_apply_settings(struct cam_sensor_ctrl_t *s_ctrl, int64_t req_id,
 	enum cam_sensor_packet_opcodes opcode);
 
 /**

+ 25 - 0
drivers/cam_sensor_module/cam_sensor/cam_sensor_dev.c

@@ -267,6 +267,14 @@ static int cam_sensor_i2c_component_bind(struct device *dev,
 		goto free_perframe;
 	}
 
+	s_ctrl->i2c_data.bubble_update =
+		kzalloc(sizeof(struct i2c_settings_array) *
+		MAX_PER_FRAME_ARRAY, GFP_KERNEL);
+	if (s_ctrl->i2c_data.bubble_update == NULL) {
+		rc = -ENOMEM;
+		goto free_frame_skip;
+	}
+
 	INIT_LIST_HEAD(&(s_ctrl->i2c_data.init_settings.list_head));
 	INIT_LIST_HEAD(&(s_ctrl->i2c_data.config_settings.list_head));
 	INIT_LIST_HEAD(&(s_ctrl->i2c_data.streamon_settings.list_head));
@@ -278,6 +286,7 @@ static int cam_sensor_i2c_component_bind(struct device *dev,
 	for (i = 0; i < MAX_PER_FRAME_ARRAY; i++) {
 		INIT_LIST_HEAD(&(s_ctrl->i2c_data.per_frame[i].list_head));
 		INIT_LIST_HEAD(&(s_ctrl->i2c_data.frame_skip[i].list_head));
+		INIT_LIST_HEAD(&(s_ctrl->i2c_data.bubble_update[i].list_head));
 	}
 
 	s_ctrl->bridge_intf.device_hdl = -1;
@@ -292,6 +301,9 @@ static int cam_sensor_i2c_component_bind(struct device *dev,
 	s_ctrl->sensordata->power_info.dev = soc_info->dev;
 
 	return rc;
+
+free_frame_skip:
+	kfree(s_ctrl->i2c_data.frame_skip);
 free_perframe:
 	kfree(s_ctrl->i2c_data.per_frame);
 unreg_subdev:
@@ -330,6 +342,7 @@ static void cam_sensor_i2c_component_unbind(struct device *dev,
 
 	kfree(s_ctrl->i2c_data.per_frame);
 	kfree(s_ctrl->i2c_data.frame_skip);
+	kfree(s_ctrl->i2c_data.bubble_update);
 	v4l2_set_subdevdata(&(s_ctrl->v4l2_dev_str.sd), NULL);
 	kfree(s_ctrl);
 }
@@ -436,6 +449,14 @@ static int cam_sensor_component_bind(struct device *dev,
 		goto free_perframe;
 	}
 
+	s_ctrl->i2c_data.bubble_update =
+		kzalloc(sizeof(struct i2c_settings_array) *
+		MAX_PER_FRAME_ARRAY, GFP_KERNEL);
+	if (s_ctrl->i2c_data.bubble_update == NULL) {
+		rc = -ENOMEM;
+		goto free_frame_skip;
+	}
+
 	INIT_LIST_HEAD(&(s_ctrl->i2c_data.init_settings.list_head));
 	INIT_LIST_HEAD(&(s_ctrl->i2c_data.config_settings.list_head));
 	INIT_LIST_HEAD(&(s_ctrl->i2c_data.streamon_settings.list_head));
@@ -447,6 +468,7 @@ static int cam_sensor_component_bind(struct device *dev,
 	for (i = 0; i < MAX_PER_FRAME_ARRAY; i++) {
 		INIT_LIST_HEAD(&(s_ctrl->i2c_data.per_frame[i].list_head));
 		INIT_LIST_HEAD(&(s_ctrl->i2c_data.frame_skip[i].list_head));
+		INIT_LIST_HEAD(&(s_ctrl->i2c_data.bubble_update[i].list_head));
 	}
 
 	s_ctrl->bridge_intf.device_hdl = -1;
@@ -469,6 +491,8 @@ static int cam_sensor_component_bind(struct device *dev,
 
 	return rc;
 
+free_frame_skip:
+	kfree(s_ctrl->i2c_data.frame_skip);
 free_perframe:
 	kfree(s_ctrl->i2c_data.per_frame);
 unreg_subdev:
@@ -514,6 +538,7 @@ static void cam_sensor_component_unbind(struct device *dev,
 
 	kfree(s_ctrl->i2c_data.per_frame);
 	kfree(s_ctrl->i2c_data.frame_skip);
+	kfree(s_ctrl->i2c_data.bubble_update);
 	platform_set_drvdata(pdev, NULL);
 	v4l2_set_subdevdata(&(s_ctrl->v4l2_dev_str.sd), NULL);
 	devm_kfree(&pdev->dev, s_ctrl);

+ 8 - 2
drivers/cam_sensor_module/cam_sensor/cam_sensor_dev.h

@@ -60,16 +60,18 @@ struct sensor_intf_params {
  *
  * @res_index        : The resolution index that gets updated
  *                     during a mode switch
+ * @feature_mask     : Feature mask
  * @fps              : Frame rate
  * @width            : Pixel width to output to csiphy
  * @height           : Pixel height to output to csiphy
- * @num_exposures    : For sHDR, etc purposes, 1, or more
+ * request_id        : Request Id
  * @caps             : Specifies capability sensor is configured
  *                     for, (eg, XCFA, HFR), num_exposures and
  *                     PDAF type
  */
 struct cam_sensor_dev_res_info {
 	uint16_t   res_index;
+	uint16_t   feature_mask;
 	uint32_t   fps;
 	uint32_t   width;
 	uint32_t   height;
@@ -106,9 +108,11 @@ struct cam_sensor_dev_res_info {
  * @pipeline_delay: Sensor pipeline delay
  * @sensor_name: Sensor name
  * @aon_camera_id: AON Camera ID associated with this sensor
+ * @last_applied_req: Last updated request id
  * @last_applied_req: Last applied request id
  * @is_stopped_by_user: Indicate if sensor has been stopped by userland
  * @stream_off_after_eof: Indicates if sensor needs to stream off after eof
+ * @is_res_info_updated: Indicate if resolution info is updated
  */
 struct cam_sensor_ctrl_t {
 	char                           device_name[CAM_CTX_DEV_NAME_MAX_LENGTH];
@@ -116,7 +120,7 @@ struct cam_sensor_ctrl_t {
 	struct cam_hw_soc_info         soc_info;
 	struct mutex                   cam_sensor_mutex;
 	struct cam_sensor_board_info  *sensordata;
-	struct cam_sensor_dev_res_info sensor_res;
+	struct cam_sensor_dev_res_info sensor_res[MAX_PER_FRAME_ARRAY];
 	enum cci_i2c_master_t          cci_i2c_master;
 	enum cci_device_num            cci_num;
 	struct camera_io_master        io_master_info;
@@ -139,9 +143,11 @@ struct cam_sensor_ctrl_t {
 	uint16_t                       pipeline_delay;
 	char                           sensor_name[CAM_SENSOR_NAME_MAX_SIZE];
 	uint8_t                        aon_camera_id;
+	int64_t                        last_updated_req;
 	int64_t                        last_applied_req;
 	bool                           is_stopped_by_user;
 	bool                           stream_off_after_eof;
+	bool                           is_res_info_updated;
 };
 
 /**

+ 1 - 0
drivers/cam_sensor_module/cam_sensor_utils/cam_sensor_cmn_header.h

@@ -246,6 +246,7 @@ struct i2c_data_settings {
 	struct i2c_settings_array read_settings;
 	struct i2c_settings_array *per_frame;
 	struct i2c_settings_array *frame_skip;
+	struct i2c_settings_array *bubble_update;
 	struct i2c_settings_array reg_bank_unlock_settings;
 	struct i2c_settings_array reg_bank_lock_settings;
 };

+ 10 - 0
include/uapi/camera/media/cam_sensor.h

@@ -121,6 +121,7 @@ enum cam_sensor_packet_opcodes {
 	CAM_SENSOR_PACKET_OPCODE_SENSOR_PROBE_V2,
 	CAM_SENSOR_PACKET_OPCODE_SENSOR_REG_BANK_UNLOCK,
 	CAM_SENSOR_PACKET_OPCODE_SENSOR_REG_BANK_LOCK,
+	CAM_SENSOR_PACKET_OPCODE_SENSOR_BUBBLE_UPDATE,
 	CAM_SENSOR_PACKET_OPCODE_SENSOR_NOP = 127,
 };
 
@@ -337,6 +338,15 @@ struct cam_cmd_i2c_info {
 	__u16    reserved;
 } __attribute__((packed));
 
+#define CAM_SENSOR_FEATURE_MASK                    BIT(0)
+
+#define CAM_SENSOR_FEATURE_NONE                    0
+#define CAM_SENSOR_FEATURE_AEB_ON                  BIT(0)
+#define CAM_SENSOR_FEATURE_AEB_UPDATE              BIT(1)
+#define CAM_SENSOR_FEATURE_AEB_OFF                 BIT(2)
+#define CAM_SENSOR_FEATURE_INSENSOR_HDR_3EXP_ON    BIT(3)
+#define CAM_SENSOR_FEATURE_INSENSOR_HDR_3EXP_OFF   BIT(4)
+
 /**
  * struct cam_cmd_sensor_res_info - Contains sensor res info
  *