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

Commit fd66b87b authored by Karthik Anantha Ram's avatar Karthik Anantha Ram Committed by Gerrit - the friendly Code Review server
Browse files

msm: camera: reqmgr: Add support for dual trigger



Currently CRM waits for a single trigger to apply settings
for all the devices on a given link. This change provides
provision for CRM to wait on two triggers prior to applying
a given setting.

CRs-Fixed: 2627065
Change-Id: If6e4c9281cfd1bf1a8ffa369daee060d79f3c39e
Signed-off-by: default avatarKarthik Anantha Ram <kartanan@codeaurora.org>
parent 283e37c3
Loading
Loading
Loading
Loading
+6 −0
Original line number Diff line number Diff line
@@ -1272,6 +1272,7 @@ static int __cam_isp_ctx_notify_sof_in_activated_state(
			notify.trigger = CAM_TRIGGER_POINT_SOF;
			notify.req_id = ctx_isp->req_info.last_bufdone_req_id;
			notify.sof_timestamp_val = ctx_isp->sof_timestamp_val;
			notify.trigger_id = ctx_isp->trigger_id;

			ctx->ctx_crm_intf->notify_trigger(&notify);
			CAM_DBG(CAM_ISP, "Notify CRM  SOF frame %lld ctx %u",
@@ -4484,6 +4485,7 @@ static int __cam_isp_ctx_link_in_acquired(struct cam_context *ctx,
	ctx->link_hdl = link->link_hdl;
	ctx->ctx_crm_intf = link->crm_cb;
	ctx_isp->subscribe_event = link->subscribe_event;
	ctx_isp->trigger_id = link->trigger_id;

	/* change state only if we had the init config */
	if (ctx_isp->init_received) {
@@ -4500,9 +4502,12 @@ static int __cam_isp_ctx_unlink_in_acquired(struct cam_context *ctx,
	struct cam_req_mgr_core_dev_link_setup *unlink)
{
	int rc = 0;
	struct cam_isp_context *ctx_isp =
		(struct cam_isp_context *) ctx->ctx_priv;

	ctx->link_hdl = -1;
	ctx->ctx_crm_intf = NULL;
	ctx_isp->trigger_id = -1;

	return rc;
}
@@ -4517,6 +4522,7 @@ static int __cam_isp_ctx_get_dev_info_in_acquired(struct cam_context *ctx,
	dev_info->dev_id = CAM_REQ_MGR_DEVICE_IFE;
	dev_info->p_delay = 1;
	dev_info->trigger = CAM_TRIGGER_POINT_SOF;
	dev_info->trigger_on = true;

	return rc;
}
+2 −0
Original line number Diff line number Diff line
@@ -255,6 +255,7 @@ struct cam_isp_context_event_record {
 * @rxd_epoch:                 Indicate whether epoch has been received. Used to
 *                             decide whether to apply request in offline ctx
 * @workq:                     Worker thread for offline ife
 * @trigger_id:                ID provided by CRM for each ctx on the link
 *
 */
struct cam_isp_context {
@@ -296,6 +297,7 @@ struct cam_isp_context {
	unsigned int                          init_timestamp;
	atomic_t                              rxd_epoch;
	struct cam_req_mgr_core_workq        *workq;
	int32_t                               trigger_id;
};

/**
+74 −3
Original line number Diff line number Diff line
@@ -40,6 +40,9 @@ void cam_req_mgr_core_link_reset(struct cam_req_mgr_core_link *link)
	link->open_req_cnt = 0;
	link->last_flush_id = 0;
	link->initial_sync_req = -1;
	link->dual_trigger = false;
	link->trigger_cnt[0] = 0;
	link->trigger_cnt[1] = 0;
	link->in_msync_mode = false;
	link->retry_cnt = 0;
	link->is_shutdown = false;
@@ -2767,6 +2770,33 @@ static int cam_req_mgr_cb_notify_err(
	return rc;
}

static int __cam_req_mgr_check_for_dual_trigger(
	struct cam_req_mgr_core_link    *link)
{
	int rc  = -EAGAIN;

	if (link->trigger_cnt[0] == link->trigger_cnt[1]) {
		link->trigger_cnt[0] = 0;
		link->trigger_cnt[1] = 0;
		rc = 0;
		return rc;
	}

	if ((link->trigger_cnt[0] &&
		(link->trigger_cnt[0] - link->trigger_cnt[1] > 1)) ||
		(link->trigger_cnt[1] &&
		(link->trigger_cnt[1] - link->trigger_cnt[0] > 1))) {

		CAM_ERR(CAM_CRM,
			"One of the devices could not generate trigger");
		return rc;
	}

	CAM_DBG(CAM_CRM, "Only one device has generated trigger");

	return rc;
}

/**
 * cam_req_mgr_cb_notify_timer()
 *
@@ -2885,7 +2915,7 @@ static int cam_req_mgr_cb_notify_stop(
static int cam_req_mgr_cb_notify_trigger(
	struct cam_req_mgr_trigger_notify *trigger_data)
{
	int                              rc = 0;
	int32_t                          rc = 0, trigger_id = 0;
	struct crm_workq_task           *task = NULL;
	struct cam_req_mgr_core_link    *link = NULL;
	struct cam_req_mgr_trigger_notify   *notify_trigger;
@@ -2905,6 +2935,8 @@ static int cam_req_mgr_cb_notify_trigger(
		goto end;
	}

	trigger_id = trigger_data->trigger_id;

	spin_lock_bh(&link->link_state_spin_lock);
	if (link->state < CAM_CRM_LINK_STATE_READY) {
		CAM_WARN(CAM_CRM, "invalid link state:%d", link->state);
@@ -2916,6 +2948,23 @@ static int cam_req_mgr_cb_notify_trigger(
	if ((link->watchdog) && (link->watchdog->pause_timer))
		link->watchdog->pause_timer = false;

	if (link->dual_trigger) {
		if ((trigger_id >= 0) && (trigger_id <
			CAM_REQ_MGR_MAX_TRIGGERS)) {
			link->trigger_cnt[trigger_id]++;
			rc = __cam_req_mgr_check_for_dual_trigger(link);
			if (rc) {
				spin_unlock_bh(&link->link_state_spin_lock);
				goto end;
			}
		} else {
			CAM_ERR(CAM_CRM, "trigger_id invalid %d", trigger_id);
			rc = -EINVAL;
			spin_unlock_bh(&link->link_state_spin_lock);
			goto end;
		}
	}

	crm_timer_reset(link->watchdog);
	spin_unlock_bh(&link->link_state_spin_lock);

@@ -2970,6 +3019,7 @@ static int __cam_req_mgr_setup_link_info(struct cam_req_mgr_core_link *link,
	struct cam_req_mgr_req_tbl             *pd_tbl;
	enum cam_pipeline_delay                 max_delay;
	uint32_t                                subscribe_event = 0;
	uint32_t num_trigger_devices = 0;
	if (link_info->version == VERSION_1) {
		if (link_info->u.link_info_v1.num_devices >
			CAM_REQ_MGR_MAX_HANDLES)
@@ -2980,6 +3030,7 @@ static int __cam_req_mgr_setup_link_info(struct cam_req_mgr_core_link *link,
			CAM_REQ_MGR_MAX_HANDLES_V2)
			return -EPERM;
	}

	mutex_init(&link->req.lock);
	CAM_DBG(CAM_CRM, "LOCK_DBG in_q lock %pK", &link->req.lock);
	link->req.num_tbl = 0;
@@ -3059,6 +3110,17 @@ static int __cam_req_mgr_setup_link_info(struct cam_req_mgr_core_link *link,

			subscribe_event |= (uint32_t)dev->dev_info.trigger;
		}

		if (dev->dev_info.trigger_on)
			num_trigger_devices++;
	}

	if (num_trigger_devices > CAM_REQ_MGR_MAX_TRIGGERS) {
		CAM_ERR(CAM_CRM,
			"Unsupported number of trigger devices %u",
			num_trigger_devices);
		rc = -EINVAL;
		goto error;
	}

	link->subscribe_event = subscribe_event;
@@ -3067,7 +3129,10 @@ static int __cam_req_mgr_setup_link_info(struct cam_req_mgr_core_link *link,
	link_data.crm_cb = &cam_req_mgr_ops;
	link_data.max_delay = max_delay;
	link_data.subscribe_event = subscribe_event;
	if (num_trigger_devices == CAM_REQ_MGR_MAX_TRIGGERS)
		link->dual_trigger = true;

	num_trigger_devices = 0;
	for (i = 0; i < num_devices; i++) {
		dev = &link->l_dev[i];

@@ -3107,6 +3172,12 @@ static int __cam_req_mgr_setup_link_info(struct cam_req_mgr_core_link *link,
		CAM_DBG(CAM_CRM, "dev_bit %u name %s pd %u mask %d",
			dev->dev_bit, dev->dev_info.name, pd_tbl->pd,
			pd_tbl->dev_mask);
		link_data.trigger_id = -1;
		if ((dev->dev_info.trigger_on) && (link->dual_trigger)) {
			link_data.trigger_id = num_trigger_devices;
			num_trigger_devices++;
		}

		/* Communicate with dev to establish the link */
		dev->ops->link_setup(&link_data);

+7 −0
Original line number Diff line number Diff line
@@ -37,6 +37,7 @@

#define VERSION_1  1
#define VERSION_2  2
#define CAM_REQ_MGR_MAX_TRIGGERS   2

/**
 * enum crm_workq_task_type
@@ -345,6 +346,9 @@ struct cam_req_mgr_connected_device {
 *                         as part of shutdown.
 * @sof_timestamp_value  : SOF timestamp value
 * @prev_sof_timestamp   : Previous SOF timestamp value
 * @dual_trigger         : Links needs to wait for two triggers prior to
 *                         applying the settings
 * @trigger_cnt          : trigger count value per device initiating the trigger
 */
struct cam_req_mgr_core_link {
	int32_t                              link_hdl;
@@ -375,6 +379,9 @@ struct cam_req_mgr_core_link {
	bool                                 is_shutdown;
	uint64_t                             sof_timestamp;
	uint64_t                             prev_sof_timestamp;
	bool                                 dual_trigger;
	uint32_t    trigger_cnt[CAM_REQ_MGR_MAX_TRIGGERS];

};

/**
+16 −12
Original line number Diff line number Diff line
@@ -211,6 +211,7 @@ enum cam_req_mgr_link_evt_type {
 * only to the devices which subscribe to this point.
 * @sof_timestamp_val: Captured time stamp value at sof hw event
 * @req_id    : req id which returned buf_done
 * @trigger_id: ID to differentiate between the trigger devices
 */
struct cam_req_mgr_trigger_notify {
	int32_t  link_hdl;
@@ -219,6 +220,7 @@ struct cam_req_mgr_trigger_notify {
	uint32_t trigger;
	uint64_t sof_timestamp_val;
	uint64_t req_id;
	int32_t  trigger_id;
};

/**
@@ -289,7 +291,7 @@ struct cam_req_mgr_notify_stop {
 * @dev_id     : device id info
 * @p_delay    : delay between time settings applied and take effect
 * @trigger    : Trigger point for the client
 *
 * @trigger_on : This device provides trigger
 */
struct cam_req_mgr_device_info {
	int32_t                     dev_hdl;
@@ -297,6 +299,7 @@ struct cam_req_mgr_device_info {
	enum cam_req_mgr_device_id  dev_id;
	enum cam_pipeline_delay     p_delay;
	uint32_t                    trigger;
	bool                        trigger_on;
};

/**
@@ -307,7 +310,7 @@ struct cam_req_mgr_device_info {
 * @max_delay       : max pipeline delay on this link
 * @crm_cb          : callback funcs to communicate with req mgr
 * @subscribe_event : the mask of trigger points this link subscribes
 *
 * @trigger_id      : Unique ID provided to the triggering device
 */
struct cam_req_mgr_core_dev_link_setup {
	int32_t                    link_enable;
@@ -316,6 +319,7 @@ struct cam_req_mgr_core_dev_link_setup {
	enum cam_pipeline_delay    max_delay;
	struct cam_req_mgr_crm_cb *crm_cb;
	uint32_t                   subscribe_event;
	int32_t                    trigger_id;
};

/**