msm: camera: reqmgr: Add EOF trigger notification
Add method in ISP to notify SOF/EOF that is subscribed by camera
modules to CRM, CRM will send apply command to modules as the
subscribe mask.
CRs-fixed: 2096454
Change-Id: I6ad7d77f091386d3be91c670da75e1cd15e41ecd
Signed-off-by: Pavan Kumar Chilamkurthi <pchilamk@codeaurora.org>
Signed-off-by: Junzhe Zou <jnzhezou@codeaurora.org>
diff --git a/drivers/media/platform/msm/camera/cam_req_mgr/cam_req_mgr_core.c b/drivers/media/platform/msm/camera/cam_req_mgr/cam_req_mgr_core.c
index efdda4f..986cc51 100644
--- a/drivers/media/platform/msm/camera/cam_req_mgr/cam_req_mgr_core.c
+++ b/drivers/media/platform/msm/camera/cam_req_mgr/cam_req_mgr_core.c
@@ -365,7 +365,7 @@
*
*/
static int __cam_req_mgr_send_req(struct cam_req_mgr_core_link *link,
- struct cam_req_mgr_req_queue *in_q)
+ struct cam_req_mgr_req_queue *in_q, uint32_t trigger)
{
int rc = 0, pd, i, idx;
struct cam_req_mgr_connected_device *dev = NULL;
@@ -391,6 +391,9 @@
link->req.apply_data[pd].req_id);
continue;
}
+ if (!(dev->dev_info.trigger & trigger))
+ continue;
+
apply_req.dev_hdl = dev->dev_hdl;
apply_req.request_id =
link->req.apply_data[pd].req_id;
@@ -400,6 +403,7 @@
trace_cam_req_mgr_apply_request(link, &apply_req, dev);
+ apply_req.trigger_point = trigger;
CAM_DBG(CAM_CRM, "SEND: pd %d req_id %lld",
pd, apply_req.request_id);
if (dev->ops && dev->ops->apply_req) {
@@ -488,7 +492,8 @@
* @return : 0 for success, negative for failure
*
*/
-static int __cam_req_mgr_process_req(struct cam_req_mgr_core_link *link)
+static int __cam_req_mgr_process_req(struct cam_req_mgr_core_link *link,
+ uint32_t trigger)
{
int rc = 0, idx;
struct cam_req_mgr_slot *slot = NULL;
@@ -499,7 +504,7 @@
session = (struct cam_req_mgr_core_session *)link->parent;
/*
- * 1. Check if new read index,
+ * Check if new read index,
* - if in pending state, traverse again to complete
* transaction of this read index.
* - if in applied_state, somthign wrong.
@@ -514,58 +519,70 @@
return 0;
}
- rc = __cam_req_mgr_check_link_is_ready(link, slot->idx);
- if (rc >= 0) {
- rc = __cam_req_mgr_send_req(link, link->req.in_q);
- if (rc < 0) {
- /* Apply req failed retry at next sof */
- slot->status = CRM_SLOT_STATUS_REQ_PENDING;
- } else {
- slot->status = CRM_SLOT_STATUS_REQ_APPLIED;
+ if (trigger != CAM_TRIGGER_POINT_SOF &&
+ trigger != CAM_TRIGGER_POINT_EOF)
+ return rc;
+ if (trigger == CAM_TRIGGER_POINT_SOF) {
+ if (!link->trigger_mask) {
+ CAM_ERR(CAM_CRM, "Applying for last EOF fails");
+ return -EINVAL;
+ }
+ rc = __cam_req_mgr_check_link_is_ready(link, slot->idx);
+ if (rc < 0) {
+
+ /* If traverse result is not success, then some devices
+ * are not ready with packet for the asked request id,
+ * hence try again in next sof
+ */
+ slot->status = CRM_SLOT_STATUS_REQ_PENDING;
if (link->state == CAM_CRM_LINK_STATE_ERR) {
- CAM_WARN(CAM_CRM,
- "Err recovery done idx %d status %d",
+ /*
+ * During error recovery all tables should be
+ * ready, don't expect to enter here.
+ * @TODO: gracefully handle if recovery fails.
+ */
+ CAM_ERR(CAM_CRM,
+ "FATAL recovery cant finish idx %d status %d",
in_q->rd_idx,
in_q->slot[in_q->rd_idx].status);
- mutex_lock(&link->lock);
- link->state = CAM_CRM_LINK_STATE_READY;
- mutex_unlock(&link->lock);
+ rc = -EPERM;
}
+ return rc;
+ }
+ }
+ if (trigger == CAM_TRIGGER_POINT_EOF &&
+ (!(link->trigger_mask & CAM_TRIGGER_POINT_SOF))) {
+ CAM_ERR(CAM_CRM, "Applying for last SOF fails");
+ return -EINVAL;
+ }
- /*
- * 2. Check if any new req is pending in input queue,
- * if not finish the lower pipeline delay device with
- * available req ids.
- */
+ rc = __cam_req_mgr_send_req(link, link->req.in_q, trigger);
+ if (rc < 0) {
+ /* Apply req failed retry at next sof */
+ slot->status = CRM_SLOT_STATUS_REQ_PENDING;
+ } else {
+ link->trigger_mask |= trigger;
+
+ if (link->state == CAM_CRM_LINK_STATE_ERR) {
+ CAM_WARN(CAM_CRM, "Err recovery done idx %d",
+ in_q->rd_idx);
+ mutex_lock(&link->lock);
+ link->state = CAM_CRM_LINK_STATE_READY;
+ mutex_unlock(&link->lock);
+ }
+ if (link->trigger_mask == link->subscribe_event) {
+ slot->status = CRM_SLOT_STATUS_REQ_APPLIED;
+ link->trigger_mask = 0;
+ CAM_DBG(CAM_CRM, "req is applied\n");
__cam_req_mgr_check_next_req_slot(in_q);
- /*
- * 3. Older req slots can be safely reset as no err ack.
- */
idx = in_q->rd_idx;
- __cam_req_mgr_dec_idx(&idx, link->max_delay + 1,
+ __cam_req_mgr_dec_idx(
+ &idx, link->max_delay + 1,
in_q->num_slots);
__cam_req_mgr_reset_req_slot(link, idx);
}
- } else {
- /*
- * 4.If traverse result is not success, then some devices are
- * not ready with packet for the asked request id,
- * hence try again in next sof
- */
- slot->status = CRM_SLOT_STATUS_REQ_PENDING;
- if (link->state == CAM_CRM_LINK_STATE_ERR) {
- /*
- * During error recovery all tables should be ready
- * don't expect to enter here.
- * @TODO: gracefully handle if recovery fails.
- */
- CAM_ERR(CAM_CRM,
- "FATAL recovery cant finish idx %d status %d",
- in_q->rd_idx, in_q->slot[in_q->rd_idx].status);
- rc = -EPERM;
- }
}
return rc;
@@ -576,7 +593,7 @@
*
* @brief : Add table to list under link sorted by pd decremeting order
* @l_tbl : list of pipeline delay tables.
- * @new_tbl : new tbl which will be appended to above list as per its pd value
+ * @new_tbl : new tbl which will be appended to above list as per its pd value
*
*/
static void __cam_req_mgr_add_tbl_to_link(struct cam_req_mgr_req_tbl **l_tbl,
@@ -828,6 +845,7 @@
link_data.link_enable = 0;
link_data.link_hdl = link->link_hdl;
link_data.crm_cb = NULL;
+ link_data.subscribe_event = 0;
/* Using device ops unlink devices */
for (i = 0; i < link->num_devs; i++) {
@@ -977,7 +995,7 @@
send_req = (struct cam_req_mgr_send_request *)data;
in_q = send_req->in_q;
- rc = __cam_req_mgr_send_req(link, in_q);
+ rc = __cam_req_mgr_send_req(link, in_q, CAM_TRIGGER_POINT_SOF);
end:
return rc;
}
@@ -1302,7 +1320,7 @@
}
/**
- * cam_req_mgr_process_sof()
+ * cam_req_mgr_process_trigger()
*
* @brief: This runs in workque thread context. Call core funcs to check
* which peding requests can be processed.
@@ -1311,10 +1329,10 @@
*
* @return: 0 on success.
*/
-static int cam_req_mgr_process_sof(void *priv, void *data)
+static int cam_req_mgr_process_trigger(void *priv, void *data)
{
int rc = 0;
- struct cam_req_mgr_sof_notify *sof_data = NULL;
+ struct cam_req_mgr_trigger_notify *trigger_data = NULL;
struct cam_req_mgr_core_link *link = NULL;
struct cam_req_mgr_req_queue *in_q = NULL;
struct crm_task_payload *task_data = NULL;
@@ -1326,11 +1344,12 @@
}
link = (struct cam_req_mgr_core_link *)priv;
task_data = (struct crm_task_payload *)data;
- sof_data = (struct cam_req_mgr_sof_notify *)&task_data->u;
+ trigger_data = (struct cam_req_mgr_trigger_notify *)&task_data->u;
- CAM_DBG(CAM_CRM, "link_hdl %x frame_id %lld",
- sof_data->link_hdl,
- sof_data->frame_id);
+ CAM_DBG(CAM_CRM, "link_hdl %x frame_id %lld, trigger %x\n",
+ trigger_data->link_hdl,
+ trigger_data->frame_id,
+ trigger_data->trigger);
in_q = link->req.in_q;
@@ -1354,7 +1373,7 @@
*/
__cam_req_mgr_inc_idx(&in_q->rd_idx, 1, in_q->num_slots);
}
- rc = __cam_req_mgr_process_req(link);
+ rc = __cam_req_mgr_process_req(link, trigger_data->trigger);
mutex_unlock(&link->req.lock);
end:
@@ -1484,7 +1503,7 @@
}
/**
- * cam_req_mgr_cb_notify_sof()
+ * cam_req_mgr_cb_notify_trigger()
*
* @brief : SOF received from device, sends trigger through workqueue
* @sof_data: contains information about frame_id, link etc.
@@ -1492,25 +1511,25 @@
* @return : 0 on success
*
*/
-static int cam_req_mgr_cb_notify_sof(
- struct cam_req_mgr_sof_notify *sof_data)
+static int cam_req_mgr_cb_notify_trigger(
+ struct cam_req_mgr_trigger_notify *trigger_data)
{
int rc = 0;
struct crm_workq_task *task = NULL;
struct cam_req_mgr_core_link *link = NULL;
- struct cam_req_mgr_sof_notify *notify_sof;
+ struct cam_req_mgr_trigger_notify *notify_trigger;
struct crm_task_payload *task_data;
- if (!sof_data) {
+ if (!trigger_data) {
CAM_ERR(CAM_CRM, "sof_data is NULL");
rc = -EINVAL;
goto end;
}
link = (struct cam_req_mgr_core_link *)
- cam_get_device_priv(sof_data->link_hdl);
+ cam_get_device_priv(trigger_data->link_hdl);
if (!link) {
- CAM_DBG(CAM_CRM, "link ptr NULL %x", sof_data->link_hdl);
+ CAM_DBG(CAM_CRM, "link ptr NULL %x", trigger_data->link_hdl);
rc = -EINVAL;
goto end;
}
@@ -1519,17 +1538,18 @@
task = cam_req_mgr_workq_get_task(link->workq);
if (!task) {
CAM_ERR(CAM_CRM, "no empty task frame %lld",
- sof_data->frame_id);
+ trigger_data->frame_id);
rc = -EBUSY;
goto end;
}
task_data = (struct crm_task_payload *)task->payload;
task_data->type = CRM_WORKQ_TASK_NOTIFY_SOF;
- notify_sof = (struct cam_req_mgr_sof_notify *)&task_data->u;
- notify_sof->frame_id = sof_data->frame_id;
- notify_sof->link_hdl = sof_data->link_hdl;
- notify_sof->dev_hdl = sof_data->dev_hdl;
- task->process_cb = &cam_req_mgr_process_sof;
+ notify_trigger = (struct cam_req_mgr_trigger_notify *)&task_data->u;
+ notify_trigger->frame_id = trigger_data->frame_id;
+ notify_trigger->link_hdl = trigger_data->link_hdl;
+ notify_trigger->dev_hdl = trigger_data->dev_hdl;
+ notify_trigger->trigger = trigger_data->trigger;
+ task->process_cb = &cam_req_mgr_process_trigger;
rc = cam_req_mgr_workq_enqueue_task(task, link, CRM_TASK_PRIORITY_0);
end:
@@ -1537,9 +1557,9 @@
}
static struct cam_req_mgr_crm_cb cam_req_mgr_ops = {
- .notify_sof = cam_req_mgr_cb_notify_sof,
- .notify_err = cam_req_mgr_cb_notify_err,
- .add_req = cam_req_mgr_cb_add_req,
+ .notify_trigger = cam_req_mgr_cb_notify_trigger,
+ .notify_err = cam_req_mgr_cb_notify_err,
+ .add_req = cam_req_mgr_cb_add_req,
};
/**
@@ -1561,6 +1581,7 @@
struct cam_req_mgr_connected_device *dev;
struct cam_req_mgr_req_tbl *pd_tbl;
enum cam_pipeline_delay max_delay;
+ uint32_t subscribe_event = 0;
if (link_info->num_devices > CAM_REQ_MGR_MAX_HANDLES)
return -EPERM;
@@ -1594,9 +1615,11 @@
trace_cam_req_mgr_connect_device(link, &dev->dev_info);
- CAM_DBG(CAM_CRM, "%x: connected: %s, id %d, delay %d",
+ CAM_DBG(CAM_CRM,
+ "%x: connected: %s, id %d, delay %d, trigger %x",
link_info->session_hdl, dev->dev_info.name,
- dev->dev_info.dev_id, dev->dev_info.p_delay);
+ dev->dev_info.dev_id, dev->dev_info.p_delay,
+ dev->dev_info.trigger);
if (rc < 0 ||
dev->dev_info.p_delay >=
CAM_PIPELINE_DELAY_MAX ||
@@ -1609,18 +1632,19 @@
link_info->session_hdl,
dev->dev_info.name,
dev->dev_info.p_delay);
- if (dev->dev_info.p_delay >
- max_delay)
- max_delay =
- dev->dev_info.p_delay;
+ if (dev->dev_info.p_delay > max_delay)
+ max_delay = dev->dev_info.p_delay;
+
+ subscribe_event |= (uint32_t)dev->dev_info.trigger;
}
}
-
+ link->subscribe_event = subscribe_event;
link_data.link_enable = 1;
link_data.link_hdl = link->link_hdl;
link_data.crm_cb = &cam_req_mgr_ops;
link_data.max_delay = max_delay;
+ link_data.subscribe_event = subscribe_event;
for (i = 0; i < link_info->num_devices; i++) {
dev = &link->l_dev[i];
diff --git a/drivers/media/platform/msm/camera/cam_req_mgr/cam_req_mgr_core.h b/drivers/media/platform/msm/camera/cam_req_mgr/cam_req_mgr_core.h
index 3ee0e2f..98a2a4f 100644
--- a/drivers/media/platform/msm/camera/cam_req_mgr/cam_req_mgr_core.h
+++ b/drivers/media/platform/msm/camera/cam_req_mgr/cam_req_mgr_core.h
@@ -47,15 +47,15 @@
/**
* struct crm_task_payload
- * @type : to identify which type of task is present
- * @u : union of payload of all types of tasks supported
- * @sched_req : contains info of incoming reqest from CSL to CRM
- * @flush_info : contains info of cancelled reqest
- * @dev_req : contains tracking info of available req id at device
- * @send_req : contains info of apply settings to be sent to devs in link
- * @apply_req : contains info of which request is applied at device
- * @notify_sof : contains notification from IFE to CRM about SOF trigger
- * @notify_err : contains error info happened while processing request
+ * @type : to identify which type of task is present
+ * @u : union of payload of all types of tasks supported
+ * @sched_req : contains info of incoming reqest from CSL to CRM
+ * @flush_info : contains info of cancelled reqest
+ * @dev_req : contains tracking info of available req id at device
+ * @send_req : contains info of apply settings to be sent to devs in link
+ * @apply_req : contains info of which request is applied at device
+ * @notify_trigger : contains notification from IFE to CRM about trigger
+ * @notify_err : contains error info happened while processing request
* -
*/
struct crm_task_payload {
@@ -65,7 +65,7 @@
struct cam_req_mgr_flush_info flush_info;
struct cam_req_mgr_add_request dev_req;
struct cam_req_mgr_send_request send_req;
- struct cam_req_mgr_sof_notify notify_sof;
+ struct cam_req_mgr_trigger_notify notify_trigger;
struct cam_req_mgr_error_notify notify_err;
} u;
};
@@ -90,8 +90,8 @@
* State machine for life cycle of request in input queue
* NO_REQ : empty slot
* REQ_ADDED : new entry in slot
- * INCOMPLETE : waiting for
- * APPLIED : req is sent to devices
+ * PENDING : waiting for next trigger to apply
+ * APPLIED : req is sent to all devices
* INVALID : invalid state
*/
enum crm_slot_status {
@@ -108,7 +108,7 @@
* AVAILABLE : link available
* IDLE : link initialized but not ready yet
* READY : link is ready for use
- * ERR : link has encountered error
+ * ERR : link has encountered error
* MAX : invalid state
*/
enum cam_req_mgr_link_state {
@@ -189,12 +189,12 @@
/**
* struct cam_req_mgr_slot
* - Internal Book keeping
- * @idx : slot index
- * @skip_idx : if req id in this slot needs to be skipped/not applied
- * @status : state machine for life cycle of a slot
+ * @idx : slot index
+ * @skip_idx : if req id in this slot needs to be skipped/not applied
+ * @status : state machine for life cycle of a slot
* - members updated due to external events
- * @recover : if user enabled recovery for this request.
- * @req_id : mask tracking which all devices have request ready
+ * @recover : if user enabled recovery for this request.
+ * @req_id : mask tracking which all devices have request ready
*/
struct cam_req_mgr_slot {
int32_t idx;
@@ -275,6 +275,9 @@
* @state : link state machine
* @parent : pvt data - link's parent is session
* @lock : mutex lock to guard link data operations
+ * @subscribe_event: irqs that link subscribes, IFE should send notification
+ * to CRM at those hw events.
+ * @trigger_mask : mask on which irq the req is already applied
*/
struct cam_req_mgr_core_link {
int32_t link_hdl;
@@ -289,6 +292,8 @@
enum cam_req_mgr_link_state state;
void *parent;
struct mutex lock;
+ uint32_t subscribe_event;
+ uint32_t trigger_mask;
};
/**
diff --git a/drivers/media/platform/msm/camera/cam_req_mgr/cam_req_mgr_interface.h b/drivers/media/platform/msm/camera/cam_req_mgr/cam_req_mgr_interface.h
index 8faf35a..6195b59 100644
--- a/drivers/media/platform/msm/camera/cam_req_mgr/cam_req_mgr_interface.h
+++ b/drivers/media/platform/msm/camera/cam_req_mgr/cam_req_mgr_interface.h
@@ -18,7 +18,7 @@
#include "cam_req_mgr_core_defs.h"
#include "cam_req_mgr_util.h"
-struct cam_req_mgr_sof_notify;
+struct cam_req_mgr_trigger_notify;
struct cam_req_mgr_error_notify;
struct cam_req_mgr_add_request;
struct cam_req_mgr_device_info;
@@ -29,13 +29,15 @@
/* Request Manager -- camera device driver interface */
/**
- * @brief: camera kernel drivers to cam req mgr communication
+ * @brief: camera kernel drivers to cam req mgr communication
*
- * @cam_req_mgr_notify_sof: for device which generates sof to inform CRM
- * @cam_req_mgr_notify_err: device use this to inform about different errors.
- * @cam_req_mgr_add_req: to info CRm about new rqeuest received from userspace
+ * @cam_req_mgr_notify_trigger: for device which generates trigger to inform CRM
+ * @cam_req_mgr_notify_err : device use this to inform about different errors
+ * @cam_req_mgr_add_req : to info CRm about new rqeuest received from
+ * userspace
*/
-typedef int (*cam_req_mgr_notify_sof)(struct cam_req_mgr_sof_notify *);
+typedef int (*cam_req_mgr_notify_trigger)(
+ struct cam_req_mgr_trigger_notify *);
typedef int (*cam_req_mgr_notify_err)(struct cam_req_mgr_error_notify *);
typedef int (*cam_req_mgr_add_req)(struct cam_req_mgr_add_request *);
@@ -57,16 +59,16 @@
typedef int (*cam_req_mgr_process_evt)(struct cam_req_mgr_link_evt_data *);
/**
- * @brief : cam_req_mgr_crm_cb - func table
+ * @brief : cam_req_mgr_crm_cb - func table
*
- * @notify_sof : payload for sof indication event
- * @notify_err : payload for different error occurred at device
- * @add_req : payload to inform which device and what request is received
+ * @notify_trigger : payload for trigger indication event
+ * @notify_err : payload for different error occurred at device
+ * @add_req : payload to inform which device and what request is received
*/
struct cam_req_mgr_crm_cb {
- cam_req_mgr_notify_sof notify_sof;
- cam_req_mgr_notify_err notify_err;
- cam_req_mgr_add_req add_req;
+ cam_req_mgr_notify_trigger notify_trigger;
+ cam_req_mgr_notify_err notify_err;
+ cam_req_mgr_add_req add_req;
};
/**
@@ -103,6 +105,13 @@
};
/**
+ * @CAM_TRIGGER_POINT_SOF : Trigger point for SOF
+ * @CAM_TRIGGER_POINT_EOF : Trigger point for EOF
+ */
+#define CAM_TRIGGER_POINT_SOF (1 << 0)
+#define CAM_TRIGGER_POINT_EOF (1 << 1)
+
+/**
* enum cam_req_status
* @brief : enumerator for request status
*
@@ -177,15 +186,18 @@
};
/**
- * struct cam_req_mgr_sof_notify
+ * struct cam_req_mgr_trigger_notify
* @link_hdl : link identifier
* @dev_hdl : device handle which has sent this req id
* @frame_id : frame id for internal tracking
+ * @trigger : trigger point of this notification, CRM will send apply
+ * only to the devices which subscribe to this point.
*/
-struct cam_req_mgr_sof_notify {
- int32_t link_hdl;
- int32_t dev_hdl;
- int64_t frame_id;
+struct cam_req_mgr_trigger_notify {
+ int32_t link_hdl;
+ int32_t dev_hdl;
+ int64_t frame_id;
+ uint32_t trigger;
};
/**
@@ -223,6 +235,7 @@
* @name : link link or unlink
* @dev_id : device id info
* @p_delay : delay between time settings applied and take effect
+ * @trigger : Trigger point for the client
*
*/
struct cam_req_mgr_device_info {
@@ -230,15 +243,17 @@
char name[256];
enum cam_req_mgr_device_id dev_id;
enum cam_pipeline_delay p_delay;
+ uint32_t trigger;
};
/**
* struct cam_req_mgr_core_dev_link_setup
- * @link_enable : link link or unlink
- * @link_hdl : link identifier
- * @dev_hdl : device handle for reference
- * @max_delay : max pipeline delay on this link
- * @crm_cb : callback funcs to communicate with req mgr
+ * @link_enable : link link or unlink
+ * @link_hdl : link identifier
+ * @dev_hdl : device handle for reference
+ * @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
*
*/
struct cam_req_mgr_core_dev_link_setup {
@@ -247,6 +262,7 @@
int32_t dev_hdl;
enum cam_pipeline_delay max_delay;
struct cam_req_mgr_crm_cb *crm_cb;
+ uint32_t subscribe_event;
};
/**
@@ -255,6 +271,7 @@
* @dev_hdl : device handle for cross check
* @request_id : request id settings to apply
* @report_if_bubble : report to crm if failure in applying
+ * @trigger_point : the trigger point of this apply
*
*/
struct cam_req_mgr_apply_request {
@@ -262,6 +279,7 @@
int32_t dev_hdl;
uint64_t request_id;
int32_t report_if_bubble;
+ uint32_t trigger_point;
};
/**