Browse Source

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: Karthik Anantha Ram <[email protected]>
Karthik Anantha Ram 5 years ago
parent
commit
b7a494a130

+ 6 - 0
drivers/cam_isp/cam_isp_context.c

@@ -1313,6 +1313,7 @@ static int __cam_isp_ctx_notify_sof_in_activated_state(
 			notify.trigger = CAM_TRIGGER_POINT_SOF;
 			notify.trigger = CAM_TRIGGER_POINT_SOF;
 			notify.req_id = ctx_isp->req_info.last_bufdone_req_id;
 			notify.req_id = ctx_isp->req_info.last_bufdone_req_id;
 			notify.sof_timestamp_val = ctx_isp->sof_timestamp_val;
 			notify.sof_timestamp_val = ctx_isp->sof_timestamp_val;
+			notify.trigger_id = ctx_isp->trigger_id;
 
 
 			ctx->ctx_crm_intf->notify_trigger(&notify);
 			ctx->ctx_crm_intf->notify_trigger(&notify);
 			CAM_DBG(CAM_ISP, "Notify CRM  SOF frame %lld ctx %u",
 			CAM_DBG(CAM_ISP, "Notify CRM  SOF frame %lld ctx %u",
@@ -4517,6 +4518,7 @@ static int __cam_isp_ctx_link_in_acquired(struct cam_context *ctx,
 	ctx->link_hdl = link->link_hdl;
 	ctx->link_hdl = link->link_hdl;
 	ctx->ctx_crm_intf = link->crm_cb;
 	ctx->ctx_crm_intf = link->crm_cb;
 	ctx_isp->subscribe_event = link->subscribe_event;
 	ctx_isp->subscribe_event = link->subscribe_event;
+	ctx_isp->trigger_id = link->trigger_id;
 
 
 	/* change state only if we had the init config */
 	/* change state only if we had the init config */
 	if (ctx_isp->init_received) {
 	if (ctx_isp->init_received) {
@@ -4533,9 +4535,12 @@ static int __cam_isp_ctx_unlink_in_acquired(struct cam_context *ctx,
 	struct cam_req_mgr_core_dev_link_setup *unlink)
 	struct cam_req_mgr_core_dev_link_setup *unlink)
 {
 {
 	int rc = 0;
 	int rc = 0;
+	struct cam_isp_context *ctx_isp =
+		(struct cam_isp_context *) ctx->ctx_priv;
 
 
 	ctx->link_hdl = -1;
 	ctx->link_hdl = -1;
 	ctx->ctx_crm_intf = NULL;
 	ctx->ctx_crm_intf = NULL;
+	ctx_isp->trigger_id = -1;
 
 
 	return rc;
 	return rc;
 }
 }
@@ -4550,6 +4555,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->dev_id = CAM_REQ_MGR_DEVICE_IFE;
 	dev_info->p_delay = 1;
 	dev_info->p_delay = 1;
 	dev_info->trigger = CAM_TRIGGER_POINT_SOF;
 	dev_info->trigger = CAM_TRIGGER_POINT_SOF;
+	dev_info->trigger_on = true;
 
 
 	return rc;
 	return rc;
 }
 }

+ 2 - 0
drivers/cam_isp/cam_isp_context.h

@@ -258,6 +258,7 @@ struct cam_isp_context_event_record {
  * @rxd_epoch:                 Indicate whether epoch has been received. Used to
  * @rxd_epoch:                 Indicate whether epoch has been received. Used to
  *                             decide whether to apply request in offline ctx
  *                             decide whether to apply request in offline ctx
  * @workq:                     Worker thread for offline ife
  * @workq:                     Worker thread for offline ife
+ * @trigger_id:                ID provided by CRM for each ctx on the link
  *
  *
  */
  */
 struct cam_isp_context {
 struct cam_isp_context {
@@ -300,6 +301,7 @@ struct cam_isp_context {
 	uint32_t                              isp_device_type;
 	uint32_t                              isp_device_type;
 	atomic_t                              rxd_epoch;
 	atomic_t                              rxd_epoch;
 	struct cam_req_mgr_core_workq        *workq;
 	struct cam_req_mgr_core_workq        *workq;
+	int32_t                               trigger_id;
 };
 };
 
 
 /**
 /**

+ 74 - 3
drivers/cam_req_mgr/cam_req_mgr_core.c

@@ -40,6 +40,9 @@ void cam_req_mgr_core_link_reset(struct cam_req_mgr_core_link *link)
 	link->open_req_cnt = 0;
 	link->open_req_cnt = 0;
 	link->last_flush_id = 0;
 	link->last_flush_id = 0;
 	link->initial_sync_req = -1;
 	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->in_msync_mode = false;
 	link->retry_cnt = 0;
 	link->retry_cnt = 0;
 	link->is_shutdown = false;
 	link->is_shutdown = false;
@@ -2760,6 +2763,33 @@ end:
 	return rc;
 	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()
  * cam_req_mgr_cb_notify_timer()
  *
  *
@@ -2878,7 +2908,7 @@ end:
 static int cam_req_mgr_cb_notify_trigger(
 static int cam_req_mgr_cb_notify_trigger(
 	struct cam_req_mgr_trigger_notify *trigger_data)
 	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 crm_workq_task           *task = NULL;
 	struct cam_req_mgr_core_link    *link = NULL;
 	struct cam_req_mgr_core_link    *link = NULL;
 	struct cam_req_mgr_trigger_notify   *notify_trigger;
 	struct cam_req_mgr_trigger_notify   *notify_trigger;
@@ -2898,6 +2928,8 @@ static int cam_req_mgr_cb_notify_trigger(
 		goto end;
 		goto end;
 	}
 	}
 
 
+	trigger_id = trigger_data->trigger_id;
+
 	spin_lock_bh(&link->link_state_spin_lock);
 	spin_lock_bh(&link->link_state_spin_lock);
 	if (link->state < CAM_CRM_LINK_STATE_READY) {
 	if (link->state < CAM_CRM_LINK_STATE_READY) {
 		CAM_WARN(CAM_CRM, "invalid link state:%d", link->state);
 		CAM_WARN(CAM_CRM, "invalid link state:%d", link->state);
@@ -2909,6 +2941,23 @@ static int cam_req_mgr_cb_notify_trigger(
 	if ((link->watchdog) && (link->watchdog->pause_timer))
 	if ((link->watchdog) && (link->watchdog->pause_timer))
 		link->watchdog->pause_timer = false;
 		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);
 	crm_timer_reset(link->watchdog);
 	spin_unlock_bh(&link->link_state_spin_lock);
 	spin_unlock_bh(&link->link_state_spin_lock);
 
 
@@ -2963,16 +3012,18 @@ static int __cam_req_mgr_setup_link_info(struct cam_req_mgr_core_link *link,
 	struct cam_req_mgr_req_tbl             *pd_tbl;
 	struct cam_req_mgr_req_tbl             *pd_tbl;
 	enum cam_pipeline_delay                 max_delay;
 	enum cam_pipeline_delay                 max_delay;
 	uint32_t                                subscribe_event = 0;
 	uint32_t                                subscribe_event = 0;
+	uint32_t num_trigger_devices = 0;
 	if (link_info->version == VERSION_1) {
 	if (link_info->version == VERSION_1) {
 		if (link_info->u.link_info_v1.num_devices >
 		if (link_info->u.link_info_v1.num_devices >
 			CAM_REQ_MGR_MAX_HANDLES)
 			CAM_REQ_MGR_MAX_HANDLES)
 			return -EPERM;
 			return -EPERM;
-		}
+	}
 	else if (link_info->version == VERSION_2) {
 	else if (link_info->version == VERSION_2) {
 		if (link_info->u.link_info_v2.num_devices >
 		if (link_info->u.link_info_v2.num_devices >
 			CAM_REQ_MGR_MAX_HANDLES_V2)
 			CAM_REQ_MGR_MAX_HANDLES_V2)
 			return -EPERM;
 			return -EPERM;
-		}
+	}
+
 	mutex_init(&link->req.lock);
 	mutex_init(&link->req.lock);
 	CAM_DBG(CAM_CRM, "LOCK_DBG in_q lock %pK", &link->req.lock);
 	CAM_DBG(CAM_CRM, "LOCK_DBG in_q lock %pK", &link->req.lock);
 	link->req.num_tbl = 0;
 	link->req.num_tbl = 0;
@@ -3052,6 +3103,17 @@ static int __cam_req_mgr_setup_link_info(struct cam_req_mgr_core_link *link,
 
 
 			subscribe_event |= (uint32_t)dev->dev_info.trigger;
 			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;
 	link->subscribe_event = subscribe_event;
@@ -3060,7 +3122,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.crm_cb = &cam_req_mgr_ops;
 	link_data.max_delay = max_delay;
 	link_data.max_delay = max_delay;
 	link_data.subscribe_event = subscribe_event;
 	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++) {
 	for (i = 0; i < num_devices; i++) {
 		dev = &link->l_dev[i];
 		dev = &link->l_dev[i];
 
 
@@ -3100,6 +3165,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",
 		CAM_DBG(CAM_CRM, "dev_bit %u name %s pd %u mask %d",
 			dev->dev_bit, dev->dev_info.name, pd_tbl->pd,
 			dev->dev_bit, dev->dev_info.name, pd_tbl->pd,
 			pd_tbl->dev_mask);
 			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 */
 		/* Communicate with dev to establish the link */
 		dev->ops->link_setup(&link_data);
 		dev->ops->link_setup(&link_data);
 
 

+ 7 - 0
drivers/cam_req_mgr/cam_req_mgr_core.h

@@ -37,6 +37,7 @@
 
 
 #define VERSION_1  1
 #define VERSION_1  1
 #define VERSION_2  2
 #define VERSION_2  2
+#define CAM_REQ_MGR_MAX_TRIGGERS   2
 
 
 /**
 /**
  * enum crm_workq_task_type
  * enum crm_workq_task_type
@@ -344,6 +345,9 @@ struct cam_req_mgr_connected_device {
  *                         as part of shutdown.
  *                         as part of shutdown.
  * @sof_timestamp_value  : SOF timestamp value
  * @sof_timestamp_value  : SOF timestamp value
  * @prev_sof_timestamp   : Previous 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 {
 struct cam_req_mgr_core_link {
 	int32_t                              link_hdl;
 	int32_t                              link_hdl;
@@ -374,6 +378,9 @@ struct cam_req_mgr_core_link {
 	bool                                 is_shutdown;
 	bool                                 is_shutdown;
 	uint64_t                             sof_timestamp;
 	uint64_t                             sof_timestamp;
 	uint64_t                             prev_sof_timestamp;
 	uint64_t                             prev_sof_timestamp;
+	bool                                 dual_trigger;
+	uint32_t    trigger_cnt[CAM_REQ_MGR_MAX_TRIGGERS];
+
 };
 };
 
 
 /**
 /**

+ 6 - 0
drivers/cam_req_mgr/cam_req_mgr_interface.h

@@ -210,6 +210,7 @@ enum cam_req_mgr_link_evt_type {
  *             only to the devices which subscribe to this point.
  *             only to the devices which subscribe to this point.
  * @sof_timestamp_val: Captured time stamp value at sof hw event
  * @sof_timestamp_val: Captured time stamp value at sof hw event
  * @req_id   : req id which returned buf_done
  * @req_id   : req id which returned buf_done
+ * @trigger_id: ID to differentiate between the trigger devices
  */
  */
 struct cam_req_mgr_trigger_notify {
 struct cam_req_mgr_trigger_notify {
 	int32_t  link_hdl;
 	int32_t  link_hdl;
@@ -218,6 +219,7 @@ struct cam_req_mgr_trigger_notify {
 	uint32_t trigger;
 	uint32_t trigger;
 	uint64_t sof_timestamp_val;
 	uint64_t sof_timestamp_val;
 	uint64_t req_id;
 	uint64_t req_id;
+	int32_t  trigger_id;
 };
 };
 
 
 /**
 /**
@@ -286,6 +288,7 @@ struct cam_req_mgr_notify_stop {
  * @dev_id  : device id info
  * @dev_id  : device id info
  * @p_delay : delay between time settings applied and take effect
  * @p_delay : delay between time settings applied and take effect
  * @trigger : Trigger point for the client
  * @trigger : Trigger point for the client
+ * @trigger_on : This device provides trigger
  */
  */
 struct cam_req_mgr_device_info {
 struct cam_req_mgr_device_info {
 	int32_t                     dev_hdl;
 	int32_t                     dev_hdl;
@@ -293,6 +296,7 @@ struct cam_req_mgr_device_info {
 	enum cam_req_mgr_device_id  dev_id;
 	enum cam_req_mgr_device_id  dev_id;
 	enum cam_pipeline_delay     p_delay;
 	enum cam_pipeline_delay     p_delay;
 	uint32_t                    trigger;
 	uint32_t                    trigger;
+	bool                        trigger_on;
 };
 };
 
 
 /**
 /**
@@ -303,6 +307,7 @@ struct cam_req_mgr_device_info {
  * @max_delay       : max pipeline delay on this link
  * @max_delay       : max pipeline delay on this link
  * @crm_cb          : callback funcs to communicate with req mgr
  * @crm_cb          : callback funcs to communicate with req mgr
  * @subscribe_event : the mask of trigger points this link subscribes
  * @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 {
 struct cam_req_mgr_core_dev_link_setup {
 	int32_t                    link_enable;
 	int32_t                    link_enable;
@@ -311,6 +316,7 @@ struct cam_req_mgr_core_dev_link_setup {
 	enum cam_pipeline_delay    max_delay;
 	enum cam_pipeline_delay    max_delay;
 	struct cam_req_mgr_crm_cb *crm_cb;
 	struct cam_req_mgr_crm_cb *crm_cb;
 	uint32_t                   subscribe_event;
 	uint32_t                   subscribe_event;
+	int32_t                    trigger_id;
 };
 };
 
 
 /**
 /**