|
@@ -43,6 +43,9 @@ void cam_req_mgr_core_link_reset(struct cam_req_mgr_core_link *link)
|
|
|
link->in_msync_mode = false;
|
|
|
link->retry_cnt = 0;
|
|
|
link->is_shutdown = false;
|
|
|
+ link->initial_skip = true;
|
|
|
+ link->sof_timestamp = 0;
|
|
|
+ link->prev_sof_timestamp = 0;
|
|
|
}
|
|
|
|
|
|
void cam_req_mgr_handle_core_shutdown(void)
|
|
@@ -689,6 +692,19 @@ static int __cam_req_mgr_check_link_is_ready(struct cam_req_mgr_core_link *link,
|
|
|
traverse_data.validate_only = validate_only;
|
|
|
traverse_data.open_req_cnt = link->open_req_cnt;
|
|
|
|
|
|
+ /*
|
|
|
+ * Some no-sync mode requests are processed after link config,
|
|
|
+ * then process the sync mode requests after no-sync mode requests
|
|
|
+ * are handled, the initial_skip should be false when processing
|
|
|
+ * the sync mode requests.
|
|
|
+ */
|
|
|
+ if (link->initial_skip) {
|
|
|
+ CAM_DBG(CAM_CRM,
|
|
|
+ "Set initial_skip to false for link %x",
|
|
|
+ link->link_hdl);
|
|
|
+ link->initial_skip = false;
|
|
|
+ }
|
|
|
+
|
|
|
/*
|
|
|
* Traverse through all pd tables, if result is success,
|
|
|
* apply the settings
|
|
@@ -982,6 +998,7 @@ static int __cam_req_mgr_check_sync_req_is_ready(
|
|
|
int64_t req_id = 0;
|
|
|
int sync_slot_idx = 0, sync_rd_idx = 0, rc = 0;
|
|
|
int32_t sync_num_slots = 0;
|
|
|
+ uint64_t sync_frame_duration = 0;
|
|
|
bool ready = true, sync_ready = true;
|
|
|
|
|
|
if (!link->sync_link) {
|
|
@@ -997,6 +1014,57 @@ static int __cam_req_mgr_check_sync_req_is_ready(
|
|
|
"link_hdl %x req %lld frame_skip_flag %d ",
|
|
|
link->link_hdl, req_id, link->sync_link_sof_skip);
|
|
|
|
|
|
+ if (sync_link->initial_skip) {
|
|
|
+ link->initial_skip = false;
|
|
|
+ __cam_req_mgr_inject_delay(link->req.l_tbl, slot->idx);
|
|
|
+ CAM_DBG(CAM_CRM,
|
|
|
+ "sync link %x not streamed on",
|
|
|
+ sync_link->link_hdl);
|
|
|
+ return -EAGAIN;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (sync_link->prev_sof_timestamp)
|
|
|
+ sync_frame_duration = sync_link->sof_timestamp -
|
|
|
+ sync_link->prev_sof_timestamp;
|
|
|
+ else
|
|
|
+ sync_frame_duration = DEFAULT_FRAME_DURATION;
|
|
|
+
|
|
|
+ CAM_DBG(CAM_CRM,
|
|
|
+ "sync link %x last frame_duration is %d ns",
|
|
|
+ sync_link->link_hdl, sync_frame_duration);
|
|
|
+
|
|
|
+ if (link->initial_skip) {
|
|
|
+ link->initial_skip = false;
|
|
|
+
|
|
|
+ if ((link->sof_timestamp > sync_link->sof_timestamp) &&
|
|
|
+ (sync_link->sof_timestamp > 0) &&
|
|
|
+ (link->sof_timestamp - sync_link->sof_timestamp) <
|
|
|
+ (sync_frame_duration / 2)) {
|
|
|
+ /*
|
|
|
+ * If this frame sync with the previous frame of sync
|
|
|
+ * link, then we need to skip this frame, since the
|
|
|
+ * previous frame of sync link is also skipped.
|
|
|
+ */
|
|
|
+ __cam_req_mgr_inject_delay(link->req.l_tbl, slot->idx);
|
|
|
+ CAM_DBG(CAM_CRM,
|
|
|
+ "This frame sync with previous sync_link %x frame",
|
|
|
+ sync_link->link_hdl);
|
|
|
+ return -EAGAIN;
|
|
|
+ } else if (link->sof_timestamp <= sync_link->sof_timestamp) {
|
|
|
+ /*
|
|
|
+ * Sometimes, link receives the SOF event is eariler
|
|
|
+ * than sync link in IFE CSID side, but link's SOF
|
|
|
+ * event is processed later than sync link's, then
|
|
|
+ * we need to skip this SOF event since the sync
|
|
|
+ * link's SOF event is also skipped.
|
|
|
+ */
|
|
|
+ __cam_req_mgr_inject_delay(link->req.l_tbl, slot->idx);
|
|
|
+ CAM_DBG(CAM_CRM,
|
|
|
+ "The previous frame of sync link is skipped");
|
|
|
+ return -EAGAIN;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
if (sync_link->sync_link_sof_skip) {
|
|
|
CAM_DBG(CAM_REQ,
|
|
|
"No req applied on corresponding SOF on sync link: %x",
|
|
@@ -1097,10 +1165,11 @@ static int __cam_req_mgr_check_sync_req_is_ready(
|
|
|
*
|
|
|
*/
|
|
|
static int __cam_req_mgr_process_req(struct cam_req_mgr_core_link *link,
|
|
|
- uint32_t trigger)
|
|
|
+ struct cam_req_mgr_trigger_notify *trigger_data)
|
|
|
{
|
|
|
int rc = 0, idx;
|
|
|
int reset_step = 0;
|
|
|
+ uint32_t trigger = trigger_data->trigger;
|
|
|
struct cam_req_mgr_slot *slot = NULL;
|
|
|
struct cam_req_mgr_req_queue *in_q;
|
|
|
struct cam_req_mgr_core_session *session;
|
|
@@ -1139,6 +1208,13 @@ static int __cam_req_mgr_process_req(struct cam_req_mgr_core_link *link,
|
|
|
}
|
|
|
|
|
|
if (trigger == CAM_TRIGGER_POINT_SOF) {
|
|
|
+ /*
|
|
|
+ * Update the timestamp in session lock protection
|
|
|
+ * to avoid timing issue.
|
|
|
+ */
|
|
|
+ link->prev_sof_timestamp = link->sof_timestamp;
|
|
|
+ link->sof_timestamp = trigger_data->sof_timestamp_val;
|
|
|
+
|
|
|
if (link->trigger_mask) {
|
|
|
CAM_ERR_RATE_LIMIT(CAM_CRM,
|
|
|
"Applying for last EOF fails");
|
|
@@ -2225,7 +2301,7 @@ static int cam_req_mgr_process_trigger(void *priv, void *data)
|
|
|
__cam_req_mgr_inc_idx(&in_q->rd_idx, 1, in_q->num_slots);
|
|
|
}
|
|
|
|
|
|
- rc = __cam_req_mgr_process_req(link, trigger_data->trigger);
|
|
|
+ rc = __cam_req_mgr_process_req(link, trigger_data);
|
|
|
|
|
|
release_lock:
|
|
|
mutex_unlock(&link->req.lock);
|
|
@@ -2456,6 +2532,7 @@ static int cam_req_mgr_cb_notify_trigger(
|
|
|
notify_trigger->link_hdl = trigger_data->link_hdl;
|
|
|
notify_trigger->dev_hdl = trigger_data->dev_hdl;
|
|
|
notify_trigger->trigger = trigger_data->trigger;
|
|
|
+ notify_trigger->sof_timestamp_val = trigger_data->sof_timestamp_val;
|
|
|
task->process_cb = &cam_req_mgr_process_trigger;
|
|
|
rc = cam_req_mgr_workq_enqueue_task(task, link, CRM_TASK_PRIORITY_0);
|
|
|
|
|
@@ -3215,8 +3292,6 @@ int cam_req_mgr_sync_config(
|
|
|
|
|
|
link1->is_master = false;
|
|
|
link2->is_master = false;
|
|
|
- link1->initial_skip = false;
|
|
|
- link2->initial_skip = false;
|
|
|
|
|
|
link1->in_msync_mode = false;
|
|
|
link2->in_msync_mode = false;
|
|
@@ -3227,6 +3302,16 @@ int cam_req_mgr_sync_config(
|
|
|
link1->sync_link = link2;
|
|
|
link2->sync_link = link1;
|
|
|
__cam_req_mgr_set_master_link(link1, link2);
|
|
|
+ } else {
|
|
|
+ /*
|
|
|
+ * Reset below info after the mode is configured
|
|
|
+ * to NO-SYNC mode since they may be overridden
|
|
|
+ * if the sync config is invoked after SOF comes.
|
|
|
+ */
|
|
|
+ link1->initial_skip = true;
|
|
|
+ link2->initial_skip = true;
|
|
|
+ link1->sof_timestamp = 0;
|
|
|
+ link2->sof_timestamp = 0;
|
|
|
}
|
|
|
|
|
|
cam_session->sync_mode = sync_info->sync_mode;
|