Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit aaff368d authored by Junzhe Zou's avatar Junzhe Zou
Browse files

msm: camera: isp: add acquire hw handler



This change splits the acquire device function into acquire device and
acquire HW function. Acquire device will only return device handle.
Acquire HW will acquire the HW required for the usecase. There is also
a check to ensure backward compatibility.

Change-Id: I436cd91e099d64abe404661b2bb7dfc09161abb1
Signed-off-by: default avatarJunzhe Zou <jnzhezou@codeaurora.org>
Signed-off-by: default avatarHarsh Shah <harshs@codeaurora.org>
parent 49cbe4f3
Loading
Loading
Loading
Loading
+59 −0
Original line number Diff line number Diff line
@@ -287,6 +287,36 @@ int cam_context_handle_acquire_dev(struct cam_context *ctx,
	return rc;
}

int cam_context_handle_acquire_hw(struct cam_context *ctx,
	void *args)
{
	int rc;

	if (!ctx->state_machine) {
		CAM_ERR(CAM_CORE, "Context is not ready");
		return -EINVAL;
	}

	if (!args) {
		CAM_ERR(CAM_CORE, "Invalid acquire device hw command payload");
		return -EINVAL;
	}

	mutex_lock(&ctx->ctx_mutex);
	if (ctx->state_machine[ctx->state].ioctl_ops.acquire_hw) {
		rc = ctx->state_machine[ctx->state].ioctl_ops.acquire_hw(
			ctx, args);
	} else {
		CAM_ERR(CAM_CORE, "No acquire hw for dev %s, state %d",
			ctx->dev_name, ctx->state);
		rc = -EPROTO;
	}

	mutex_unlock(&ctx->ctx_mutex);

	return rc;
}

int cam_context_handle_release_dev(struct cam_context *ctx,
	struct cam_release_dev_cmd *cmd)
{
@@ -316,6 +346,35 @@ int cam_context_handle_release_dev(struct cam_context *ctx,
	return rc;
}

int cam_context_handle_release_hw(struct cam_context *ctx,
	void *args)
{
	int rc;

	if (!ctx->state_machine) {
		CAM_ERR(CAM_CORE, "Context is not ready");
		return -EINVAL;
	}

	if (!args) {
		CAM_ERR(CAM_CORE, "Invalid release HW command payload");
		return -EINVAL;
	}

	mutex_lock(&ctx->ctx_mutex);
	if (ctx->state_machine[ctx->state].ioctl_ops.release_hw) {
		rc = ctx->state_machine[ctx->state].ioctl_ops.release_hw(
			ctx, args);
	} else {
		CAM_ERR(CAM_CORE, "No release hw for dev %s, state %d",
			ctx->dev_name, ctx->state);
		rc = -EPROTO;
	}
	mutex_unlock(&ctx->ctx_mutex);

	return rc;
}

int cam_context_handle_flush_dev(struct cam_context *ctx,
	struct cam_flush_dev_cmd *cmd)
{
+28 −0
Original line number Diff line number Diff line
@@ -87,6 +87,8 @@ struct cam_ctx_request {
 * @start_dev:             Function pointer for start device
 * @stop_dev:              Function pointer for stop device
 * @flush_dev:             Function pointer for flush device
 * @acquire_hw:            Function pointer for acquire hw
 * @release_hw:            Function pointer for release hw
 *
 */
struct cam_ctx_ioctl_ops {
@@ -102,6 +104,8 @@ struct cam_ctx_ioctl_ops {
			struct cam_start_stop_dev_cmd *cmd);
	int (*flush_dev)(struct cam_context *ctx,
			struct cam_flush_dev_cmd *cmd);
	int (*acquire_hw)(struct cam_context *ctx, void *args);
	int (*release_hw)(struct cam_context *ctx, void *args);
};

/**
@@ -320,6 +324,18 @@ int cam_context_dump_pf_info(struct cam_context *ctx, unsigned long iova,
int cam_context_handle_acquire_dev(struct cam_context *ctx,
		struct cam_acquire_dev_cmd *cmd);

/**
 * cam_context_handle_acquire_hw()
 *
 * @brief:        Handle acquire HW command
 *
 * @ctx:          Object pointer for cam_context
 * @cmd:          Acquire HW command payload
 *
 */
int cam_context_handle_acquire_hw(struct cam_context *ctx,
		void *cmd);

/**
 * cam_context_handle_release_dev()
 *
@@ -332,6 +348,18 @@ int cam_context_handle_acquire_dev(struct cam_context *ctx,
int cam_context_handle_release_dev(struct cam_context *ctx,
		struct cam_release_dev_cmd *cmd);

/**
 * cam_context_handle_release_hw()
 *
 * @brief:        Handle release HW command
 *
 * @ctx:          Object pointer for cam_context
 * @cmd:          Release HW command payload
 *
 */
int cam_context_handle_release_hw(struct cam_context *ctx,
		void *cmd);

/**
 * cam_context_handle_config_dev()
 *
+1 −0
Original line number Diff line number Diff line
@@ -93,6 +93,7 @@ struct cam_hw_acquire_args {
	void                        *context_data;
	cam_hw_event_cb_func         event_cb;
	uint32_t                     num_acq;
	uint32_t                     acquire_info_size;
	uint64_t                     acquire_info;
	void                        *ctxt_to_hw_map;
};
+170 −0
Original line number Diff line number Diff line
@@ -128,6 +128,45 @@ static int __cam_node_handle_acquire_dev(struct cam_node *node,
	return rc;
}

static int __cam_node_handle_acquire_hw_v1(struct cam_node *node,
	struct cam_acquire_hw_cmd_v1 *acquire)
{
	int rc = 0;
	struct cam_context *ctx = NULL;

	if (!acquire)
		return -EINVAL;

	if (acquire->dev_handle <= 0) {
		CAM_ERR(CAM_CORE, "Invalid device handle for context");
		return -EINVAL;
	}

	if (acquire->session_handle <= 0) {
		CAM_ERR(CAM_CORE, "Invalid session handle for context");
		return -EINVAL;
	}

	ctx = (struct cam_context *)cam_get_device_priv(acquire->dev_handle);
	if (!ctx) {
		CAM_ERR(CAM_CORE, "Can not get context for handle %d",
			acquire->dev_handle);
		return -EINVAL;
	}

	rc = cam_context_handle_acquire_hw(ctx, acquire);
	if (rc) {
		CAM_ERR(CAM_CORE, "Acquire device failed for node %s",
			node->name);
		return rc;
	}

	CAM_DBG(CAM_CORE, "[%s] Acquire ctx_id %d",
		node->name, ctx->ctx_id);

	return 0;
}

static int __cam_node_handle_start_dev(struct cam_node *node,
	struct cam_start_stop_dev_cmd *start)
{
@@ -313,6 +352,43 @@ static int __cam_node_handle_release_dev(struct cam_node *node,
	return rc;
}

static int __cam_node_handle_release_hw_v1(struct cam_node *node,
	struct cam_release_hw_cmd_v1 *release)
{
	int rc = 0;
	struct cam_context *ctx = NULL;

	if (!release)
		return -EINVAL;

	if (release->dev_handle <= 0) {
		CAM_ERR(CAM_CORE, "Invalid device handle for context");
		return -EINVAL;
	}

	if (release->session_handle <= 0) {
		CAM_ERR(CAM_CORE, "Invalid session handle for context");
		return -EINVAL;
	}

	ctx = (struct cam_context *)cam_get_device_priv(release->dev_handle);
	if (!ctx) {
		CAM_ERR(CAM_CORE, "Can not get context for handle %d node %s",
			release->dev_handle, node->name);
		return -EINVAL;
	}

	rc = cam_context_handle_release_hw(ctx, release);
	if (rc)
		CAM_ERR(CAM_CORE, "context release failed node %s", node->name);

	CAM_DBG(CAM_CORE, "[%s] Release ctx_id=%d, refcount=%d",
		node->name, ctx->ctx_id,
		atomic_read(&(ctx->refcount.refcount.refs)));

	return rc;
}

static int __cam_node_crm_get_dev_info(struct cam_req_mgr_device_info *info)
{
	struct cam_context *ctx = NULL;
@@ -542,6 +618,56 @@ int cam_node_handle_ioctl(struct cam_node *node, struct cam_control *cmd)
			rc = -EFAULT;
		break;
	}
	case CAM_ACQUIRE_HW: {
		uint32_t api_version;
		void *acquire_ptr = NULL;
		size_t acquire_size;

		if (copy_from_user(&api_version, (void __user *)cmd->handle,
			sizeof(api_version))) {
			rc = -EFAULT;
			break;
		}

		if (api_version == 1) {
			acquire_size = sizeof(struct cam_acquire_hw_cmd_v1);
		} else {
			CAM_ERR(CAM_CORE, "Unsupported api version %d",
				api_version);
			rc = -EINVAL;
			break;
		}

		acquire_ptr = kzalloc(acquire_size, GFP_KERNEL);
		if (!acquire_ptr) {
			CAM_ERR(CAM_CORE, "No memory for acquire HW");
			rc = -ENOMEM;
			break;
		}

		if (copy_from_user(acquire_ptr, (void __user *)cmd->handle,
			acquire_size)) {
			rc = -EFAULT;
			goto acquire_kfree;
		}

		if (api_version == 1) {
			rc = __cam_node_handle_acquire_hw_v1(node, acquire_ptr);
			if (rc) {
				CAM_ERR(CAM_CORE,
					"acquire device failed(rc = %d)", rc);
				goto acquire_kfree;
			}
		}

		if (copy_to_user((void __user *)cmd->handle, acquire_ptr,
			acquire_size))
			rc = -EFAULT;

acquire_kfree:
		kfree(acquire_ptr);
		break;
	}
	case CAM_START_DEV: {
		struct cam_start_stop_dev_cmd start;

@@ -598,6 +724,50 @@ int cam_node_handle_ioctl(struct cam_node *node, struct cam_control *cmd)
		}
		break;
	}
	case CAM_RELEASE_HW: {
		uint32_t api_version;
		size_t release_size;
		void *release_ptr = NULL;

		if (copy_from_user(&api_version, (void __user *)cmd->handle,
			sizeof(api_version))) {
			rc = -EFAULT;
			break;
		}

		if (api_version == 1) {
			release_size = sizeof(struct cam_release_hw_cmd_v1);
		} else {
			CAM_ERR(CAM_CORE, "Unsupported api version %d",
				api_version);
			rc = -EINVAL;
			break;
		}

		release_ptr = kzalloc(release_size, GFP_KERNEL);
		if (!release_ptr) {
			CAM_ERR(CAM_CORE, "No memory for release HW");
			rc = -ENOMEM;
			break;
		}

		if (copy_from_user(release_ptr, (void __user *)cmd->handle,
			release_size)) {
			rc = -EFAULT;
			goto release_kfree;
		}

		if (api_version == 1) {
			rc = __cam_node_handle_release_hw_v1(node, release_ptr);
			if (rc)
				CAM_ERR(CAM_CORE,
					"release device failed(rc = %d)", rc);
		}

release_kfree:
		kfree(release_ptr);
		break;
	}
	case CAM_FLUSH_REQ: {
		struct cam_flush_dev_cmd flush;

+247 −8
Original line number Diff line number Diff line
@@ -1967,6 +1967,11 @@ static int __cam_isp_ctx_release_dev_in_top_state(struct cam_context *ctx,
		(struct cam_isp_context *) ctx->ctx_priv;
	struct cam_req_mgr_flush_request flush_req;

	if (cmd && ctx_isp->hw_ctx && ctx_isp->split_acquire) {
		CAM_ERR(CAM_ISP, "ctx expects release HW before release dev");
		return rc;
	}

	if (ctx_isp->hw_ctx) {
		rel_arg.ctxt_to_hw_map = ctx_isp->hw_ctx;
		ctx->hw_mgr_intf->hw_release(ctx->hw_mgr_intf->hw_mgr_priv,
@@ -1981,6 +1986,8 @@ static int __cam_isp_ctx_release_dev_in_top_state(struct cam_context *ctx,
	ctx_isp->frame_id = 0;
	ctx_isp->active_req_cnt = 0;
	ctx_isp->reported_req_id = 0;
	ctx_isp->hw_acquired = false;
	ctx_isp->init_received = false;

	/*
	 * Ideally, we should never have any active request here.
@@ -2006,6 +2013,54 @@ static int __cam_isp_ctx_release_dev_in_top_state(struct cam_context *ctx,
	return rc;
}

static int __cam_isp_ctx_release_hw_in_top_state(struct cam_context *ctx,
	void *cmd)
{
	int rc = 0;
	struct cam_hw_release_args       rel_arg;
	struct cam_isp_context *ctx_isp =
		(struct cam_isp_context *) ctx->ctx_priv;
	struct cam_req_mgr_flush_request flush_req;

	if (ctx_isp->hw_ctx) {
		rel_arg.ctxt_to_hw_map = ctx_isp->hw_ctx;
		ctx->hw_mgr_intf->hw_release(ctx->hw_mgr_intf->hw_mgr_priv,
			&rel_arg);
		ctx_isp->hw_ctx = NULL;
	} else {
		CAM_ERR(CAM_ISP, "No hw resources acquired for this ctx");
	}

	ctx_isp->frame_id = 0;
	ctx_isp->active_req_cnt = 0;
	ctx_isp->reported_req_id = 0;
	ctx_isp->hw_acquired = false;
	ctx_isp->init_received = false;

	/*
	 * Ideally, we should never have any active request here.
	 * But we still add some sanity check code here to help the debug
	 */
	if (!list_empty(&ctx->active_req_list))
		CAM_WARN(CAM_ISP, "Active list is not empty");

	/* Flush all the pending request list  */
	flush_req.type = CAM_REQ_MGR_FLUSH_TYPE_ALL;
	flush_req.link_hdl = ctx->link_hdl;
	flush_req.dev_hdl = ctx->dev_hdl;

	CAM_DBG(CAM_ISP, "try to flush pending list");
	spin_lock_bh(&ctx->lock);
	rc = __cam_isp_ctx_flush_req(ctx, &ctx->pending_req_list, &flush_req);
	spin_unlock_bh(&ctx->lock);
	ctx->state = CAM_CTX_ACQUIRED;

	trace_cam_context_state("ISP", ctx);
	CAM_DBG(CAM_ISP, "Release device success[%u] next state %d",
		ctx->ctx_id, ctx->state);
	return rc;
}

static int __cam_isp_ctx_config_dev_in_top_state(
	struct cam_context *ctx, struct cam_config_dev_cmd *cmd)
{
@@ -2112,6 +2167,7 @@ static int __cam_isp_ctx_config_dev_in_top_state(
			rc = __cam_isp_ctx_enqueue_init_request(ctx, req);
			if (rc)
				CAM_ERR(CAM_ISP, "Enqueue INIT pkt failed");
			ctx_isp->init_received = true;
		} else {
			rc = -EINVAL;
			CAM_ERR(CAM_ISP, "Recevied INIT pkt in wrong state");
@@ -2183,6 +2239,12 @@ static int __cam_isp_ctx_acquire_dev_in_available(struct cam_context *ctx,
		cmd->session_handle, cmd->num_resources,
		cmd->handle_type, cmd->resource_hdl);

	if (cmd->num_resources == CAM_API_COMPAT_CONSTANT) {
		ctx_isp->split_acquire = true;
		CAM_DBG(CAM_ISP, "Acquire dev handle");
		goto get_dev_handle;
	}

	if (cmd->num_resources > CAM_ISP_CTX_RES_MAX) {
		CAM_ERR(CAM_ISP, "Too much resources in the acquire");
		rc = -ENOMEM;
@@ -2258,8 +2320,15 @@ static int __cam_isp_ctx_acquire_dev_in_available(struct cam_context *ctx,

	ctx_isp->rdi_only_context = isp_hw_cmd_args.u.is_rdi_only_context;
	ctx_isp->hw_ctx = param.ctxt_to_hw_map;
	ctx_isp->hw_acquired = true;
	ctx_isp->split_acquire = false;
	ctx->ctxt_to_hw_map = param.ctxt_to_hw_map;

	kfree(isp_res);
	isp_res = NULL;

get_dev_handle:

	req_hdl_param.session_hdl = cmd->session_handle;
	/* bridge is not ready for these flags. so false for now */
	req_hdl_param.v4l2_sub_dev_flag = 0;
@@ -2278,31 +2347,178 @@ static int __cam_isp_ctx_acquire_dev_in_available(struct cam_context *ctx,

	/* store session information */
	ctx->session_hdl = cmd->session_handle;

	ctx->state = CAM_CTX_ACQUIRED;

	trace_cam_context_state("ISP", ctx);
	CAM_DBG(CAM_ISP,
		"Acquire success on session_hdl 0x%x num_rsrces %d RDI only %d ctx %u",
		cmd->session_handle, cmd->num_resources,
		(isp_hw_cmd_args.u.is_rdi_only_context ? 1 : 0), ctx->ctx_id);
		"Acquire success on session_hdl 0x%x num_rsrces %d ctx %u",
		cmd->session_handle, cmd->num_resources, ctx->ctx_id);

	return rc;

free_hw:
	release.ctxt_to_hw_map = ctx_isp->hw_ctx;
	if (ctx_isp->hw_acquired)
		ctx->hw_mgr_intf->hw_release(ctx->hw_mgr_intf->hw_mgr_priv,
			&release);
	ctx_isp->hw_ctx = NULL;
	ctx_isp->hw_acquired = false;
free_res:
	kfree(isp_res);
end:
	return rc;
}

static int __cam_isp_ctx_acquire_hw_v1(struct cam_context *ctx,
	void *args)
{
	int rc = 0;
	struct cam_acquire_hw_cmd_v1 *cmd =
		(struct cam_acquire_hw_cmd_v1 *)args;
	struct cam_hw_acquire_args       param;
	struct cam_hw_release_args       release;
	struct cam_isp_context          *ctx_isp =
		(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;
	struct cam_isp_acquire_hw_info  *acquire_hw_info = NULL;

	if (!ctx->hw_mgr_intf) {
		CAM_ERR(CAM_ISP, "HW interface is not ready");
		rc = -EFAULT;
		goto end;
	}

	CAM_DBG(CAM_ISP,
		"session_hdl 0x%x, hdl type %d, res %lld",
		cmd->session_handle, cmd->handle_type, cmd->resource_hdl);

	/* for now we only support user pointer */
	if (cmd->handle_type != 1)  {
		CAM_ERR(CAM_ISP, "Only user pointer is supported");
		rc = -EINVAL;
		goto end;
	}

	if (cmd->data_size < sizeof(*acquire_hw_info)) {
		CAM_ERR(CAM_ISP, "data_size is not a valid value");
		goto end;
	}

	acquire_hw_info = kzalloc(cmd->data_size, GFP_KERNEL);
	if (!acquire_hw_info) {
		rc = -ENOMEM;
		goto end;
	}

	CAM_DBG(CAM_ISP, "start copy resources from user");

	if (copy_from_user(acquire_hw_info, (void __user *)cmd->resource_hdl,
		cmd->data_size)) {
		rc = -EFAULT;
		goto free_res;
	}

	param.context_data = ctx;
	param.event_cb = ctx->irq_cb_intf;
	param.num_acq = CAM_API_COMPAT_CONSTANT;
	param.acquire_info_size = cmd->data_size;
	param.acquire_info = (uint64_t) acquire_hw_info;

	/* call HW manager to reserve the resource */
	rc = ctx->hw_mgr_intf->hw_acquire(ctx->hw_mgr_intf->hw_mgr_priv,
		&param);
	if (rc != 0) {
		CAM_ERR(CAM_ISP, "Acquire device failed");
		goto free_res;
	}

	/* Query the context has rdi only resource */
	hw_cmd_args.ctxt_to_hw_map = param.ctxt_to_hw_map;
	hw_cmd_args.cmd_type = CAM_HW_MGR_CMD_INTERNAL;
	isp_hw_cmd_args.cmd_type = CAM_ISP_HW_MGR_CMD_IS_RDI_ONLY_CONTEXT;
	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, "HW command failed");
		goto free_hw;
	}

	if (isp_hw_cmd_args.u.is_rdi_only_context) {
		/*
		 * this context has rdi only resource assign rdi only
		 * state machine
		 */
		CAM_DBG(CAM_ISP, "RDI only session Context");

		ctx_isp->substate_machine_irq =
			cam_isp_ctx_rdi_only_activated_state_machine_irq;
		ctx_isp->substate_machine =
			cam_isp_ctx_rdi_only_activated_state_machine;
	} else {
		CAM_DBG(CAM_ISP, "Session has PIX or PIX and RDI resources");
		ctx_isp->substate_machine_irq =
			cam_isp_ctx_activated_state_machine_irq;
		ctx_isp->substate_machine =
			cam_isp_ctx_activated_state_machine;
	}

	ctx_isp->rdi_only_context = isp_hw_cmd_args.u.is_rdi_only_context;
	ctx_isp->hw_ctx = param.ctxt_to_hw_map;
	ctx_isp->hw_acquired = true;
	ctx->ctxt_to_hw_map = param.ctxt_to_hw_map;

	trace_cam_context_state("ISP", ctx);
	CAM_DBG(CAM_ISP,
		"Acquire success on session_hdl 0x%xs RDI only %d ctx %u",
		ctx->session_hdl,
		(isp_hw_cmd_args.u.is_rdi_only_context ? 1 : 0), ctx->ctx_id);
	kfree(acquire_hw_info);
	return rc;

free_hw:
	release.ctxt_to_hw_map = ctx_isp->hw_ctx;
	ctx->hw_mgr_intf->hw_release(ctx->hw_mgr_intf->hw_mgr_priv, &release);
	ctx_isp->hw_ctx = NULL;
	ctx_isp->hw_acquired = false;
free_res:
	kfree(isp_res);
	kfree(acquire_hw_info);
end:
	return rc;
}

static int __cam_isp_ctx_acquire_hw_in_acquired(struct cam_context *ctx,
	void *args)
{
	int rc = -EINVAL;
	uint32_t api_version;

	if (!ctx || !args) {
		CAM_ERR(CAM_ISP, "Invalid input pointer");
		return rc;
	}

	api_version = *((uint32_t *)args);
	if (api_version == 1)
		rc = __cam_isp_ctx_acquire_hw_v1(ctx, args);
	else
		CAM_ERR(CAM_ISP, "Unsupported api version %d", api_version);

	return rc;
}

static int __cam_isp_ctx_config_dev_in_acquired(struct cam_context *ctx,
	struct cam_config_dev_cmd *cmd)
{
	int rc = 0;
	struct cam_isp_context *ctx_isp =
		(struct cam_isp_context *) ctx->ctx_priv;

	if (!ctx_isp->hw_acquired) {
		CAM_ERR(CAM_ISP, "HW is not acquired, reject packet");
		return -EINVAL;
	}

	rc = __cam_isp_ctx_config_dev_in_top_state(ctx, cmd);

@@ -2329,7 +2545,7 @@ static int __cam_isp_ctx_link_in_acquired(struct cam_context *ctx,
	ctx_isp->subscribe_event = link->subscribe_event;

	/* change state only if we had the init config */
	if (!list_empty(&ctx->pending_req_list)) {
	if (ctx_isp->init_received) {
		ctx->state = CAM_CTX_READY;
		trace_cam_context_state("ISP", ctx);
	}
@@ -2550,8 +2766,11 @@ static int __cam_isp_ctx_stop_dev_in_activated(struct cam_context *ctx,
	struct cam_start_stop_dev_cmd *cmd)
{
	int rc = 0;
	struct cam_isp_context *ctx_isp =
		(struct cam_isp_context *)ctx->ctx_priv;

	__cam_isp_ctx_stop_dev_in_activated_unlock(ctx, cmd);
	ctx_isp->init_received = false;
	ctx->state = CAM_CTX_ACQUIRED;
	trace_cam_context_state("ISP", ctx);
	return rc;
@@ -2573,6 +2792,22 @@ static int __cam_isp_ctx_release_dev_in_activated(struct cam_context *ctx,
	return rc;
}

static int __cam_isp_ctx_release_hw_in_activated(struct cam_context *ctx,
	void *cmd)
{
	int rc = 0;

	rc = __cam_isp_ctx_stop_dev_in_activated_unlock(ctx, NULL);
	if (rc)
		CAM_ERR(CAM_ISP, "Stop device failed rc=%d", rc);

	rc = __cam_isp_ctx_release_hw_in_top_state(ctx, cmd);
	if (rc)
		CAM_ERR(CAM_ISP, "Release hw failed rc=%d", rc);

	return rc;
}

static int __cam_isp_ctx_link_pause(struct cam_context *ctx)
{
	int rc = 0;
@@ -2754,8 +2989,10 @@ static struct cam_ctx_ops
	/* Acquired */
	{
		.ioctl_ops = {
			.acquire_hw = __cam_isp_ctx_acquire_hw_in_acquired,
			.release_dev = __cam_isp_ctx_release_dev_in_top_state,
			.config_dev = __cam_isp_ctx_config_dev_in_acquired,
			.release_hw = __cam_isp_ctx_release_hw_in_top_state,
		},
		.crm_ops = {
			.link = __cam_isp_ctx_link_in_acquired,
@@ -2772,6 +3009,7 @@ static struct cam_ctx_ops
			.start_dev = __cam_isp_ctx_start_dev_in_ready,
			.release_dev = __cam_isp_ctx_release_dev_in_top_state,
			.config_dev = __cam_isp_ctx_config_dev_in_top_state,
			.release_hw = __cam_isp_ctx_release_hw_in_top_state,
		},
		.crm_ops = {
			.unlink = __cam_isp_ctx_unlink_in_ready,
@@ -2786,6 +3024,7 @@ static struct cam_ctx_ops
			.stop_dev = __cam_isp_ctx_stop_dev_in_activated,
			.release_dev = __cam_isp_ctx_release_dev_in_activated,
			.config_dev = __cam_isp_ctx_config_dev_in_top_state,
			.release_hw = __cam_isp_ctx_release_hw_in_activated,
		},
		.crm_ops = {
			.unlink = __cam_isp_ctx_unlink_in_activated,
Loading