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 <kartanan@codeaurora.org>
Dieser Commit ist enthalten in:
Karthik Anantha Ram
2020-03-11 15:44:46 -07:00
Ursprung 5619d4e93e
Commit b7a494a130
5 geänderte Dateien mit 95 neuen und 3 gelöschten Zeilen

Datei anzeigen

@@ -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(&notify);
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;
}

Datei anzeigen

@@ -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;
};
/**

Datei anzeigen

@@ -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);

Datei anzeigen

@@ -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];
};
/**

Datei anzeigen

@@ -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;
};
/**