|
@@ -93,6 +93,8 @@ void cam_req_mgr_core_link_reset(struct cam_req_mgr_core_link *link)
|
|
|
link->is_sending_req = false;
|
|
|
atomic_set(&link->eof_event_cnt, 0);
|
|
|
link->cont_empty_slots = 0;
|
|
|
+ link->is_shdr = false;
|
|
|
+ link->wait_for_dual_trigger = false;
|
|
|
__cam_req_mgr_reset_apply_data(link);
|
|
|
__cam_req_mgr_reset_state_monitor_array(link);
|
|
|
|
|
@@ -1182,6 +1184,31 @@ static int __cam_req_mgr_move_to_next_req_slot(
|
|
|
return rc;
|
|
|
}
|
|
|
|
|
|
+static void cam_req_mgr_reconfigure_link(struct cam_req_mgr_core_link *link,
|
|
|
+ struct cam_req_mgr_connected_device *device, bool is_active)
|
|
|
+{
|
|
|
+ int i = 0;
|
|
|
+ struct cam_req_mgr_connected_device *dev = NULL;
|
|
|
+ struct cam_req_mgr_req_tbl *tbl = NULL;
|
|
|
+
|
|
|
+ for (i = 0; i < link->num_devs; i++) {
|
|
|
+ dev = &link->l_dev[i];
|
|
|
+
|
|
|
+ if (dev->dev_info.trigger_on && !dev->dev_info.is_shdr_master) {
|
|
|
+ dev->is_active = is_active;
|
|
|
+ tbl = dev->pd_tbl;
|
|
|
+
|
|
|
+ if (is_active) {
|
|
|
+ tbl->dev_mask |= (1 << dev->dev_bit);
|
|
|
+ } else {
|
|
|
+ tbl->dev_mask &= ~(1 << dev->dev_bit);
|
|
|
+ dev->dev_info.mode_switch_req = 0;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
/**
|
|
|
* __cam_req_mgr_send_req()
|
|
|
*
|
|
@@ -1206,6 +1233,7 @@ static int __cam_req_mgr_send_req(struct cam_req_mgr_core_link *link,
|
|
|
struct cam_req_mgr_tbl_slot *slot = NULL;
|
|
|
struct cam_req_mgr_apply *apply_data = NULL;
|
|
|
struct cam_req_mgr_state_monitor state;
|
|
|
+ bool prev_dual_trigger_status = false;
|
|
|
|
|
|
apply_req.link_hdl = link->link_hdl;
|
|
|
apply_req.report_if_bubble = 0;
|
|
@@ -1252,6 +1280,12 @@ static int __cam_req_mgr_send_req(struct cam_req_mgr_core_link *link,
|
|
|
continue;
|
|
|
}
|
|
|
|
|
|
+ if (!dev->is_active) {
|
|
|
+ CAM_DBG(CAM_CRM, "Device %x linked with link %x is not active",
|
|
|
+ dev->dev_hdl, link->link_hdl);
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+
|
|
|
for (j = 0; j < slot->ops.num_dev; j++) {
|
|
|
if (dev->dev_hdl == slot->ops.dev_hdl[j]) {
|
|
|
found = true;
|
|
@@ -1345,7 +1379,7 @@ static int __cam_req_mgr_send_req(struct cam_req_mgr_core_link *link,
|
|
|
/* For regular send requests */
|
|
|
for (i = 0; i < link->num_devs; i++) {
|
|
|
dev = &link->l_dev[i];
|
|
|
- if (dev) {
|
|
|
+ if (dev && dev->is_active) {
|
|
|
pd = dev->dev_info.p_delay;
|
|
|
if (pd >= CAM_PIPELINE_DELAY_MAX) {
|
|
|
CAM_WARN(CAM_CRM, "pd %d greater than max",
|
|
@@ -1356,6 +1390,11 @@ static int __cam_req_mgr_send_req(struct cam_req_mgr_core_link *link,
|
|
|
if (!(dev->dev_info.trigger & trigger))
|
|
|
continue;
|
|
|
|
|
|
+ if (dev->dev_info.trigger_on && !dev->dev_info.is_shdr_master &&
|
|
|
+ dev->dev_info.mode_switch_req == apply_data[pd].req_id &&
|
|
|
+ link->wait_for_dual_trigger)
|
|
|
+ continue;
|
|
|
+
|
|
|
if (apply_data[pd].skip_idx ||
|
|
|
(apply_data[pd].req_id < 0)) {
|
|
|
CAM_DBG(CAM_CRM,
|
|
@@ -1421,6 +1460,7 @@ static int __cam_req_mgr_send_req(struct cam_req_mgr_core_link *link,
|
|
|
continue;
|
|
|
|
|
|
apply_req.trigger_point = trigger;
|
|
|
+ apply_req.dual_trigger_status = CAM_REQ_DUAL_TRIGGER_NONE;
|
|
|
CAM_DBG(CAM_REQ,
|
|
|
"SEND: link_hdl %x dev %s pd %d req_id %lld",
|
|
|
link->link_hdl, dev->dev_info.name,
|
|
@@ -1440,6 +1480,19 @@ static int __cam_req_mgr_send_req(struct cam_req_mgr_core_link *link,
|
|
|
state.frame_id = -1;
|
|
|
__cam_req_mgr_update_state_monitor_array(link, &state);
|
|
|
|
|
|
+ if (link->is_shdr && dev->dev_info.is_shdr_master) {
|
|
|
+ prev_dual_trigger_status = link->wait_for_dual_trigger;
|
|
|
+ if (apply_req.dual_trigger_status ==
|
|
|
+ CAM_REQ_DUAL_TRIGGER_TWO_EXPOSURE)
|
|
|
+ link->wait_for_dual_trigger = true;
|
|
|
+ else if (apply_req.dual_trigger_status ==
|
|
|
+ CAM_REQ_DUAL_TRIGGER_ONE_EXPOSURE)
|
|
|
+ link->wait_for_dual_trigger = false;
|
|
|
+ if (prev_dual_trigger_status != link->wait_for_dual_trigger)
|
|
|
+ cam_req_mgr_reconfigure_link(
|
|
|
+ link, dev, link->wait_for_dual_trigger);
|
|
|
+ }
|
|
|
+
|
|
|
if (pd == link->min_delay)
|
|
|
req_applied_to_min_pd = apply_req.request_id;
|
|
|
|
|
@@ -3307,6 +3360,38 @@ end:
|
|
|
return rc;
|
|
|
}
|
|
|
|
|
|
+static void cam_req_mgr_handle_exposure_change(
|
|
|
+ struct cam_req_mgr_core_link *link,
|
|
|
+ struct cam_req_mgr_add_request *add_req)
|
|
|
+{
|
|
|
+ int i = 0;
|
|
|
+ struct cam_req_mgr_connected_device *device = NULL;
|
|
|
+
|
|
|
+ if (add_req->num_exp == CAM_REQ_DUAL_TRIGGER_TWO_EXPOSURE &&
|
|
|
+ !link->wait_for_dual_trigger) {
|
|
|
+ for (i = 0; i < link->num_devs; i++) {
|
|
|
+ device = &link->l_dev[i];
|
|
|
+
|
|
|
+ if (!device->dev_info.trigger_on || device->dev_info.is_shdr_master)
|
|
|
+ continue;
|
|
|
+
|
|
|
+ device->is_active = true;
|
|
|
+ device->dev_info.mode_switch_req = 0;
|
|
|
+ }
|
|
|
+ } else if (add_req->num_exp == CAM_REQ_DUAL_TRIGGER_ONE_EXPOSURE &&
|
|
|
+ link->wait_for_dual_trigger) {
|
|
|
+
|
|
|
+ for (i = 0; i < link->num_devs; i++) {
|
|
|
+ device = &link->l_dev[i];
|
|
|
+
|
|
|
+ if (!device->dev_info.trigger_on || device->dev_info.is_shdr_master)
|
|
|
+ continue;
|
|
|
+
|
|
|
+ device->dev_info.mode_switch_req = add_req->req_id;
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
/**
|
|
|
* cam_req_mgr_process_add_req()
|
|
|
*
|
|
@@ -3498,8 +3583,30 @@ int cam_req_mgr_process_add_req(void *priv, void *data)
|
|
|
state.frame_id = -1;
|
|
|
__cam_req_mgr_update_state_monitor_array(link, &state);
|
|
|
}
|
|
|
- mutex_unlock(&link->req.lock);
|
|
|
|
|
|
+ if (!link->is_shdr && !device->dev_info.trigger_on) {
|
|
|
+ mutex_unlock(&link->req.lock);
|
|
|
+ return rc;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (!device->is_active && !device->dev_info.is_shdr_master &&
|
|
|
+ !link->wait_for_dual_trigger) {
|
|
|
+ device->is_active = true;
|
|
|
+ if (slot->req_ready_map == tbl->dev_mask) {
|
|
|
+ CAM_DBG(CAM_REQ,
|
|
|
+ "link 0x%x idx %d req_id %lld pd %d SLOT READY",
|
|
|
+ link->link_hdl, idx, add_req->req_id, tbl->pd);
|
|
|
+ slot->state = CRM_REQ_STATE_READY;
|
|
|
+ }
|
|
|
+
|
|
|
+ mutex_unlock(&link->req.lock);
|
|
|
+ goto end;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (device->dev_info.is_shdr_master)
|
|
|
+ cam_req_mgr_handle_exposure_change(link, add_req);
|
|
|
+
|
|
|
+ mutex_unlock(&link->req.lock);
|
|
|
end:
|
|
|
return rc;
|
|
|
}
|
|
@@ -4206,8 +4313,6 @@ end:
|
|
|
return rc;
|
|
|
}
|
|
|
|
|
|
-
|
|
|
-
|
|
|
/**
|
|
|
* cam_req_mgr_cb_notify_trigger()
|
|
|
*
|
|
@@ -4290,7 +4395,7 @@ static int cam_req_mgr_cb_notify_trigger(
|
|
|
(trigger == CAM_TRIGGER_POINT_SOF))
|
|
|
link->watchdog->pause_timer = false;
|
|
|
|
|
|
- if (link->dual_trigger) {
|
|
|
+ if (link->dual_trigger && link->wait_for_dual_trigger) {
|
|
|
if ((trigger_id >= 0) && (trigger_id <
|
|
|
CAM_REQ_MGR_MAX_TRIGGERS)) {
|
|
|
link->trigger_cnt[trigger_id][trigger]++;
|
|
@@ -4364,11 +4469,13 @@ static int __cam_req_mgr_setup_link_info(struct cam_req_mgr_core_link *link,
|
|
|
{
|
|
|
int rc = 0, i = 0, num_devices = 0;
|
|
|
struct cam_req_mgr_core_dev_link_setup link_data;
|
|
|
- struct cam_req_mgr_connected_device *dev;
|
|
|
+ struct cam_req_mgr_connected_device *dev, *master_dev = NULL, *tmp_dev;
|
|
|
struct cam_req_mgr_req_tbl *pd_tbl;
|
|
|
enum cam_pipeline_delay max_delay;
|
|
|
enum cam_modeswitch_delay max_modeswitch;
|
|
|
uint32_t num_trigger_devices = 0;
|
|
|
+ int32_t master_dev_idx = -1;
|
|
|
+
|
|
|
if (link_info->version == VERSION_1) {
|
|
|
if (link_info->u.link_info_v1.num_devices >
|
|
|
CAM_REQ_MGR_MAX_HANDLES)
|
|
@@ -4419,6 +4526,11 @@ static int __cam_req_mgr_setup_link_info(struct cam_req_mgr_core_link *link,
|
|
|
dev->dev_info.dev_hdl = dev->dev_hdl;
|
|
|
rc = dev->ops->get_dev_info(&dev->dev_info);
|
|
|
|
|
|
+ if (dev->dev_info.is_shdr_master) {
|
|
|
+ master_dev = dev;
|
|
|
+ master_dev_idx = i;
|
|
|
+ }
|
|
|
+
|
|
|
trace_cam_req_mgr_connect_device(link, &dev->dev_info);
|
|
|
if (link_info->version == VERSION_1)
|
|
|
CAM_DBG(CAM_CRM,
|
|
@@ -4467,8 +4579,13 @@ static int __cam_req_mgr_setup_link_info(struct cam_req_mgr_core_link *link,
|
|
|
max_modeswitch = dev->dev_info.m_delay;
|
|
|
}
|
|
|
|
|
|
- if (dev->dev_info.trigger_on)
|
|
|
+ if (dev->dev_info.trigger_on) {
|
|
|
num_trigger_devices++;
|
|
|
+ if (dev->dev_info.is_shdr)
|
|
|
+ link->is_shdr = true;
|
|
|
+ }
|
|
|
+
|
|
|
+ dev->is_active = true;
|
|
|
}
|
|
|
|
|
|
if (num_trigger_devices > CAM_REQ_MGR_MAX_TRIGGERS) {
|
|
@@ -4484,8 +4601,26 @@ 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.mode_switch_max_delay = max_modeswitch;
|
|
|
- if (num_trigger_devices == CAM_REQ_MGR_MAX_TRIGGERS)
|
|
|
+ if (num_trigger_devices == CAM_REQ_MGR_MAX_TRIGGERS) {
|
|
|
link->dual_trigger = true;
|
|
|
+ link->wait_for_dual_trigger = true;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (link->dual_trigger && master_dev) {
|
|
|
+ for (i = 0; i < num_devices; i++) {
|
|
|
+ dev = &link->l_dev[i];
|
|
|
+
|
|
|
+ if (dev->dev_info.trigger_on) {
|
|
|
+ if (dev->dev_hdl == master_dev->dev_hdl)
|
|
|
+ continue;
|
|
|
+ if (master_dev_idx < i) {
|
|
|
+ tmp_dev = master_dev;
|
|
|
+ master_dev = dev;
|
|
|
+ dev = tmp_dev;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
|
|
|
num_trigger_devices = 0;
|
|
|
for (i = 0; i < num_devices; i++) {
|