Эх сурвалжийг харах

msm: camera: isp: Add per frame support for scratch buffers

If CRM skips applying settings on a given frame, in case of sHDR
program scratch buffers along with RUP/AUP to ensure
continuity with respect to sensor frames.

CRs-Fixed: 2841729
Change-Id: I296dbc713f49db54681043415b6ad1499dc13de4
Signed-off-by: Karthik Anantha Ram <[email protected]>
Karthik Anantha Ram 4 жил өмнө
parent
commit
fa9a698aa1

+ 4 - 7
drivers/cam_core/cam_hw_mgr_intf.h

@@ -1,6 +1,6 @@
 /* SPDX-License-Identifier: GPL-2.0-only */
 /* SPDX-License-Identifier: GPL-2.0-only */
 /*
 /*
- * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2017-2021, The Linux Foundation. All rights reserved.
  */
  */
 
 
 #ifndef _CAM_HW_MGR_INTF_H_
 #ifndef _CAM_HW_MGR_INTF_H_
@@ -113,9 +113,8 @@ struct cam_hw_done_event_data {
  * @acquire_info:          Acquired resource array pointer
  * @acquire_info:          Acquired resource array pointer
  * @ctxt_to_hw_map:        HW context (returned)
  * @ctxt_to_hw_map:        HW context (returned)
  * @hw_mgr_ctx_id          HWMgr context id(returned)
  * @hw_mgr_ctx_id          HWMgr context id(returned)
- * @custom_enabled:        ctx has custom enabled
- * @use_frame_header_ts:   Use frame header for qtimer ts
- * @support_consumed_addr: The platform has last consumed addr register
+ * @op_flags:              Used as bitwise params from hw_mgr to ctx
+ *                         See xxx_hw_mgr_intf.h for definitions
  * @acquired_hw_id:        Acquired hardware mask
  * @acquired_hw_id:        Acquired hardware mask
  * @acquired_hw_path:      Acquired path mask for an input
  * @acquired_hw_path:      Acquired path mask for an input
  *                         if input splits into multiple paths,
  *                         if input splits into multiple paths,
@@ -132,9 +131,7 @@ struct cam_hw_acquire_args {
 	uintptr_t                    acquire_info;
 	uintptr_t                    acquire_info;
 	void                        *ctxt_to_hw_map;
 	void                        *ctxt_to_hw_map;
 	uint32_t                     hw_mgr_ctx_id;
 	uint32_t                     hw_mgr_ctx_id;
-	bool                         custom_enabled;
-	bool                         use_frame_header_ts;
-	bool                         support_consumed_addr;
+	uint32_t                     op_flags;
 
 
 	uint32_t    acquired_hw_id[CAM_MAX_ACQ_RES];
 	uint32_t    acquired_hw_id[CAM_MAX_ACQ_RES];
 	uint32_t    acquired_hw_path[CAM_MAX_ACQ_RES][CAM_MAX_HW_SPLIT];
 	uint32_t    acquired_hw_path[CAM_MAX_ACQ_RES][CAM_MAX_HW_SPLIT];

+ 80 - 6
drivers/cam_isp/cam_isp_context.c

@@ -1,6 +1,6 @@
 // SPDX-License-Identifier: GPL-2.0-only
 // SPDX-License-Identifier: GPL-2.0-only
 /*
 /*
- * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2017-2021, The Linux Foundation. All rights reserved.
  */
  */
 
 
 #include <linux/debugfs.h>
 #include <linux/debugfs.h>
@@ -3275,6 +3275,32 @@ static int __cam_isp_ctx_apply_req_in_bubble(
 	return rc;
 	return rc;
 }
 }
 
 
+static int __cam_isp_ctx_apply_default_req_settings(
+	struct cam_context *ctx, struct cam_req_mgr_apply_request *apply)
+{
+	int rc = 0;
+	struct cam_isp_context *isp_ctx =
+		(struct cam_isp_context *) ctx->ctx_priv;
+	struct cam_hw_cmd_args        hw_cmd_args;
+	struct cam_isp_hw_cmd_args    isp_hw_cmd_args;
+
+	hw_cmd_args.ctxt_to_hw_map = isp_ctx->hw_ctx;
+	hw_cmd_args.cmd_type = CAM_HW_MGR_CMD_INTERNAL;
+	isp_hw_cmd_args.cmd_type =
+		CAM_ISP_HW_MGR_CMD_PROG_DEFAULT_CFG;
+	hw_cmd_args.u.internal_args = (void *)&isp_hw_cmd_args;
+
+	rc = ctx->hw_mgr_intf->hw_cmd(ctx->hw_mgr_intf->hw_mgr_priv,
+			&hw_cmd_args);
+	if (rc)
+		CAM_ERR(CAM_ISP,
+			"Failed to apply default settings rc %d", rc);
+	else
+		CAM_DBG(CAM_ISP, "Applied default settings rc %d", rc);
+
+	return rc;
+}
+
 static int __cam_isp_ctx_dump_req_info(
 static int __cam_isp_ctx_dump_req_info(
 	struct cam_context     *ctx,
 	struct cam_context     *ctx,
 	struct cam_ctx_request *req,
 	struct cam_ctx_request *req,
@@ -3670,6 +3696,8 @@ static struct cam_ctx_ops
 		.ioctl_ops = {},
 		.ioctl_ops = {},
 		.crm_ops = {
 		.crm_ops = {
 			.apply_req = __cam_isp_ctx_apply_req_in_sof,
 			.apply_req = __cam_isp_ctx_apply_req_in_sof,
+			.notify_frame_skip =
+				__cam_isp_ctx_apply_default_req_settings,
 		},
 		},
 		.irq_ops = NULL,
 		.irq_ops = NULL,
 	},
 	},
@@ -3684,6 +3712,8 @@ static struct cam_ctx_ops
 		.ioctl_ops = {},
 		.ioctl_ops = {},
 		.crm_ops = {
 		.crm_ops = {
 			.apply_req = __cam_isp_ctx_apply_req_in_epoch,
 			.apply_req = __cam_isp_ctx_apply_req_in_epoch,
+			.notify_frame_skip =
+				__cam_isp_ctx_apply_default_req_settings,
 		},
 		},
 		.irq_ops = NULL,
 		.irq_ops = NULL,
 	},
 	},
@@ -3692,6 +3722,8 @@ static struct cam_ctx_ops
 		.ioctl_ops = {},
 		.ioctl_ops = {},
 		.crm_ops = {
 		.crm_ops = {
 			.apply_req = __cam_isp_ctx_apply_req_in_bubble,
 			.apply_req = __cam_isp_ctx_apply_req_in_bubble,
+			.notify_frame_skip =
+				__cam_isp_ctx_apply_default_req_settings,
 		},
 		},
 		.irq_ops = NULL,
 		.irq_ops = NULL,
 	},
 	},
@@ -4306,6 +4338,7 @@ static int __cam_isp_ctx_release_hw_in_top_state(struct cam_context *ctx,
 	ctx->last_flush_req = 0;
 	ctx->last_flush_req = 0;
 	ctx_isp->custom_enabled = false;
 	ctx_isp->custom_enabled = false;
 	ctx_isp->use_frame_header_ts = false;
 	ctx_isp->use_frame_header_ts = false;
+	ctx_isp->use_default_apply = false;
 	ctx_isp->frame_id = 0;
 	ctx_isp->frame_id = 0;
 	ctx_isp->active_req_cnt = 0;
 	ctx_isp->active_req_cnt = 0;
 	ctx_isp->reported_req_id = 0;
 	ctx_isp->reported_req_id = 0;
@@ -4928,7 +4961,7 @@ static int __cam_isp_ctx_acquire_hw_v1(struct cam_context *ctx,
 	}
 	}
 
 
 	ctx_isp->support_consumed_addr =
 	ctx_isp->support_consumed_addr =
-		param.support_consumed_addr;
+		(param.op_flags & CAM_IFE_CTX_FRAME_HEADER_EN);
 
 
 	/* Query the context has rdi only resource */
 	/* Query the context has rdi only resource */
 	hw_cmd_args.ctxt_to_hw_map = param.ctxt_to_hw_map;
 	hw_cmd_args.ctxt_to_hw_map = param.ctxt_to_hw_map;
@@ -5077,13 +5110,18 @@ static int __cam_isp_ctx_acquire_hw_v2(struct cam_context *ctx,
 		goto free_res;
 		goto free_res;
 	}
 	}
 
 
-	/* Set custom flag if applicable
+	/*
+	 * Set feature flag if applicable
 	 * custom hw is supported only on v2
 	 * custom hw is supported only on v2
 	 */
 	 */
-	ctx_isp->custom_enabled = param.custom_enabled;
-	ctx_isp->use_frame_header_ts = param.use_frame_header_ts;
+	ctx_isp->custom_enabled =
+		(param.op_flags & CAM_IFE_CTX_CUSTOM_EN);
+	ctx_isp->use_frame_header_ts =
+		(param.op_flags & CAM_IFE_CTX_FRAME_HEADER_EN);
+	ctx_isp->use_default_apply =
+		(param.op_flags & CAM_IFE_CTX_APPLY_DEFAULT_CFG);
 	ctx_isp->support_consumed_addr =
 	ctx_isp->support_consumed_addr =
-		param.support_consumed_addr;
+		(param.op_flags & CAM_IFE_CTX_CONSUME_ADDR_EN);
 
 
 	/* Query the context has rdi only resource */
 	/* Query the context has rdi only resource */
 	hw_cmd_args.ctxt_to_hw_map = param.ctxt_to_hw_map;
 	hw_cmd_args.ctxt_to_hw_map = param.ctxt_to_hw_map;
@@ -5761,6 +5799,39 @@ static int __cam_isp_ctx_apply_req(struct cam_context *ctx,
 	return rc;
 	return rc;
 }
 }
 
 
+static int __cam_isp_ctx_apply_default_settings(
+	struct cam_context *ctx,
+	struct cam_req_mgr_apply_request *apply)
+{
+	int rc = 0;
+	struct cam_ctx_ops *ctx_ops = NULL;
+	struct cam_isp_context *ctx_isp =
+		(struct cam_isp_context *) ctx->ctx_priv;
+
+	if (!ctx_isp->use_default_apply)
+		return 0;
+
+	CAM_DBG(CAM_ISP,
+		"Enter: apply req in Substate %d request _id:%lld",
+		 ctx_isp->substate_activated, apply->request_id);
+
+	ctx_ops = &ctx_isp->substate_machine[
+		ctx_isp->substate_activated];
+	if (ctx_ops->crm_ops.notify_frame_skip) {
+		rc = ctx_ops->crm_ops.notify_frame_skip(ctx, apply);
+	} else {
+		CAM_WARN_RATE_LIMIT(CAM_ISP,
+			"No handle function in activated substate %d",
+			ctx_isp->substate_activated);
+		rc = -EFAULT;
+	}
+
+	if (rc)
+		CAM_WARN_RATE_LIMIT(CAM_ISP,
+			"Apply default failed in active substate %d rc %d",
+			ctx_isp->substate_activated, rc);
+	return rc;
+}
 
 
 
 
 static int __cam_isp_ctx_handle_irq_in_activated(void *context,
 static int __cam_isp_ctx_handle_irq_in_activated(void *context,
@@ -5878,6 +5949,8 @@ static struct cam_ctx_ops
 		.crm_ops = {
 		.crm_ops = {
 			.unlink = __cam_isp_ctx_unlink_in_activated,
 			.unlink = __cam_isp_ctx_unlink_in_activated,
 			.apply_req = __cam_isp_ctx_apply_req,
 			.apply_req = __cam_isp_ctx_apply_req,
+			.notify_frame_skip =
+				__cam_isp_ctx_apply_default_settings,
 			.flush_req = __cam_isp_ctx_flush_req_in_top_state,
 			.flush_req = __cam_isp_ctx_flush_req_in_top_state,
 			.process_evt = __cam_isp_ctx_process_evt,
 			.process_evt = __cam_isp_ctx_process_evt,
 			.dump_req = __cam_isp_ctx_dump_in_top_state,
 			.dump_req = __cam_isp_ctx_dump_in_top_state,
@@ -6078,6 +6151,7 @@ int cam_isp_context_init(struct cam_isp_context *ctx,
 	ctx->frame_id = 0;
 	ctx->frame_id = 0;
 	ctx->custom_enabled = false;
 	ctx->custom_enabled = false;
 	ctx->use_frame_header_ts = false;
 	ctx->use_frame_header_ts = false;
+	ctx->use_default_apply = false;
 	ctx->active_req_cnt = 0;
 	ctx->active_req_cnt = 0;
 	ctx->reported_req_id = 0;
 	ctx->reported_req_id = 0;
 	ctx->bubble_frame_cnt = 0;
 	ctx->bubble_frame_cnt = 0;

+ 3 - 1
drivers/cam_isp/cam_isp_context.h

@@ -1,6 +1,6 @@
 /* SPDX-License-Identifier: GPL-2.0-only */
 /* SPDX-License-Identifier: GPL-2.0-only */
 /*
 /*
- * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2017-2021, The Linux Foundation. All rights reserved.
  */
  */
 
 
 #ifndef _CAM_ISP_CONTEXT_H_
 #ifndef _CAM_ISP_CONTEXT_H_
@@ -270,6 +270,7 @@ struct cam_isp_context_event_record {
  * @use_frame_header_ts:       Use frame header for qtimer ts
  * @use_frame_header_ts:       Use frame header for qtimer ts
  * @support_consumed_addr:     Indicate whether HW has last consumed addr reg
  * @support_consumed_addr:     Indicate whether HW has last consumed addr reg
  * @apply_in_progress          Whether request apply is in progress
  * @apply_in_progress          Whether request apply is in progress
+ * @use_default_apply:         Use default settings in case of frame skip
  * @init_timestamp:            Timestamp at which this context is initialized
  * @init_timestamp:            Timestamp at which this context is initialized
  * @isp_device_type:           ISP device type
  * @isp_device_type:           ISP device type
  * @rxd_epoch:                 Indicate whether epoch has been received. Used to
  * @rxd_epoch:                 Indicate whether epoch has been received. Used to
@@ -318,6 +319,7 @@ struct cam_isp_context {
 	bool                                  use_frame_header_ts;
 	bool                                  use_frame_header_ts;
 	bool                                  support_consumed_addr;
 	bool                                  support_consumed_addr;
 	atomic_t                              apply_in_progress;
 	atomic_t                              apply_in_progress;
+	bool                                  use_default_apply;
 	unsigned int                          init_timestamp;
 	unsigned int                          init_timestamp;
 	uint32_t                              isp_device_type;
 	uint32_t                              isp_device_type;
 	atomic_t                              rxd_epoch;
 	atomic_t                              rxd_epoch;

+ 229 - 24
drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c

@@ -1,6 +1,6 @@
 // SPDX-License-Identifier: GPL-2.0-only
 // SPDX-License-Identifier: GPL-2.0-only
 /*
 /*
- * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2017-2021, The Linux Foundation. All rights reserved.
  */
  */
 
 
 #include <linux/slab.h>
 #include <linux/slab.h>
@@ -4047,6 +4047,9 @@ skip_csid_pxl:
 		}
 		}
 	}
 	}
 
 
+	if (in_port->dynamic_sensor_switch_en)
+		ife_ctx->ctx_config |= CAM_IFE_CTX_CFG_DYNAMIC_SWITCH_ON;
+
 	return 0;
 	return 0;
 err:
 err:
 	/* release resource at the acquire entry funciton */
 	/* release resource at the acquire entry funciton */
@@ -4357,7 +4360,7 @@ static int cam_ife_mgr_acquire_hw(void *hw_mgr_priv, void *acquire_hw_args)
 	}
 	}
 
 
 	cam_cpas_get_cpas_hw_version(&ife_ctx->hw_version);
 	cam_cpas_get_cpas_hw_version(&ife_ctx->hw_version);
-	ife_ctx->custom_config = 0;
+	ife_ctx->ctx_config = 0;
 	ife_ctx->cdm_handle = 0;
 	ife_ctx->cdm_handle = 0;
 	ife_ctx->ctx_type = CAM_IFE_CTX_TYPE_NONE;
 	ife_ctx->ctx_type = CAM_IFE_CTX_TYPE_NONE;
 
 
@@ -4420,10 +4423,10 @@ static int cam_ife_mgr_acquire_hw(void *hw_mgr_priv, void *acquire_hw_args)
 			if (in_port[i].cust_node) {
 			if (in_port[i].cust_node) {
 				ife_ctx->ctx_type = CAM_IFE_CTX_TYPE_CUSTOM;
 				ife_ctx->ctx_type = CAM_IFE_CTX_TYPE_CUSTOM;
 				/* These can be obtained from uapi */
 				/* These can be obtained from uapi */
-				ife_ctx->custom_config |=
-					CAM_IFE_CUSTOM_CFG_FRAME_HEADER_TS;
-				ife_ctx->custom_config |=
-					CAM_IFE_CUSTOM_CFG_SW_SYNC_ON;
+				ife_ctx->ctx_config |=
+					CAM_IFE_CTX_CFG_FRAME_HEADER_TS;
+				ife_ctx->ctx_config |=
+					CAM_IFE_CTX_CFG_SW_SYNC_ON;
 			} else if (in_port[i].sfe_in_path_type) {
 			} else if (in_port[i].sfe_in_path_type) {
 				ife_ctx->ctx_type = CAM_IFE_CTX_TYPE_SFE;
 				ife_ctx->ctx_type = CAM_IFE_CTX_TYPE_SFE;
 			}
 			}
@@ -4517,16 +4520,26 @@ static int cam_ife_mgr_acquire_hw(void *hw_mgr_priv, void *acquire_hw_args)
 	atomic_set(&ife_ctx->cdm_done, 1);
 	atomic_set(&ife_ctx->cdm_done, 1);
 	ife_ctx->last_cdm_done_req = 0;
 	ife_ctx->last_cdm_done_req = 0;
 
 
-	acquire_args->support_consumed_addr =
-		g_ife_hw_mgr.support_consumed_addr;
+	if (g_ife_hw_mgr.support_consumed_addr)
+		acquire_args->op_flags |=
+			CAM_IFE_CTX_CONSUME_ADDR_EN;
+
+	if ((ife_ctx->ctx_type == CAM_IFE_CTX_TYPE_SFE) &&
+		ife_ctx->is_fe_enabled) {
+		ife_ctx->ctx_config |= CAM_IFE_CTX_CFG_SFE_FE_MODE;
+		acquire_args->op_flags |=
+			CAM_IFE_CTX_APPLY_DEFAULT_CFG;
+	}
 
 
 	acquire_args->ctxt_to_hw_map = ife_ctx;
 	acquire_args->ctxt_to_hw_map = ife_ctx;
-	acquire_args->custom_enabled = false;
 	if (ife_ctx->ctx_type == CAM_IFE_CTX_TYPE_CUSTOM)
 	if (ife_ctx->ctx_type == CAM_IFE_CTX_TYPE_CUSTOM)
-		acquire_args->custom_enabled = true;
-	acquire_args->use_frame_header_ts =
-		(ife_ctx->custom_config &
-		CAM_IFE_CUSTOM_CFG_FRAME_HEADER_TS);
+		acquire_args->op_flags |= CAM_IFE_CTX_CUSTOM_EN;
+
+	if (ife_ctx->ctx_config &
+		CAM_IFE_CTX_CFG_FRAME_HEADER_TS)
+		acquire_args->op_flags |=
+			CAM_IFE_CTX_FRAME_HEADER_EN;
+
 	ife_ctx->ctx_in_use = 1;
 	ife_ctx->ctx_in_use = 1;
 	ife_ctx->num_reg_dump_buf = 0;
 	ife_ctx->num_reg_dump_buf = 0;
 	memset(&ife_ctx->scratch_config, 0,
 	memset(&ife_ctx->scratch_config, 0,
@@ -5374,7 +5387,7 @@ static int cam_ife_mgr_config_hw(void *hw_mgr_priv,
 		}
 		}
 
 
 		if (cfg->init_packet || hw_update_data->mup_en ||
 		if (cfg->init_packet || hw_update_data->mup_en ||
-			(ctx->custom_config & CAM_IFE_CUSTOM_CFG_SW_SYNC_ON)) {
+			(ctx->ctx_config & CAM_IFE_CTX_CFG_SW_SYNC_ON)) {
 			rem_jiffies = wait_for_completion_timeout(
 			rem_jiffies = wait_for_completion_timeout(
 				&ctx->config_done_complete,
 				&ctx->config_done_complete,
 				msecs_to_jiffies(60));
 				msecs_to_jiffies(60));
@@ -6272,7 +6285,7 @@ static int cam_ife_mgr_release_hw(void *hw_mgr_priv,
 	ctx->cdm_ops = NULL;
 	ctx->cdm_ops = NULL;
 	ctx->num_reg_dump_buf = 0;
 	ctx->num_reg_dump_buf = 0;
 	ctx->ctx_type = CAM_IFE_CTX_TYPE_NONE;
 	ctx->ctx_type = CAM_IFE_CTX_TYPE_NONE;
-	ctx->custom_config = 0;
+	ctx->ctx_config = 0;
 	ctx->num_reg_dump_buf = 0;
 	ctx->num_reg_dump_buf = 0;
 	ctx->is_dual = false;
 	ctx->is_dual = false;
 	ctx->dsp_enabled = false;
 	ctx->dsp_enabled = false;
@@ -8313,6 +8326,21 @@ static int cam_sfe_packet_generic_blob_handler(void *user_data,
 			CAM_ERR(CAM_ISP, "FS Update Failed rc: %d", rc);
 			CAM_ERR(CAM_ISP, "FS Update Failed rc: %d", rc);
 	}
 	}
 		break;
 		break;
+	case CAM_ISP_GENERIC_BLOB_TYPE_DYNAMIC_MODE_SWITCH: {
+		struct cam_isp_mode_switch_info    *mup_config;
+
+		if (blob_size < sizeof(struct cam_isp_mode_switch_info)) {
+			CAM_ERR(CAM_ISP, "Invalid blob size %u expected %lu",
+				blob_size,
+				sizeof(struct cam_isp_mode_switch_info));
+			return -EINVAL;
+		}
+
+		mup_config = (struct cam_isp_mode_switch_info *)blob_data;
+		ife_mgr_ctx->scratch_config.curr_num_exp =
+			mup_config->num_expoures;
+	}
+		break;
 	case CAM_ISP_GENERIC_BLOB_TYPE_HFR_CONFIG:
 	case CAM_ISP_GENERIC_BLOB_TYPE_HFR_CONFIG:
 	case CAM_ISP_GENERIC_BLOB_TYPE_CLOCK_CONFIG:
 	case CAM_ISP_GENERIC_BLOB_TYPE_CLOCK_CONFIG:
 	case CAM_ISP_GENERIC_BLOB_TYPE_BW_CONFIG:
 	case CAM_ISP_GENERIC_BLOB_TYPE_BW_CONFIG:
@@ -8350,7 +8378,7 @@ static int cam_isp_sfe_send_scratch_buf_upd(
 
 
 	memset(io_addr, 0, sizeof(io_addr));
 	memset(io_addr, 0, sizeof(io_addr));
 	update_buf.res = hw_res;
 	update_buf.res = hw_res;
-	update_buf.cmd_type = CAM_ISP_HW_CMD_GET_BUF_UPDATE;
+	update_buf.cmd_type = cmd_type;
 	update_buf.cmd.cmd_buf_addr = cpu_addr;
 	update_buf.cmd.cmd_buf_addr = cpu_addr;
 	update_buf.use_scratch_cfg = true;
 	update_buf.use_scratch_cfg = true;
 
 
@@ -8380,7 +8408,11 @@ static int cam_isp_sfe_send_scratch_buf_upd(
 	CAM_DBG(CAM_ISP, "Scratch buf configured for: 0x%x",
 	CAM_DBG(CAM_ISP, "Scratch buf configured for: 0x%x",
 		hw_res->res_id);
 		hw_res->res_id);
 
 
-	*used_bytes = update_buf.cmd.used_bytes;
+	/* Update used bytes if update is via CDM */
+	if ((cmd_type == CAM_ISP_HW_CMD_GET_BUF_UPDATE) ||
+		(cmd_type == CAM_ISP_HW_CMD_GET_BUF_UPDATE_RM))
+		*used_bytes = update_buf.cmd.used_bytes;
+
 	return rc;
 	return rc;
 }
 }
 
 
@@ -8441,7 +8473,15 @@ static int cam_isp_sfe_add_scratch_buffer_cfg(
 			}
 			}
 
 
 			res_id = hw_mgr_res->hw_res[j]->res_id;
 			res_id = hw_mgr_res->hw_res[j]->res_id;
-			cpu_addr = kmd_buf_info->cpu_addr +
+
+			/* check for num exposures */
+			if ((ctx->ctx_config &
+				CAM_IFE_CTX_CFG_DYNAMIC_SWITCH_ON) &&
+				((res_id - CAM_ISP_SFE_OUT_RES_RDI_0) >=
+				ctx->scratch_config.curr_num_exp))
+				continue;
+
+				cpu_addr = kmd_buf_info->cpu_addr +
 				kmd_buf_info->used_bytes / 4 +
 				kmd_buf_info->used_bytes / 4 +
 				io_cfg_used_bytes / 4;
 				io_cfg_used_bytes / 4;
 			buf_info = &ctx->scratch_config.buf_info[
 			buf_info = &ctx->scratch_config.buf_info[
@@ -8487,6 +8527,14 @@ static int cam_isp_sfe_add_scratch_buffer_cfg(
 			}
 			}
 
 
 			res_id = hw_mgr_res->hw_res[j]->res_id;
 			res_id = hw_mgr_res->hw_res[j]->res_id;
+
+			/* check for num exposures */
+			if ((ctx->ctx_config &
+				CAM_IFE_CTX_CFG_DYNAMIC_SWITCH_ON) &&
+				((res_id - CAM_ISP_HW_SFE_IN_RD0) >=
+				ctx->scratch_config.curr_num_exp))
+				continue;
+
 			cpu_addr = kmd_buf_info->cpu_addr +
 			cpu_addr = kmd_buf_info->cpu_addr +
 				kmd_buf_info->used_bytes  / 4 +
 				kmd_buf_info->used_bytes  / 4 +
 				io_cfg_used_bytes / 4;
 				io_cfg_used_bytes / 4;
@@ -8707,7 +8755,7 @@ static int cam_ife_mgr_prepare_hw_update(void *hw_mgr_priv,
 	if (rc)
 	if (rc)
 		return rc;
 		return rc;
 
 
-	if (ctx->custom_config & CAM_IFE_CUSTOM_CFG_FRAME_HEADER_TS) {
+	if (ctx->ctx_config & CAM_IFE_CTX_CFG_FRAME_HEADER_TS) {
 		rc = cam_ife_mgr_util_insert_frame_header(&kmd_buf,
 		rc = cam_ife_mgr_util_insert_frame_header(&kmd_buf,
 			prepare_hw_data);
 			prepare_hw_data);
 		if (rc)
 		if (rc)
@@ -8825,7 +8873,7 @@ static int cam_ife_mgr_prepare_hw_update(void *hw_mgr_priv,
 		}
 		}
 
 
 		sfe_fe_chk_cfg.sfe_fe_enabled = false;
 		sfe_fe_chk_cfg.sfe_fe_enabled = false;
-		if ((ctx->is_fe_enabled) &&
+		if ((!ctx->is_offline) && (ctx->is_fe_enabled) &&
 			(ctx->base[i].hw_type == CAM_ISP_HW_TYPE_SFE)) {
 			(ctx->base[i].hw_type == CAM_ISP_HW_TYPE_SFE)) {
 			sfe_fe_chk_cfg.sfe_fe_enabled = true;
 			sfe_fe_chk_cfg.sfe_fe_enabled = true;
 			sfe_fe_chk_cfg.sfe_rdi_cfg_mask = 0;
 			sfe_fe_chk_cfg.sfe_rdi_cfg_mask = 0;
@@ -8899,7 +8947,7 @@ static int cam_ife_mgr_prepare_hw_update(void *hw_mgr_priv,
 	}
 	}
 
 
 	/* Check if frame header was enabled for any WM */
 	/* Check if frame header was enabled for any WM */
-	if ((ctx->custom_config & CAM_IFE_CUSTOM_CFG_FRAME_HEADER_TS) &&
+	if ((ctx->ctx_config & CAM_IFE_CTX_CFG_FRAME_HEADER_TS) &&
 		(prepare->num_out_map_entries) &&
 		(prepare->num_out_map_entries) &&
 		(!prepare_hw_data->frame_header_res_id)) {
 		(!prepare_hw_data->frame_header_res_id)) {
 		CAM_ERR(CAM_ISP, "Failed to configure frame header");
 		CAM_ERR(CAM_ISP, "Failed to configure frame header");
@@ -9290,6 +9338,159 @@ outportlog:
 
 
 }
 }
 
 
+int cam_isp_config_csid_rup_aup(
+	struct cam_ife_hw_mgr_ctx *ctx)
+{
+	int rc = 0, i, j, hw_idx;
+	struct cam_isp_hw_mgr_res       *hw_mgr_res;
+	struct list_head                *res_list;
+	struct cam_isp_resource_node    *res;
+	struct cam_isp_csid_reg_update_args
+		rup_args[CAM_IFE_CSID_HW_NUM_MAX] = {0};
+
+	res_list = &ctx->res_list_ife_csid;
+	for (j = 0; j < ctx->num_base; j++) {
+		if (ctx->base[j].hw_type != CAM_ISP_HW_TYPE_CSID)
+			continue;
+
+		list_for_each_entry(hw_mgr_res, res_list, list) {
+			if (hw_mgr_res->res_type == CAM_ISP_RESOURCE_UNINT)
+				continue;
+
+			for (i = 0; i < CAM_ISP_HW_SPLIT_MAX; i++) {
+				if (!hw_mgr_res->hw_res[i])
+					continue;
+
+				res = hw_mgr_res->hw_res[i];
+				if (res->hw_intf->hw_idx != ctx->base[j].idx)
+					continue;
+
+				hw_idx = res->hw_intf->hw_idx;
+				rup_args[hw_idx].res[rup_args[hw_idx].num_res] = res;
+				rup_args[hw_idx].num_res++;
+
+				CAM_DBG(CAM_ISP,
+					"Reg update for res %d hw_id %d cdm_idx %d",
+					res->res_id, res->hw_intf->hw_idx, ctx->base[j].idx);
+			}
+		}
+	}
+
+	for (i = 0; i < CAM_IFE_CSID_HW_NUM_MAX; i++) {
+		if (!rup_args[i].num_res)
+			continue;
+
+		rup_args[i].cmd.cmd_buf_addr = NULL;
+		rup_args[i].cmd.size = 0;
+		rup_args[i].reg_write = true;
+		res = rup_args[i].res[0];
+
+		rc = res->hw_intf->hw_ops.process_cmd(
+			res->hw_intf->hw_priv,
+			CAM_ISP_HW_CMD_GET_REG_UPDATE, &rup_args[i],
+			sizeof(struct cam_isp_csid_reg_update_args));
+		if (rc)
+			return rc;
+
+		CAM_DBG(CAM_ISP,
+			"Reg update for res %d hw_id %d ",
+			res->res_id, res->hw_intf->hw_idx);
+	}
+
+	return rc;
+}
+
+/*
+ * Scratch buffer is for sHDR usescases involing SFE RDI0-2
+ * There is no possibility of dual in this case, hence
+ * using the scratch buffer provided during INIT corresponding
+ * to each left RDIs
+ */
+static int cam_ife_mgr_prog_default_settings(
+	struct cam_ife_hw_mgr_ctx *ctx)
+{
+	int i, j, res_id, rc = 0;
+	struct cam_isp_hw_mgr_res       *hw_mgr_res;
+	struct cam_sfe_scratch_buf_info *buf_info;
+	struct list_head                *res_list_in_rd = NULL;
+	struct cam_isp_hw_mgr_res       *res_list_sfe_out = NULL;
+
+	res_list_in_rd = &ctx->res_list_ife_in_rd;
+	res_list_sfe_out = ctx->res_list_sfe_out;
+
+	for (i = 0; i < CAM_SFE_FE_RDI_NUM_MAX; i++) {
+		hw_mgr_res = &res_list_sfe_out[i];
+		for (j = 0; j < CAM_ISP_HW_SPLIT_MAX; j++) {
+			/* j = 1 is not valid for this use-case */
+			if (!hw_mgr_res->hw_res[j])
+				continue;
+
+			res_id = hw_mgr_res->hw_res[j]->res_id;
+			/* check for num exposures */
+			if ((ctx->ctx_config &
+				CAM_IFE_CTX_CFG_DYNAMIC_SWITCH_ON) &&
+				((res_id - CAM_ISP_SFE_OUT_RES_RDI_0) >=
+				ctx->scratch_config.curr_num_exp))
+				continue;
+
+			buf_info = &ctx->scratch_config.buf_info[
+				res_id - CAM_ISP_SFE_OUT_RES_RDI_0];
+
+			CAM_DBG(CAM_ISP,
+				"RDI%d res_id 0x%x idx %u io_addr %pK",
+				i,
+				hw_mgr_res->hw_res[j]->res_id,
+				(res_id - CAM_ISP_SFE_OUT_RES_RDI_0),
+				buf_info->io_addr);
+
+			rc = cam_isp_sfe_send_scratch_buf_upd(0x0,
+				CAM_ISP_HW_CMD_BUF_UPDATE,
+				hw_mgr_res->hw_res[j], buf_info,
+				NULL, NULL);
+			if (rc)
+				return rc;
+		}
+	}
+
+	list_for_each_entry(hw_mgr_res, res_list_in_rd, list) {
+		for (j = 0; j < CAM_ISP_HW_SPLIT_MAX; j++) {
+			if (!hw_mgr_res->hw_res[j])
+				continue;
+
+			res_id = hw_mgr_res->hw_res[j]->res_id;
+
+			/* check for num exposures */
+			if ((ctx->ctx_config &
+				CAM_IFE_CTX_CFG_DYNAMIC_SWITCH_ON) &&
+				((res_id - CAM_ISP_HW_SFE_IN_RD0) >=
+				ctx->scratch_config.curr_num_exp))
+				continue;
+
+			buf_info = &ctx->scratch_config.buf_info
+				[res_id - CAM_ISP_HW_SFE_IN_RD0];
+			CAM_DBG(CAM_ISP,
+				"RD res_id 0x%x idx %u io_addr %pK",
+				hw_mgr_res->hw_res[j]->res_id,
+				(res_id - CAM_ISP_HW_SFE_IN_RD0),
+				buf_info->io_addr);
+			rc = cam_isp_sfe_send_scratch_buf_upd(0x0,
+				CAM_ISP_HW_CMD_BUF_UPDATE_RM,
+				hw_mgr_res->hw_res[j], buf_info,
+				NULL, NULL);
+			if (rc)
+				return rc;
+		}
+	}
+
+	/* Program rup & aup */
+	rc = cam_isp_config_csid_rup_aup(ctx);
+	if (rc)
+		CAM_ERR(CAM_ISP,
+			"RUP/AUP update failed for scratch buffers");
+
+	return rc;
+}
+
 static int cam_ife_mgr_cmd(void *hw_mgr_priv, void *cmd_args)
 static int cam_ife_mgr_cmd(void *hw_mgr_priv, void *cmd_args)
 {
 {
 	int rc = 0;
 	int rc = 0;
@@ -9359,6 +9560,9 @@ static int cam_ife_mgr_cmd(void *hw_mgr_priv, void *cmd_args)
 			isp_hw_cmd_args->u.last_cdm_done =
 			isp_hw_cmd_args->u.last_cdm_done =
 				ctx->last_cdm_done_req;
 				ctx->last_cdm_done_req;
 			break;
 			break;
+		case CAM_ISP_HW_MGR_CMD_PROG_DEFAULT_CFG:
+			rc = cam_ife_mgr_prog_default_settings(ctx);
+			break;
 		default:
 		default:
 			CAM_ERR(CAM_ISP, "Invalid HW mgr command:0x%x",
 			CAM_ERR(CAM_ISP, "Invalid HW mgr command:0x%x",
 				hw_cmd_args->cmd_type);
 				hw_cmd_args->cmd_type);
@@ -10248,8 +10452,8 @@ static int cam_ife_hw_mgr_handle_hw_sof(
 	case CAM_ISP_HW_VFE_IN_CAMIF:
 	case CAM_ISP_HW_VFE_IN_CAMIF:
 	case CAM_ISP_HW_VFE_IN_RD:
 	case CAM_ISP_HW_VFE_IN_RD:
 		/* if frame header is enabled reset qtimer ts */
 		/* if frame header is enabled reset qtimer ts */
-		if (ife_hw_mgr_ctx->custom_config &
-			CAM_IFE_CUSTOM_CFG_FRAME_HEADER_TS) {
+		if (ife_hw_mgr_ctx->ctx_config &
+			CAM_IFE_CTX_CFG_FRAME_HEADER_TS) {
 			sof_done_event_data.timestamp = 0x0;
 			sof_done_event_data.timestamp = 0x0;
 			ktime_get_boottime_ts64(&ts);
 			ktime_get_boottime_ts64(&ts);
 			sof_done_event_data.boot_time =
 			sof_done_event_data.boot_time =
@@ -10417,7 +10621,8 @@ static int cam_ife_hw_mgr_handle_hw_buf_done(
 	buf_done_event_data.last_consumed_addr[0] =
 	buf_done_event_data.last_consumed_addr[0] =
 		event_info->reg_val;
 		event_info->reg_val;
 
 
-	if ((ife_hw_mgr_ctx->ctx_type == CAM_IFE_CTX_TYPE_SFE) &&
+	if ((!ife_hw_mgr_ctx->is_offline) &&
+		(ife_hw_mgr_ctx->ctx_type == CAM_IFE_CTX_TYPE_SFE) &&
 		(ife_hw_mgr_ctx->is_fe_enabled)) {
 		(ife_hw_mgr_ctx->is_fe_enabled)) {
 		rc = cam_ife_hw_mgr_check_rdi_scratch_buf_done(
 		rc = cam_ife_hw_mgr_check_rdi_scratch_buf_done(
 			ife_hw_mgr_ctx, event_info->res_id,
 			ife_hw_mgr_ctx, event_info->res_id,

+ 9 - 5
drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.h

@@ -1,6 +1,6 @@
 /* SPDX-License-Identifier: GPL-2.0-only */
 /* SPDX-License-Identifier: GPL-2.0-only */
 /*
 /*
- * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2017-2021, The Linux Foundation. All rights reserved.
  */
  */
 
 
 #ifndef _CAM_IFE_HW_MGR_H_
 #ifndef _CAM_IFE_HW_MGR_H_
@@ -33,9 +33,11 @@ enum cam_ife_ctx_master_type {
 #define CAM_SFE_HW_OUT_RES_MAX           (CAM_ISP_SFE_OUT_RES_MAX & 0xFF)
 #define CAM_SFE_HW_OUT_RES_MAX           (CAM_ISP_SFE_OUT_RES_MAX & 0xFF)
 #define CAM_IFE_HW_RES_POOL_MAX          64
 #define CAM_IFE_HW_RES_POOL_MAX          64
 
 
-/* IFE_HW_MGR custom config */
-#define CAM_IFE_CUSTOM_CFG_FRAME_HEADER_TS   BIT(0)
-#define CAM_IFE_CUSTOM_CFG_SW_SYNC_ON        BIT(1)
+/* IFE_HW_MGR ctx config */
+#define CAM_IFE_CTX_CFG_FRAME_HEADER_TS   BIT(0)
+#define CAM_IFE_CTX_CFG_SW_SYNC_ON        BIT(1)
+#define CAM_IFE_CTX_CFG_SFE_FE_MODE       BIT(2)
+#define CAM_IFE_CTX_CFG_DYNAMIC_SWITCH_ON BIT(3)
 
 
 #define CAM_IFE_UBWC_COMP_EN                 BIT(1)
 #define CAM_IFE_UBWC_COMP_EN                 BIT(1)
 
 
@@ -89,12 +91,14 @@ struct cam_sfe_scratch_buf_info {
  *
  *
  * @config_done: To indicate if stream received it's scratch cfg
  * @config_done: To indicate if stream received it's scratch cfg
  * @num_configs: Number of buffer configs [max of 3 currently]
  * @num_configs: Number of buffer configs [max of 3 currently]
+ * @curr_num_exp: Current num of exposures
  * @buf_info: Info on each of the buffers
  * @buf_info: Info on each of the buffers
  *
  *
  */
  */
 struct cam_sfe_scratch_buf_cfg {
 struct cam_sfe_scratch_buf_cfg {
 	bool                            config_done;
 	bool                            config_done;
 	uint32_t                        num_config;
 	uint32_t                        num_config;
+	uint32_t                        curr_num_exp;
 	struct cam_sfe_scratch_buf_info buf_info[
 	struct cam_sfe_scratch_buf_info buf_info[
 		CAM_SFE_FE_RDI_NUM_MAX];
 		CAM_SFE_FE_RDI_NUM_MAX];
 };
 };
@@ -212,7 +216,7 @@ struct cam_ife_hw_mgr_ctx {
 	bool                            is_fe_enabled;
 	bool                            is_fe_enabled;
 	bool                            is_dual;
 	bool                            is_dual;
 	enum cam_ife_ctx_master_type    ctx_type;
 	enum cam_ife_ctx_master_type    ctx_type;
-	uint32_t                        custom_config;
+	uint32_t                        ctx_config;
 	struct timespec64               ts;
 	struct timespec64               ts;
 	bool                            is_tpg;
 	bool                            is_tpg;
 	bool                            is_offline;
 	bool                            is_offline;

+ 3 - 2
drivers/cam_isp/isp_hw_mgr/cam_tfe_hw_mgr.c

@@ -2037,8 +2037,9 @@ static int cam_tfe_mgr_acquire_hw(void *hw_mgr_priv, void *acquire_hw_args)
 	tfe_ctx->ctx_in_use = 1;
 	tfe_ctx->ctx_in_use = 1;
 	tfe_ctx->num_reg_dump_buf = 0;
 	tfe_ctx->num_reg_dump_buf = 0;
 
 
-	acquire_args->support_consumed_addr =
-		g_tfe_hw_mgr.support_consumed_addr;
+	if (g_tfe_hw_mgr.support_consumed_addr)
+		acquire_args->op_flags |=
+			 CAM_IFE_CTX_CONSUME_ADDR_EN;
 
 
 	cam_tfe_hw_mgr_put_ctx(&tfe_hw_mgr->used_ctx_list, &tfe_ctx);
 	cam_tfe_hw_mgr_put_ctx(&tfe_hw_mgr->used_ctx_list, &tfe_ctx);
 
 

+ 2 - 1
drivers/cam_isp/isp_hw_mgr/hw_utils/cam_isp_packet_parser.c

@@ -1,6 +1,6 @@
 // SPDX-License-Identifier: GPL-2.0-only
 // SPDX-License-Identifier: GPL-2.0-only
 /*
 /*
- * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2017-2021, The Linux Foundation. All rights reserved.
  */
  */
 
 
 #include <media/cam_defs.h>
 #include <media/cam_defs.h>
@@ -1723,6 +1723,7 @@ int cam_isp_add_csid_reg_update(
 		kmd_buf_info->used_bytes/4 +
 		kmd_buf_info->used_bytes/4 +
 		reg_update_size/4;
 		reg_update_size/4;
 	rup_args->cmd.size = kmd_buf_remain_size;
 	rup_args->cmd.size = kmd_buf_remain_size;
+	rup_args->reg_write = false;
 	res = rup_args->res[0];
 	res = rup_args->res[0];
 
 
 	rc = res->hw_intf->hw_ops.process_cmd(
 	rc = res->hw_intf->hw_ops.process_cmd(

+ 8 - 1
drivers/cam_isp/isp_hw_mgr/include/cam_isp_hw_mgr_intf.h

@@ -1,6 +1,6 @@
 /* SPDX-License-Identifier: GPL-2.0-only */
 /* SPDX-License-Identifier: GPL-2.0-only */
 /*
 /*
- * Copyright (c) 2016-2020, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2016-2021, The Linux Foundation. All rights reserved.
  */
  */
 
 
 #ifndef _CAM_ISP_HW_MGR_INTF_H_
 #ifndef _CAM_ISP_HW_MGR_INTF_H_
@@ -32,6 +32,12 @@
 /* Appliacble vote paths for dual ife, based on no. of UAPI definitions */
 /* Appliacble vote paths for dual ife, based on no. of UAPI definitions */
 #define CAM_ISP_MAX_PER_PATH_VOTES 40
 #define CAM_ISP_MAX_PER_PATH_VOTES 40
 
 
+/* Output params for acquire from hw_mgr to ctx */
+#define CAM_IFE_CTX_CUSTOM_EN          BIT(0)
+#define CAM_IFE_CTX_FRAME_HEADER_EN    BIT(1)
+#define CAM_IFE_CTX_CONSUME_ADDR_EN    BIT(2)
+#define CAM_IFE_CTX_APPLY_DEFAULT_CFG  BIT(3)
+
 /**
 /**
  *  enum cam_isp_hw_event_type - Collection of the ISP hardware events
  *  enum cam_isp_hw_event_type - Collection of the ISP hardware events
  */
  */
@@ -240,6 +246,7 @@ enum cam_isp_hw_mgr_command {
 	CAM_ISP_HW_MGR_CMD_CTX_TYPE,
 	CAM_ISP_HW_MGR_CMD_CTX_TYPE,
 	CAM_ISP_HW_MGR_GET_PACKET_OPCODE,
 	CAM_ISP_HW_MGR_GET_PACKET_OPCODE,
 	CAM_ISP_HW_MGR_GET_LAST_CDM_DONE,
 	CAM_ISP_HW_MGR_GET_LAST_CDM_DONE,
+	CAM_ISP_HW_MGR_CMD_PROG_DEFAULT_CFG,
 	CAM_ISP_HW_MGR_CMD_MAX,
 	CAM_ISP_HW_MGR_CMD_MAX,
 };
 };
 
 

+ 13 - 6
drivers/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_hw_ver2.c

@@ -1,6 +1,6 @@
 // SPDX-License-Identifier: GPL-2.0-only
 // SPDX-License-Identifier: GPL-2.0-only
 /*
 /*
- * Copyright (c) 2020, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2020-2021, The Linux Foundation. All rights reserved.
  */
  */
 
 
 #include <linux/iopoll.h>
 #include <linux/iopoll.h>
@@ -3334,6 +3334,7 @@ static int cam_ife_csid_ver2_reg_update(
 	struct cam_isp_csid_reg_update_args         *rup_args = cmd_args;
 	struct cam_isp_csid_reg_update_args         *rup_args = cmd_args;
 	struct cam_cdm_utils_ops                    *cdm_util_ops;
 	struct cam_cdm_utils_ops                    *cdm_util_ops;
 	struct cam_ife_csid_ver2_reg_info           *csid_reg;
 	struct cam_ife_csid_ver2_reg_info           *csid_reg;
+	struct cam_hw_soc_info                      *soc_info;
 	uint32_t                                     size, i;
 	uint32_t                                     size, i;
 	uint32_t                                     reg_val_pair[2];
 	uint32_t                                     reg_val_pair[2];
 	uint32_t                                     rup_aup_mask = 0;
 	uint32_t                                     rup_aup_mask = 0;
@@ -3366,7 +3367,7 @@ static int cam_ife_csid_ver2_reg_update(
 
 
 	size = cdm_util_ops->cdm_required_size_reg_random(1);
 	size = cdm_util_ops->cdm_required_size_reg_random(1);
 	/* since cdm returns dwords, we need to convert it into bytes */
 	/* since cdm returns dwords, we need to convert it into bytes */
-	if ((size * 4) > rup_args->cmd.size) {
+	if ((!rup_args->reg_write) && ((size * 4) > rup_args->cmd.size)) {
 		CAM_ERR(CAM_ISP, "buf size:%d is not sufficient, expected: %d",
 		CAM_ERR(CAM_ISP, "buf size:%d is not sufficient, expected: %d",
 			rup_args->cmd.size, (size*4));
 			rup_args->cmd.size, (size*4));
 		return -EINVAL;
 		return -EINVAL;
@@ -3420,10 +3421,16 @@ static int cam_ife_csid_ver2_reg_update(
 		csid_hw->hw_intf->hw_idx,
 		csid_hw->hw_intf->hw_idx,
 		reg_val_pair[1], reg_val_pair[0]);
 		reg_val_pair[1], reg_val_pair[0]);
 
 
-	cdm_util_ops->cdm_write_regrandom(rup_args->cmd.cmd_buf_addr,
-		1, reg_val_pair);
-
-	rup_args->cmd.used_bytes = size * 4;
+	if (rup_args->reg_write) {
+		soc_info = &csid_hw->hw_info->soc_info;
+		cam_io_w_mb(reg_val_pair[1],
+			soc_info->reg_map[CAM_IFE_CSID_CLC_MEM_BASE_ID].mem_base +
+			reg_val_pair[0]);
+	} else {
+		cdm_util_ops->cdm_write_regrandom(rup_args->cmd.cmd_buf_addr,
+			1, reg_val_pair);
+		rup_args->cmd.used_bytes = size * 4;
+	}
 
 
 	return rc;
 	return rc;
 err:
 err:

+ 3 - 1
drivers/cam_isp/isp_hw_mgr/isp_hw/include/cam_ife_csid_hw_intf.h

@@ -1,6 +1,6 @@
 /* SPDX-License-Identifier: GPL-2.0-only */
 /* SPDX-License-Identifier: GPL-2.0-only */
 /*
 /*
- * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2017-2021, The Linux Foundation. All rights reserved.
  */
  */
 
 
 #ifndef _CAM_CSID_HW_INTF_H_
 #ifndef _CAM_CSID_HW_INTF_H_
@@ -353,11 +353,13 @@ struct cam_ife_csid_dual_sync_args {
  * @cmd:           cmd buf update args
  * @cmd:           cmd buf update args
  * @node_res:      Node res pointer
  * @node_res:      Node res pointer
  * @num_res:       Num of resources
  * @num_res:       Num of resources
+ * @reg_write:     if set use AHB to config rup/aup
  */
  */
 struct cam_isp_csid_reg_update_args {
 struct cam_isp_csid_reg_update_args {
 	struct cam_isp_hw_cmd_buf_update  cmd;
 	struct cam_isp_hw_cmd_buf_update  cmd;
 	struct cam_isp_resource_node     *res[CAM_IFE_PIX_PATH_RES_MAX];
 	struct cam_isp_resource_node     *res[CAM_IFE_PIX_PATH_RES_MAX];
 	uint32_t                          num_res;
 	uint32_t                          num_res;
+	bool                              reg_write;
 };
 };
 
 
 /*
 /*

+ 3 - 1
drivers/cam_isp/isp_hw_mgr/isp_hw/include/cam_isp_hw.h

@@ -1,6 +1,6 @@
 /* SPDX-License-Identifier: GPL-2.0-only */
 /* SPDX-License-Identifier: GPL-2.0-only */
 /*
 /*
- * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2017-2021, The Linux Foundation. All rights reserved.
  */
  */
 
 
 #ifndef _CAM_ISP_HW_H_
 #ifndef _CAM_ISP_HW_H_
@@ -145,6 +145,8 @@ enum cam_isp_hw_cmd_type {
 	CAM_IFE_CSID_PROGRAM_OFFLINE_CMD,
 	CAM_IFE_CSID_PROGRAM_OFFLINE_CMD,
 	CAM_IFE_CSID_SET_DUAL_SYNC_CONFIG,
 	CAM_IFE_CSID_SET_DUAL_SYNC_CONFIG,
 	CAM_ISP_HW_CMD_CSID_MUP_UPDATE,
 	CAM_ISP_HW_CMD_CSID_MUP_UPDATE,
+	CAM_ISP_HW_CMD_BUF_UPDATE,
+	CAM_ISP_HW_CMD_BUF_UPDATE_RM,
 	CAM_ISP_HW_CMD_MAX,
 	CAM_ISP_HW_CMD_MAX,
 };
 };
 
 

+ 3 - 1
drivers/cam_isp/isp_hw_mgr/isp_hw/sfe_hw/cam_sfe_core.c

@@ -1,6 +1,6 @@
 // SPDX-License-Identifier: GPL-2.0-only
 // SPDX-License-Identifier: GPL-2.0-only
 /*
 /*
- * Copyright (c) 2020, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2020-2021, The Linux Foundation. All rights reserved.
  */
  */
 
 
 #include <linux/slab.h>
 #include <linux/slab.h>
@@ -327,6 +327,7 @@ int cam_sfe_process_cmd(void *hw_priv, uint32_t cmd_type,
 			cmd_args, arg_size);
 			cmd_args, arg_size);
 		break;
 		break;
 	case CAM_ISP_HW_CMD_GET_BUF_UPDATE:
 	case CAM_ISP_HW_CMD_GET_BUF_UPDATE:
+	case CAM_ISP_HW_CMD_BUF_UPDATE:
 	case CAM_ISP_HW_CMD_GET_HFR_UPDATE:
 	case CAM_ISP_HW_CMD_GET_HFR_UPDATE:
 	case CAM_ISP_HW_CMD_STRIPE_UPDATE:
 	case CAM_ISP_HW_CMD_STRIPE_UPDATE:
 	case CAM_ISP_HW_CMD_WM_CONFIG_UPDATE:
 	case CAM_ISP_HW_CMD_WM_CONFIG_UPDATE:
@@ -337,6 +338,7 @@ int cam_sfe_process_cmd(void *hw_priv, uint32_t cmd_type,
 		break;
 		break;
 	case CAM_ISP_HW_CMD_GET_HFR_UPDATE_RM:
 	case CAM_ISP_HW_CMD_GET_HFR_UPDATE_RM:
 	case CAM_ISP_HW_CMD_GET_BUF_UPDATE_RM:
 	case CAM_ISP_HW_CMD_GET_BUF_UPDATE_RM:
+	case CAM_ISP_HW_CMD_BUF_UPDATE_RM:
 	case CAM_ISP_HW_CMD_FE_UPDATE_BUS_RD:
 	case CAM_ISP_HW_CMD_FE_UPDATE_BUS_RD:
 		rc = core_info->sfe_bus_rd->hw_ops.process_cmd(
 		rc = core_info->sfe_bus_rd->hw_ops.process_cmd(
 			core_info->sfe_bus_rd->bus_priv, cmd_type,
 			core_info->sfe_bus_rd->bus_priv, cmd_type,

+ 86 - 1
drivers/cam_isp/isp_hw_mgr/isp_hw/sfe_hw/sfe_bus/cam_sfe_bus_rd.c

@@ -1,6 +1,6 @@
 // SPDX-License-Identifier: GPL-2.0-only
 // SPDX-License-Identifier: GPL-2.0-only
 /*
 /*
- * Copyright (c) 2020, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2020-2021, The Linux Foundation. All rights reserved.
  */
  */
 
 
 #include <linux/ratelimit.h>
 #include <linux/ratelimit.h>
@@ -1118,6 +1118,88 @@ static int cam_sfe_bus_deinit_sfe_bus_rd_resource(
 	return 0;
 	return 0;
 }
 }
 
 
+/*
+ * API similar to cam_sfe_bus_rd_update_rm() with the
+ * only change being config is done via AHB instead of CDM
+ */
+static int cam_sfe_bus_rd_config_rm(void *priv, void *cmd_args,
+	uint32_t arg_size)
+{
+	struct cam_sfe_bus_rd_priv             *bus_priv;
+	struct cam_isp_hw_get_cmd_update       *update_buf;
+	struct cam_sfe_bus_rd_data             *sfe_bus_rd_data = NULL;
+	struct cam_sfe_bus_rd_rm_resource_data *rm_data = NULL;
+	uint32_t width = 0, height = 0, stride = 0;
+	uint32_t  i;
+
+	bus_priv = (struct cam_sfe_bus_rd_priv  *) priv;
+	update_buf =  (struct cam_isp_hw_get_cmd_update *) cmd_args;
+
+	sfe_bus_rd_data = (struct cam_sfe_bus_rd_data *)
+		update_buf->res->res_priv;
+
+	if (!sfe_bus_rd_data || !sfe_bus_rd_data->cdm_util_ops) {
+		CAM_ERR(CAM_SFE, "Failed! Invalid data");
+		return -EINVAL;
+	}
+
+	CAM_DBG(CAM_SFE, "num of RM: %d scratch_buf_cfg: %s",
+		sfe_bus_rd_data->num_rm,
+		update_buf->use_scratch_cfg ? "true" : "false");
+	if (update_buf->rm_update->num_buf != sfe_bus_rd_data->num_rm) {
+		CAM_ERR(CAM_SFE,
+			"Failed! Invalid number buffers:%d required:%d",
+			update_buf->rm_update->num_buf,
+			sfe_bus_rd_data->num_rm);
+		return -EINVAL;
+	}
+
+	for (i = 0; i < sfe_bus_rd_data->num_rm; i++) {
+		rm_data = sfe_bus_rd_data->rm_res[i]->res_priv;
+
+		stride = update_buf->rm_update->stride;
+		width = update_buf->rm_update->width;
+		height = update_buf->rm_update->height;
+
+		/* update size register */
+		cam_sfe_bus_rd_pxls_to_bytes(width,
+			rm_data->unpacker_cfg, &rm_data->width);
+		rm_data->height = height;
+
+		cam_io_w_mb(rm_data->width,
+			rm_data->common_data->mem_base +
+			rm_data->hw_regs->buf_width);
+		cam_io_w_mb(rm_data->height,
+			rm_data->common_data->mem_base +
+			rm_data->hw_regs->buf_height);
+
+		CAM_DBG(CAM_SFE, "SFE:%d RM:%d width:0x%X height:0x%X",
+			rm_data->common_data->core_index,
+			rm_data->index, rm_data->width,
+			rm_data->height);
+
+		rm_data->stride = stride;
+		cam_io_w_mb(stride,
+			rm_data->common_data->mem_base +
+			rm_data->hw_regs->stride);
+		CAM_DBG(CAM_SFE, "SFE:%d RM:%d image_stride:0x%X",
+			rm_data->common_data->core_index,
+			rm_data->index, stride);
+
+		cam_io_w_mb(update_buf->rm_update->image_buf[i],
+			rm_data->common_data->mem_base +
+			rm_data->hw_regs->image_addr);
+		CAM_DBG(CAM_SFE, "SFE:%d RM:%d image_address:0x%X",
+			rm_data->common_data->core_index,
+			rm_data->index,
+			update_buf->rm_update->image_buf[i]);
+		rm_data->img_addr =
+			update_buf->rm_update->image_buf[i];
+	}
+
+	return 0;
+}
+
 static int cam_sfe_bus_rd_update_rm(void *priv, void *cmd_args,
 static int cam_sfe_bus_rd_update_rm(void *priv, void *cmd_args,
 	uint32_t arg_size)
 	uint32_t arg_size)
 {
 {
@@ -1320,6 +1402,9 @@ static int cam_sfe_bus_rd_process_cmd(
 	case CAM_ISP_HW_CMD_GET_BUF_UPDATE_RM:
 	case CAM_ISP_HW_CMD_GET_BUF_UPDATE_RM:
 		rc = cam_sfe_bus_rd_update_rm(priv, cmd_args, arg_size);
 		rc = cam_sfe_bus_rd_update_rm(priv, cmd_args, arg_size);
 		break;
 		break;
+	case CAM_ISP_HW_CMD_BUF_UPDATE_RM:
+		rc = cam_sfe_bus_rd_config_rm(priv, cmd_args, arg_size);
+		break;
 	case CAM_ISP_HW_CMD_GET_SECURE_MODE:
 	case CAM_ISP_HW_CMD_GET_SECURE_MODE:
 		rc = cam_sfe_bus_rd_get_secure_mode(priv, cmd_args, arg_size);
 		rc = cam_sfe_bus_rd_get_secure_mode(priv, cmd_args, arg_size);
 		break;
 		break;

+ 119 - 1
drivers/cam_isp/isp_hw_mgr/isp_hw/sfe_hw/sfe_bus/cam_sfe_bus_wr.c

@@ -1,6 +1,6 @@
 // SPDX-License-Identifier: GPL-2.0-only
 // SPDX-License-Identifier: GPL-2.0-only
 /*
 /*
- * Copyright (c) 2020, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2020-2021, The Linux Foundation. All rights reserved.
  */
  */
 
 
 
 
@@ -2074,6 +2074,121 @@ static int cam_sfe_bus_wr_update_wm(void *priv, void *cmd_args,
 	return 0;
 	return 0;
 }
 }
 
 
+/*
+ * API similar to cam_sfe_bus_wr_update_wm() with the
+ * only change being config is done via AHB instead of CDM
+ */
+static int cam_sfe_bus_wr_config_wm(void *priv, void *cmd_args,
+	uint32_t arg_size)
+{
+	struct cam_sfe_bus_wr_priv             *bus_priv;
+	struct cam_isp_hw_get_cmd_update       *update_buf;
+	struct cam_sfe_bus_wr_out_data         *sfe_out_data = NULL;
+	struct cam_sfe_bus_wr_wm_resource_data *wm_data = NULL;
+	uint32_t  i, k;
+	uint32_t  frame_inc = 0, val;
+	uint32_t loop_size = 0, stride = 0, slice_h = 0;
+
+	bus_priv = (struct cam_sfe_bus_wr_priv  *) priv;
+	update_buf =  (struct cam_isp_hw_get_cmd_update *) cmd_args;
+
+	sfe_out_data = (struct cam_sfe_bus_wr_out_data *)
+		update_buf->res->res_priv;
+
+	if (!sfe_out_data || !sfe_out_data->cdm_util_ops) {
+		CAM_ERR(CAM_SFE, "Failed! Invalid data");
+		return -EINVAL;
+	}
+
+	if (update_buf->wm_update->num_buf != sfe_out_data->num_wm) {
+		CAM_ERR(CAM_SFE,
+			"Failed! Invalid number buffers:%d required:%d",
+			update_buf->wm_update->num_buf, sfe_out_data->num_wm);
+		return -EINVAL;
+	}
+
+	for (i = 0; i < sfe_out_data->num_wm; i++) {
+		wm_data = (struct cam_sfe_bus_wr_wm_resource_data *)
+			sfe_out_data->wm_res[i].res_priv;
+
+		val = (wm_data->height << 16) | wm_data->width;
+		cam_io_w_mb(val,
+			wm_data->common_data->mem_base +
+			wm_data->hw_regs->image_cfg_0);
+		CAM_DBG(CAM_SFE, "WM:%d image height and width 0x%X",
+			wm_data->index, val);
+
+		/* For initial configuration program all bus registers */
+		stride = update_buf->wm_update->stride;
+		slice_h = update_buf->wm_update->slice_height;
+
+		val = stride;
+		CAM_DBG(CAM_SFE, "before stride %d", val);
+		val = ALIGNUP(val, 16);
+		if (val != stride &&
+			val != wm_data->stride)
+			CAM_WARN(CAM_SFE, "Warning stride %u expected %u",
+				stride, val);
+
+		if (wm_data->stride != val || !wm_data->init_cfg_done) {
+			cam_io_w_mb(stride,
+				wm_data->common_data->mem_base +
+				wm_data->hw_regs->image_cfg_2);
+			wm_data->stride = val;
+			CAM_DBG(CAM_SFE, "WM:%d image stride 0x%X",
+				wm_data->index, val);
+		}
+
+		frame_inc = stride * slice_h;
+
+		if (!(wm_data->en_cfg & (0x3 << 16))) {
+			cam_io_w_mb(wm_data->h_init,
+				wm_data->common_data->mem_base +
+				wm_data->hw_regs->image_cfg_1);
+			CAM_DBG(CAM_SFE, "WM:%d h_init 0x%X",
+				wm_data->index, wm_data->h_init);
+		}
+
+		if (wm_data->index > 7)
+			loop_size = wm_data->irq_subsample_period + 1;
+		else
+			loop_size = 1;
+
+		/* WM Image address */
+		for (k = 0; k < loop_size; k++) {
+			if (wm_data->en_cfg & (0x3 << 16))
+				cam_io_w_mb((update_buf->wm_update->image_buf[i] +
+					wm_data->offset + k * frame_inc),
+					wm_data->common_data->mem_base +
+					wm_data->hw_regs->image_addr);
+			else
+				cam_io_w_mb((update_buf->wm_update->image_buf[i] +
+					k * frame_inc),
+					wm_data->common_data->mem_base +
+					wm_data->hw_regs->image_addr);
+		}
+
+		cam_io_w_mb(frame_inc,
+				wm_data->common_data->mem_base +
+				wm_data->hw_regs->frame_incr);
+		CAM_DBG(CAM_SFE, "WM:%d frame_inc %d",
+			wm_data->index, frame_inc);
+
+		/* enable the WM */
+		cam_io_w_mb(wm_data->en_cfg,
+			wm_data->common_data->mem_base +
+			wm_data->hw_regs->cfg);
+		CAM_DBG(CAM_SFE, "WM:%d en_cfg 0x%X",
+			wm_data->index, wm_data->en_cfg);
+
+		/* set initial configuration done */
+		if (!wm_data->init_cfg_done)
+			wm_data->init_cfg_done = true;
+	}
+
+	return 0;
+}
+
 static int cam_sfe_bus_wr_update_hfr(void *priv, void *cmd_args,
 static int cam_sfe_bus_wr_update_hfr(void *priv, void *cmd_args,
 	uint32_t arg_size)
 	uint32_t arg_size)
 {
 {
@@ -2330,6 +2445,9 @@ static int cam_sfe_bus_wr_process_cmd(
 	case CAM_ISP_HW_CMD_GET_BUF_UPDATE:
 	case CAM_ISP_HW_CMD_GET_BUF_UPDATE:
 		rc = cam_sfe_bus_wr_update_wm(priv, cmd_args, arg_size);
 		rc = cam_sfe_bus_wr_update_wm(priv, cmd_args, arg_size);
 		break;
 		break;
+	case CAM_ISP_HW_CMD_BUF_UPDATE:
+		rc = cam_sfe_bus_wr_config_wm(priv, cmd_args, arg_size);
+		break;
 	case CAM_ISP_HW_CMD_GET_HFR_UPDATE:
 	case CAM_ISP_HW_CMD_GET_HFR_UPDATE:
 		rc = cam_sfe_bus_wr_update_hfr(priv, cmd_args, arg_size);
 		rc = cam_sfe_bus_wr_update_hfr(priv, cmd_args, arg_size);
 		break;
 		break;