From b7a494a1309b645beed787ce054cebe5ff0d1f6f Mon Sep 17 00:00:00 2001 From: Karthik Anantha Ram Date: Wed, 11 Mar 2020 15:44:46 -0700 Subject: [PATCH] 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 --- drivers/cam_isp/cam_isp_context.c | 6 ++ drivers/cam_isp/cam_isp_context.h | 2 + drivers/cam_req_mgr/cam_req_mgr_core.c | 77 ++++++++++++++++++++- drivers/cam_req_mgr/cam_req_mgr_core.h | 7 ++ drivers/cam_req_mgr/cam_req_mgr_interface.h | 6 ++ 5 files changed, 95 insertions(+), 3 deletions(-) diff --git a/drivers/cam_isp/cam_isp_context.c b/drivers/cam_isp/cam_isp_context.c index 5843b6be10..596a4f3071 100644 --- a/drivers/cam_isp/cam_isp_context.c +++ b/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.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(¬ify); 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->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) { @@ -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) { 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; } @@ -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->p_delay = 1; dev_info->trigger = CAM_TRIGGER_POINT_SOF; + dev_info->trigger_on = true; return rc; } diff --git a/drivers/cam_isp/cam_isp_context.h b/drivers/cam_isp/cam_isp_context.h index ba49f534e0..2baabe8b24 100644 --- a/drivers/cam_isp/cam_isp_context.h +++ b/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 * 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 { @@ -300,6 +301,7 @@ struct cam_isp_context { uint32_t isp_device_type; atomic_t rxd_epoch; struct cam_req_mgr_core_workq *workq; + int32_t trigger_id; }; /** diff --git a/drivers/cam_req_mgr/cam_req_mgr_core.c b/drivers/cam_req_mgr/cam_req_mgr_core.c index b5f10a232b..bc4ed38648 100644 --- a/drivers/cam_req_mgr/cam_req_mgr_core.c +++ b/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->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; @@ -2760,6 +2763,33 @@ end: 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() * @@ -2878,7 +2908,7 @@ end: 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; @@ -2898,6 +2928,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); @@ -2909,6 +2941,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); @@ -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; 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) return -EPERM; - } + } else if (link_info->version == VERSION_2) { if (link_info->u.link_info_v2.num_devices > 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; @@ -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; } + + 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; @@ -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.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]; @@ -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", 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); diff --git a/drivers/cam_req_mgr/cam_req_mgr_core.h b/drivers/cam_req_mgr/cam_req_mgr_core.h index 8324e706cb..c364128e60 100644 --- a/drivers/cam_req_mgr/cam_req_mgr_core.h +++ b/drivers/cam_req_mgr/cam_req_mgr_core.h @@ -37,6 +37,7 @@ #define VERSION_1 1 #define VERSION_2 2 +#define CAM_REQ_MGR_MAX_TRIGGERS 2 /** * enum crm_workq_task_type @@ -344,6 +345,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; @@ -374,6 +378,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]; + }; /** diff --git a/drivers/cam_req_mgr/cam_req_mgr_interface.h b/drivers/cam_req_mgr/cam_req_mgr_interface.h index e2e69c3cd2..01e3f7abf0 100644 --- a/drivers/cam_req_mgr/cam_req_mgr_interface.h +++ b/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. * @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; @@ -218,6 +219,7 @@ struct cam_req_mgr_trigger_notify { uint32_t trigger; uint64_t sof_timestamp_val; uint64_t req_id; + int32_t trigger_id; }; /** @@ -286,6 +288,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; @@ -293,6 +296,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; }; /** @@ -303,6 +307,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; @@ -311,6 +316,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; }; /**