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

Commit 2df84503 authored by Junzhe Zou's avatar Junzhe Zou
Browse files

msm: camera: reqmgr: Add EOF trigger notification



Add method in ISP to notify SOF/EOF that is subscribed by camera
modules to CRM, CRM will send apply command to modules as the
subscribe mask.

CRs-fixed: 2096454
Change-Id: I6ad7d77f091386d3be91c670da75e1cd15e41ecd
Signed-off-by: default avatarPavan Kumar Chilamkurthi <pchilamk@codeaurora.org>
Signed-off-by: default avatarJunzhe Zou <jnzhezou@codeaurora.org>
parent 505171ef
Loading
Loading
Loading
Loading
+61 −22
Original line number Diff line number Diff line
@@ -219,7 +219,8 @@ static int __cam_isp_ctx_reg_upd_in_activated_state(
static int __cam_isp_ctx_notify_sof_in_actived_state(
	struct cam_isp_context *ctx_isp, void *evt_data)
{
	struct cam_req_mgr_sof_notify  notify;
	int rc = 0;
	struct cam_req_mgr_trigger_notify  notify;
	struct cam_context *ctx = ctx_isp->base;
	struct cam_ctx_request  *req;
	uint64_t  request_id  = 0;
@@ -231,15 +232,18 @@ static int __cam_isp_ctx_notify_sof_in_actived_state(
	 * In this case, we need to skip the current notification. This
	 * helps the state machine to catch up the delay.
	 */
	if (ctx->ctx_crm_intf && ctx->ctx_crm_intf->notify_sof &&
	if (ctx->ctx_crm_intf && ctx->ctx_crm_intf->notify_trigger &&
		ctx_isp->active_req_cnt <= 2) {
		if (ctx_isp->subscribe_event & CAM_TRIGGER_POINT_SOF) {
			notify.link_hdl = ctx->link_hdl;
			notify.dev_hdl = ctx->dev_hdl;
			notify.frame_id = ctx_isp->frame_id;
			notify.trigger = CAM_TRIGGER_POINT_SOF;

		ctx->ctx_crm_intf->notify_sof(&notify);
			ctx->ctx_crm_intf->notify_trigger(&notify);
			CAM_DBG(CAM_ISP, "Notify CRM  SOF frame %lld",
				ctx_isp->frame_id);
		}

		list_for_each_entry(req, &ctx->active_req_list, list) {
			if (req->request_id > ctx_isp->reported_req_id) {
@@ -253,11 +257,39 @@ static int __cam_isp_ctx_notify_sof_in_actived_state(
			CAM_REQ_MGR_SOF_EVENT_SUCCESS);
	} else {
		CAM_ERR(CAM_ISP, "Can not notify SOF to CRM");
		rc = -EFAULT;
	}

	return 0;
}

static int __cam_isp_ctx_notify_eof_in_actived_state(
	struct cam_isp_context *ctx_isp, void *evt_data)
{
	int rc = 0;
	struct cam_req_mgr_trigger_notify  notify;
	struct cam_context *ctx = ctx_isp->base;

	if (!(ctx_isp->subscribe_event & CAM_TRIGGER_POINT_EOF))
		return rc;

	/* notify reqmgr with eof signal */
	if (ctx->ctx_crm_intf && ctx->ctx_crm_intf->notify_trigger) {
		notify.link_hdl = ctx->link_hdl;
		notify.dev_hdl = ctx->dev_hdl;
		notify.frame_id = ctx_isp->frame_id;
		notify.trigger = CAM_TRIGGER_POINT_EOF;

		ctx->ctx_crm_intf->notify_trigger(&notify);
		CAM_DBG(CAM_ISP, "Notify CRM EOF frame %lld\n",
			ctx_isp->frame_id);
	} else {
		CAM_ERR(CAM_ISP, "Can not notify EOF to CRM");
		rc = -EFAULT;
	}

	return rc;
}

static int __cam_isp_ctx_sof_in_activated_state(
	struct cam_isp_context *ctx_isp, void *evt_data)
@@ -581,7 +613,7 @@ static struct cam_isp_ctx_irq_ops
			__cam_isp_ctx_sof_in_activated_state,
			__cam_isp_ctx_reg_upd_in_sof,
			__cam_isp_ctx_notify_sof_in_actived_state,
			NULL,
			__cam_isp_ctx_notify_eof_in_actived_state,
			NULL,
		},
	},
@@ -592,7 +624,7 @@ static struct cam_isp_ctx_irq_ops
			__cam_isp_ctx_sof_in_activated_state,
			__cam_isp_ctx_reg_upd_in_activated_state,
			__cam_isp_ctx_epoch_in_applied,
			NULL,
			__cam_isp_ctx_notify_eof_in_actived_state,
			__cam_isp_ctx_buf_done_in_applied,
		},
	},
@@ -603,7 +635,7 @@ static struct cam_isp_ctx_irq_ops
			__cam_isp_ctx_sof_in_epoch,
			NULL,
			__cam_isp_ctx_notify_sof_in_actived_state,
			NULL,
			__cam_isp_ctx_notify_eof_in_actived_state,
			__cam_isp_ctx_buf_done_in_epoch,
		},
	},
@@ -614,7 +646,7 @@ static struct cam_isp_ctx_irq_ops
			__cam_isp_ctx_sof_in_activated_state,
			NULL,
			__cam_isp_ctx_notify_sof_in_actived_state,
			NULL,
			__cam_isp_ctx_notify_eof_in_actived_state,
			__cam_isp_ctx_buf_done_in_bubble,
		},
	},
@@ -890,7 +922,7 @@ static int __cam_isp_ctx_rdi_only_sof_in_top_state(
{
	int rc = 0;
	struct cam_context                    *ctx = ctx_isp->base;
	struct cam_req_mgr_sof_notify          notify;
	struct cam_req_mgr_trigger_notify      notify;
	struct cam_isp_hw_sof_event_data      *sof_event_data = evt_data;
	uint64_t                               request_id  = 0;

@@ -911,13 +943,14 @@ static int __cam_isp_ctx_rdi_only_sof_in_top_state(
	 * In this case, we need to skip the current notification. This
	 * helps the state machine to catch up the delay.
	 */
	if (ctx->ctx_crm_intf && ctx->ctx_crm_intf->notify_sof &&
	if (ctx->ctx_crm_intf && ctx->ctx_crm_intf->notify_trigger &&
		ctx_isp->active_req_cnt <= 2) {
		notify.link_hdl = ctx->link_hdl;
		notify.dev_hdl = ctx->dev_hdl;
		notify.frame_id = ctx_isp->frame_id;
		notify.trigger = CAM_TRIGGER_POINT_SOF;

		ctx->ctx_crm_intf->notify_sof(&notify);
		ctx->ctx_crm_intf->notify_trigger(&notify);
		CAM_DBG(CAM_ISP, "Notify CRM  SOF frame %lld",
			ctx_isp->frame_id);

@@ -1037,7 +1070,7 @@ static int __cam_isp_ctx_rdi_only_sof_in_bubble_state(
	uint32_t i;
	struct cam_ctx_request                *req;
	struct cam_context                    *ctx = ctx_isp->base;
	struct cam_req_mgr_sof_notify          notify;
	struct cam_req_mgr_trigger_notify      notify;
	struct cam_isp_hw_sof_event_data      *sof_event_data = evt_data;
	struct cam_isp_ctx_req                *req_isp;
	uint64_t                               request_id  = 0;
@@ -1072,12 +1105,13 @@ static int __cam_isp_ctx_rdi_only_sof_in_bubble_state(
	}

	/* notify reqmgr with sof signal */
	if (ctx->ctx_crm_intf && ctx->ctx_crm_intf->notify_sof) {
	if (ctx->ctx_crm_intf && ctx->ctx_crm_intf->notify_trigger) {
		notify.link_hdl = ctx->link_hdl;
		notify.dev_hdl = ctx->dev_hdl;
		notify.frame_id = ctx_isp->frame_id;
		notify.trigger = CAM_TRIGGER_POINT_SOF;

		ctx->ctx_crm_intf->notify_sof(&notify);
		ctx->ctx_crm_intf->notify_trigger(&notify);
		CAM_DBG(CAM_ISP, "Notify CRM  SOF frame %lld",
			ctx_isp->frame_id);

@@ -1106,11 +1140,11 @@ static int __cam_isp_ctx_rdi_only_reg_upd_in_bubble_applied_state(
	struct cam_ctx_request  *req;
	struct cam_context      *ctx = ctx_isp->base;
	struct cam_isp_ctx_req  *req_isp;
	struct cam_req_mgr_sof_notify  notify;
	struct cam_req_mgr_trigger_notify  notify;
	uint64_t  request_id  = 0;

	/* notify reqmgr with sof signal*/
	if (ctx->ctx_crm_intf && ctx->ctx_crm_intf->notify_sof) {
	if (ctx->ctx_crm_intf && ctx->ctx_crm_intf->notify_trigger) {
		if (list_empty(&ctx->pending_req_list)) {
			CAM_ERR(CAM_ISP, "Reg upd ack with no pending request");
			goto error;
@@ -1138,8 +1172,9 @@ static int __cam_isp_ctx_rdi_only_reg_upd_in_bubble_applied_state(
		notify.link_hdl = ctx->link_hdl;
		notify.dev_hdl = ctx->dev_hdl;
		notify.frame_id = ctx_isp->frame_id;
		notify.trigger = CAM_TRIGGER_POINT_SOF;

		ctx->ctx_crm_intf->notify_sof(&notify);
		ctx->ctx_crm_intf->notify_trigger(&notify);
		CAM_DBG(CAM_ISP, "Notify CRM  SOF frame %lld",
			ctx_isp->frame_id);
	} else {
@@ -1608,11 +1643,14 @@ static int __cam_isp_ctx_link_in_acquired(struct cam_context *ctx,
	struct cam_req_mgr_core_dev_link_setup *link)
{
	int rc = 0;
	struct cam_isp_context *ctx_isp =
		(struct cam_isp_context *) ctx->ctx_priv;

	CAM_DBG(CAM_ISP, "Enter.........");

	ctx->link_hdl = link->link_hdl;
	ctx->ctx_crm_intf = link->crm_cb;
	ctx_isp->subscribe_event = link->subscribe_event;

	/* change state only if we had the init config */
	if (!list_empty(&ctx->pending_req_list)) {
@@ -1645,6 +1683,7 @@ static int __cam_isp_ctx_get_dev_info_in_acquired(struct cam_context *ctx,
	strlcpy(dev_info->name, CAM_ISP_DEV_NAME, sizeof(dev_info->name));
	dev_info->dev_id = CAM_REQ_MGR_DEVICE_IFE;
	dev_info->p_delay = 1;
	dev_info->trigger = CAM_TRIGGER_POINT_SOF;

	return rc;
}
+4 −0
Original line number Diff line number Diff line
@@ -109,6 +109,9 @@ struct cam_isp_ctx_req {
 * @sof_timestamp_val:     Captured time stamp value at sof hw event
 * @active_req_cnt:        Counter for the active request
 * @reported_req_id:       Last reported request id
 * @subscribe_event:       The irq event mask that CRM subscribes to, IFE will
 *                         invoke CRM cb at those event.
 *
 */
struct cam_isp_context {
	struct cam_context              *base;
@@ -125,6 +128,7 @@ struct cam_isp_context {
	uint64_t                         sof_timestamp_val;
	int32_t                          active_req_cnt;
	int64_t                          reported_req_id;
	uint32_t                         subscribe_event;
};

/**
+153 −46
Original line number Diff line number Diff line
@@ -2444,34 +2444,51 @@ static int cam_ife_hw_mgr_handle_reg_update(
	return 0;
}

static int cam_ife_hw_mgr_check_epoch_for_dual_vfe(
static int cam_ife_hw_mgr_check_irq_for_dual_vfe(
	struct cam_ife_hw_mgr_ctx   *ife_hw_mgr_ctx,
	uint32_t                     core_idx0,
	uint32_t                     core_idx1)
	uint32_t                     core_idx1,
	uint32_t                     hw_event_type)
{
	int32_t rc = -1;
	uint32_t *epoch_cnt = ife_hw_mgr_ctx->epoch_cnt;
	uint32_t *event_cnt = NULL;

	if (epoch_cnt[core_idx0] ==
			epoch_cnt[core_idx1]) {
	switch (hw_event_type) {
	case CAM_ISP_HW_EVENT_SOF:
		event_cnt = ife_hw_mgr_ctx->sof_cnt;
		break;
	case CAM_ISP_HW_EVENT_REG_UPDATE:
		event_cnt = ife_hw_mgr_ctx->epoch_cnt;
		break;
	case CAM_ISP_HW_EVENT_EOF:
		event_cnt = ife_hw_mgr_ctx->eof_cnt;
		break;
	default:
		return 0;
	}

		epoch_cnt[core_idx0] = 0;
		epoch_cnt[core_idx1] = 0;
	if (event_cnt[core_idx0] ==
			event_cnt[core_idx1]) {

		event_cnt[core_idx0] = 0;
		event_cnt[core_idx1] = 0;

		rc = 0;
		return rc;
	}

	if ((epoch_cnt[core_idx0] - epoch_cnt[core_idx1] > 1) ||
		(epoch_cnt[core_idx1] - epoch_cnt[core_idx0] > 1)) {
	if ((event_cnt[core_idx0] - event_cnt[core_idx1] > 1) ||
		(event_cnt[core_idx1] - event_cnt[core_idx0] > 1)) {

		CAM_WARN(CAM_ISP,
			"One of the VFE of dual VFE cound not generate error");
			"One of the VFE cound not generate hw event %d",
			hw_event_type);
		rc = -1;
		return rc;
	}

	CAM_DBG(CAM_ISP, "Only one core_index has given EPOCH");
	CAM_DBG(CAM_ISP, "Only one core_index has given hw event %d",
			hw_event_type);

	return rc;
}
@@ -2562,10 +2579,11 @@ static int cam_ife_hw_mgr_handle_epoch_for_camif_hw_res(
			core_index0 = hw_res_l->hw_intf->hw_idx;
			core_index1 = hw_res_r->hw_intf->hw_idx;

			rc = cam_ife_hw_mgr_check_epoch_for_dual_vfe(
			rc = cam_ife_hw_mgr_check_irq_for_dual_vfe(
					ife_hwr_mgr_ctx,
					core_index0,
					core_index1);
					core_index1,
					evt_payload->evt_id);

			if (!rc)
				ife_hwr_irq_epoch_cb(
@@ -2588,37 +2606,6 @@ static int cam_ife_hw_mgr_handle_epoch_for_camif_hw_res(
	return 0;
}

static int cam_ife_hw_mgr_check_sof_for_dual_vfe(
	struct cam_ife_hw_mgr_ctx   *ife_hwr_mgr_ctx,
	uint32_t                     core_idx0,
	uint32_t                     core_idx1)
{
	uint32_t *sof_cnt = ife_hwr_mgr_ctx->sof_cnt;
	int32_t rc = -1;

	if (sof_cnt[core_idx0] ==
			sof_cnt[core_idx1]) {

		sof_cnt[core_idx0] = 0;
		sof_cnt[core_idx1] = 0;

		rc = 0;
		return rc;
	}

	if ((sof_cnt[core_idx0] - sof_cnt[core_idx1] > 1) ||
		(sof_cnt[core_idx1] - sof_cnt[core_idx0] > 1)) {

		CAM_ERR(CAM_ISP, "One VFE of dual VFE cound not generate SOF");
		rc = -1;
		return rc;
	}

	CAM_INFO(CAM_ISP, "Only one core_index has given SOF");

	return rc;
}

static int cam_ife_hw_mgr_process_camif_sof(
	struct cam_ife_hw_mgr_res            *isp_ife_camif_res,
	struct cam_ife_hw_mgr_ctx            *ife_hwr_mgr_ctx,
@@ -2709,8 +2696,8 @@ static int cam_ife_hw_mgr_process_camif_sof(
		core_index0 = hw_res_l->hw_intf->hw_idx;
		core_index1 = hw_res_r->hw_intf->hw_idx;

		rc = cam_ife_hw_mgr_check_sof_for_dual_vfe(ife_hwr_mgr_ctx,
			core_index0, core_index1);
		rc = cam_ife_hw_mgr_check_irq_for_dual_vfe(ife_hwr_mgr_ctx,
			core_index0, core_index1, evt_payload->evt_id);

		if (!rc)
			ife_hwr_irq_sof_cb(ife_hwr_mgr_ctx->common.cb_priv,
@@ -2803,6 +2790,124 @@ static int cam_ife_hw_mgr_handle_sof(
	return 0;
}

static int cam_ife_hw_mgr_handle_eof_for_camif_hw_res(
	void                              *handler_priv,
	void                              *payload)
{
	int32_t rc = -EINVAL;
	struct cam_isp_resource_node         *hw_res_l = NULL;
	struct cam_isp_resource_node         *hw_res_r = NULL;
	struct cam_ife_hw_mgr_ctx            *ife_hwr_mgr_ctx;
	struct cam_vfe_top_irq_evt_payload   *evt_payload;
	struct cam_ife_hw_mgr_res            *isp_ife_camif_res = NULL;
	cam_hw_event_cb_func                  ife_hwr_irq_eof_cb;
	struct cam_isp_hw_eof_event_data      eof_done_event_data;
	uint32_t  core_idx;
	uint32_t  eof_status = 0;
	uint32_t  core_index0;
	uint32_t  core_index1;

	CAM_DBG(CAM_ISP, "Enter");

	ife_hwr_mgr_ctx = handler_priv;
	evt_payload = payload;
	if (!evt_payload) {
		pr_err("%s: no payload\n", __func__);
		return IRQ_HANDLED;
	}
	core_idx = evt_payload->core_index;
	ife_hwr_irq_eof_cb =
		ife_hwr_mgr_ctx->common.event_cb[CAM_ISP_HW_EVENT_EOF];

	evt_payload->evt_id = CAM_ISP_HW_EVENT_EOF;

	list_for_each_entry(isp_ife_camif_res,
		&ife_hwr_mgr_ctx->res_list_ife_src, list) {

		if ((isp_ife_camif_res->res_type ==
			CAM_IFE_HW_MGR_RES_UNINIT) ||
			(isp_ife_camif_res->res_id != CAM_ISP_HW_VFE_IN_CAMIF))
			continue;

		hw_res_l = isp_ife_camif_res->hw_res[0];
		hw_res_r = isp_ife_camif_res->hw_res[1];

		CAM_DBG(CAM_ISP, "is_dual_vfe ? = %d",
				isp_ife_camif_res->is_dual_vfe);
		switch (isp_ife_camif_res->is_dual_vfe) {
		/* Handling Single VFE Scenario */
		case 0:
			/* EOF check for Left side VFE */
			if (!hw_res_l) {
				pr_err("%s: VFE Device is NULL\n",
					__func__);
				break;
			}
			CAM_DBG(CAM_ISP, "curr_core_idx = %d, core idx hw = %d",
					core_idx, hw_res_l->hw_intf->hw_idx);

			if (core_idx == hw_res_l->hw_intf->hw_idx) {
				eof_status = hw_res_l->bottom_half_handler(
					hw_res_l, evt_payload);
				if (!eof_status)
					ife_hwr_irq_eof_cb(
						ife_hwr_mgr_ctx->common.cb_priv,
						CAM_ISP_HW_EVENT_EOF,
						&eof_done_event_data);
			}

			break;
		/* Handling dual VFE Scenario */
		case 1:
			if ((!hw_res_l) || (!hw_res_r)) {
				CAM_ERR(CAM_ISP, "Dual VFE Device is NULL");
				break;
			}
			if (core_idx == hw_res_l->hw_intf->hw_idx) {
				eof_status = hw_res_l->bottom_half_handler(
					hw_res_l, evt_payload);

				if (!eof_status)
					ife_hwr_mgr_ctx->eof_cnt[core_idx]++;
			}

			/* EOF check for Right side VFE */
			if (core_idx == hw_res_r->hw_intf->hw_idx) {
				eof_status = hw_res_r->bottom_half_handler(
					hw_res_r, evt_payload);

				if (!eof_status)
					ife_hwr_mgr_ctx->eof_cnt[core_idx]++;
			}

			core_index0 = hw_res_l->hw_intf->hw_idx;
			core_index1 = hw_res_r->hw_intf->hw_idx;

			rc = cam_ife_hw_mgr_check_irq_for_dual_vfe(
					ife_hwr_mgr_ctx,
					core_index0,
					core_index1,
					evt_payload->evt_id);

			if (!rc)
				ife_hwr_irq_eof_cb(
					ife_hwr_mgr_ctx->common.cb_priv,
					CAM_ISP_HW_EVENT_EPOCH,
					&eof_done_event_data);

			break;

		default:
			CAM_ERR(CAM_ISP, "error with hw_res");
		}
	}

	CAM_DBG(CAM_ISP, "Exit (eof_status = %d)!", eof_status);

	return 0;
}


static int cam_ife_hw_mgr_handle_buf_done_for_hw_res(
	void                              *handler_priv,
	void                              *payload)
@@ -3009,6 +3114,8 @@ int cam_ife_mgr_do_tasklet(void *handler_priv, void *evt_payload_priv)
	/* EPOCH IRQ */
	cam_ife_hw_mgr_handle_epoch_for_camif_hw_res(ife_hwr_mgr_ctx,
		evt_payload_priv);
	cam_ife_hw_mgr_handle_eof_for_camif_hw_res(ife_hwr_mgr_ctx,
		evt_payload_priv);

	return IRQ_HANDLED;
}
+2 −0
Original line number Diff line number Diff line
@@ -106,6 +106,7 @@ struct ctx_base_info {
 * @cdm_cmd                 cdm base and length request pointer
 * @sof_cnt                 sof count value per core, used for dual VFE
 * @epoch_cnt               epoch count value per core, used for dual VFE
 * @eof_cnt                 eof count value per core, used for dual VFE
 * @overflow_pending        flat to specify the overflow is pending for the
 *                          context
 * @is_rdi_only_context     flag to specify the context has only rdi resource
@@ -138,6 +139,7 @@ struct cam_ife_hw_mgr_ctx {

	uint32_t                        sof_cnt[CAM_IFE_HW_NUM_MAX];
	uint32_t                        epoch_cnt[CAM_IFE_HW_NUM_MAX];
	uint32_t                        eof_cnt[CAM_IFE_HW_NUM_MAX];
	atomic_t                        overflow_pending;
	uint32_t                        is_rdi_only_context;

+1 −0
Original line number Diff line number Diff line
@@ -70,6 +70,7 @@ static struct cam_vfe_camif_reg_data vfe_170_camif_reg_data = {
	.sof_irq_mask                    = 0x00000001,
	.epoch0_irq_mask                 = 0x00000004,
	.reg_update_irq_mask             = 0x00000010,
	.eof_irq_mask                    = 0x00000002,
};

struct cam_vfe_top_ver2_reg_offset_module_ctrl lens_170_reg = {
Loading