Merge "msm: camera: isp: Add support for offline IFE" into camera-kernel.lnx.4.0

This commit is contained in:
Camera Software Integration 2020-02-12 14:10:59 -08:00 • committed by Gerrit - the friendly Code Review server
commit 6c7de8467b
15 changed files with 1215 additions and 583 deletions

View file

@ -1028,6 +1028,96 @@ static int __cam_isp_ctx_handle_buf_done_in_activated_state(
return rc;
}
static int __cam_isp_ctx_apply_req_offline(
struct cam_context *ctx, uint32_t next_state,
struct cam_isp_context *ctx_isp)
{
int rc = 0;
struct cam_ctx_request *req;
struct cam_isp_ctx_req *req_isp;
struct cam_hw_config_args cfg;
if (list_empty(&ctx->pending_req_list)) {
CAM_DBG(CAM_ISP, "No pending requests to apply");
rc = -EFAULT;
goto end;
}
if (ctx->state != CAM_CTX_ACTIVATED)
goto end;
if (ctx_isp->active_req_cnt >= 2)
goto end;
req = list_first_entry(&ctx->pending_req_list, struct cam_ctx_request,
list);
CAM_DBG(CAM_REQ, "Apply request %lld in substate %d ctx %u",
req->request_id, ctx_isp->substate_activated, ctx->ctx_id);
req_isp = (struct cam_isp_ctx_req *) req->req_priv;
memset(&cfg, 0, sizeof(cfg));
cfg.ctxt_to_hw_map = ctx_isp->hw_ctx;
cfg.request_id = req->request_id;
cfg.hw_update_entries = req_isp->cfg;
cfg.num_hw_update_entries = req_isp->num_cfg;
cfg.priv = &req_isp->hw_update_data;
cfg.init_packet = 0;
rc = ctx->hw_mgr_intf->hw_config(ctx->hw_mgr_intf->hw_mgr_priv, &cfg);
if (rc) {
CAM_ERR_RATE_LIMIT(CAM_ISP, "Can not apply the configuration");
} else {
atomic_set(&ctx_isp->rxd_epoch, 0);
ctx_isp->substate_activated = next_state;
ctx_isp->last_applied_req_id = req->request_id;
list_del_init(&req->list);
list_add_tail(&req->list, &ctx->wait_req_list);
CAM_DBG(CAM_ISP, "New substate state %d, applied req %lld",
next_state, ctx_isp->last_applied_req_id);
__cam_isp_ctx_update_state_monitor_array(ctx_isp,
CAM_ISP_STATE_CHANGE_TRIGGER_APPLIED,
req->request_id);
}
end:
return rc;
}
static int __cam_isp_ctx_offline_epoch_in_activated_state(
struct cam_isp_context *ctx_isp, void *evt_data)
{
struct cam_context *ctx = ctx_isp->base;
struct cam_ctx_request *req, *req_temp;
uint64_t request_id = 0;
atomic_set(&ctx_isp->rxd_epoch, 1);
CAM_DBG(CAM_ISP, "SOF frame %lld ctx %u", ctx_isp->frame_id,
ctx->ctx_id);
list_for_each_entry_safe(req, req_temp, &ctx->active_req_list, list) {
if (req->request_id > ctx_isp->reported_req_id) {
request_id = req->request_id;
ctx_isp->reported_req_id = request_id;
break;
}
}
__cam_isp_ctx_apply_req_offline(ctx, CAM_ISP_CTX_ACTIVATED_APPLIED,
ctx_isp);
__cam_isp_ctx_send_sof_timestamp(ctx_isp, request_id,
CAM_REQ_MGR_SOF_EVENT_SUCCESS);
__cam_isp_ctx_update_state_monitor_array(ctx_isp,
CAM_ISP_STATE_CHANGE_TRIGGER_EPOCH,
request_id);
return 0;
}
static int __cam_isp_ctx_reg_upd_in_epoch_bubble_state(
struct cam_isp_context *ctx_isp, void *evt_data)
{
@ -1811,6 +1901,9 @@ end:
} while (req->request_id < ctx_isp->last_applied_req_id);
if (ctx_isp->offline_context)
goto exit;
if (ctx->ctx_crm_intf && ctx->ctx_crm_intf->notify_err) {
notify.link_hdl = ctx->link_hdl;
notify.dev_hdl = ctx->dev_hdl;
@ -1861,6 +1954,7 @@ end:
CAM_DBG(CAM_ISP, "Exit");
exit:
return rc;
}
@ -2244,6 +2338,63 @@ static struct cam_isp_ctx_irq_ops
},
};
static struct cam_isp_ctx_irq_ops
cam_isp_ctx_offline_state_machine_irq[CAM_ISP_CTX_ACTIVATED_MAX] = {
/* SOF */
{
.irq_ops = {
__cam_isp_ctx_handle_error,
NULL,
NULL,
NULL,
NULL,
NULL,
},
},
/* APPLIED */
{
.irq_ops = {
__cam_isp_ctx_handle_error,
__cam_isp_ctx_sof_in_activated_state,
__cam_isp_ctx_reg_upd_in_applied_state,
NULL,
NULL,
__cam_isp_ctx_buf_done_in_applied,
},
},
/* EPOCH */
{
.irq_ops = {
__cam_isp_ctx_handle_error,
NULL,
NULL,
__cam_isp_ctx_offline_epoch_in_activated_state,
NULL,
__cam_isp_ctx_buf_done_in_epoch,
},
},
/* BUBBLE */
{
},
/* Bubble Applied */
{
},
/* HW ERROR */
{
.irq_ops = {
NULL,
__cam_isp_ctx_sof_in_activated_state,
__cam_isp_ctx_reg_upd_in_hw_error,
NULL,
NULL,
NULL,
},
},
/* HALT */
{
},
};
static int __cam_isp_ctx_apply_req_in_activated_state(
struct cam_context *ctx, struct cam_req_mgr_apply_request *apply,
enum cam_isp_ctx_activated_substate next_state)
@ -2796,6 +2947,7 @@ static int __cam_isp_ctx_flush_req_in_top_state(
end:
ctx_isp->bubble_frame_cnt = 0;
atomic_set(&ctx_isp->process_bubble, 0);
atomic_set(&ctx_isp->rxd_epoch, 0);
return rc;
}
@ -3685,8 +3837,11 @@ static int __cam_isp_ctx_config_dev_in_top_state(
ctx->state);
}
} else {
if (ctx->state != CAM_CTX_FLUSHED && ctx->state >= CAM_CTX_READY
&& ctx->ctx_crm_intf->add_req) {
if (ctx_isp->offline_context) {
__cam_isp_ctx_enqueue_request_in_order(ctx, req);
} else if ((ctx->state != CAM_CTX_FLUSHED) &&
(ctx->state >= CAM_CTX_READY) &&
ctx->ctx_crm_intf->add_req) {
add_req.link_hdl = ctx->link_hdl;
add_req.dev_hdl = ctx->dev_hdl;
add_req.req_id = req->request_id;
@ -3713,6 +3868,13 @@ static int __cam_isp_ctx_config_dev_in_top_state(
"Preprocessing Config req_id %lld successful on ctx %u",
req->request_id, ctx->ctx_id);
if (ctx_isp->offline_context && atomic_read(&ctx_isp->rxd_epoch)) {
spin_lock_bh(&ctx->lock);
__cam_isp_ctx_apply_req_offline(ctx,
CAM_ISP_CTX_ACTIVATED_APPLIED, ctx_isp);
spin_unlock_bh(&ctx->lock);
}
return rc;
put_ref:
@ -3827,11 +3989,15 @@ static int __cam_isp_ctx_acquire_dev_in_available(struct cam_context *ctx,
cam_isp_ctx_rdi_only_activated_state_machine;
ctx_isp->rdi_only_context = true;
} else if (isp_hw_cmd_args.u.ctx_type == CAM_ISP_CTX_FS2) {
CAM_DBG(CAM_ISP, "FS2 Session has PIX ,RD and RDI");
CAM_DBG(CAM_ISP, "FS2 Session has PIX, RD and RDI");
ctx_isp->substate_machine_irq =
cam_isp_ctx_fs2_state_machine_irq;
ctx_isp->substate_machine =
cam_isp_ctx_fs2_state_machine;
} else if (isp_hw_cmd_args.u.ctx_type == CAM_ISP_CTX_OFFLINE) {
CAM_DBG(CAM_ISP, "offline Session has PIX and RD resources");
ctx_isp->substate_machine_irq =
cam_isp_ctx_offline_state_machine_irq;
} else {
CAM_DBG(CAM_ISP, "Session has PIX or PIX and RDI resources");
ctx_isp->substate_machine_irq =
@ -3985,11 +4151,16 @@ static int __cam_isp_ctx_acquire_hw_v1(struct cam_context *ctx,
cam_isp_ctx_rdi_only_activated_state_machine;
ctx_isp->rdi_only_context = true;
} else if (isp_hw_cmd_args.u.ctx_type == CAM_ISP_CTX_FS2) {
CAM_DBG(CAM_ISP, "FS2 Session has PIX ,RD and RDI");
CAM_DBG(CAM_ISP, "FS2 Session has PIX, RD and RDI");
ctx_isp->substate_machine_irq =
cam_isp_ctx_fs2_state_machine_irq;
ctx_isp->substate_machine =
cam_isp_ctx_fs2_state_machine;
} else if (isp_hw_cmd_args.u.ctx_type == CAM_ISP_CTX_OFFLINE) {
CAM_DBG(CAM_ISP, "Offline session has PIX and RD resources");
ctx_isp->substate_machine_irq =
cam_isp_ctx_offline_state_machine_irq;
ctx_isp->substate_machine = NULL;
} else {
CAM_DBG(CAM_ISP, "Session has PIX or PIX and RDI resources");
ctx_isp->substate_machine_irq =
@ -4136,11 +4307,17 @@ static int __cam_isp_ctx_acquire_hw_v2(struct cam_context *ctx,
cam_isp_ctx_rdi_only_activated_state_machine;
ctx_isp->rdi_only_context = true;
} else if (isp_hw_cmd_args.u.ctx_type == CAM_ISP_CTX_FS2) {
CAM_DBG(CAM_ISP, "FS2 Session has PIX ,RD and RDI");
CAM_DBG(CAM_ISP, "FS2 Session has PIX, RD and RDI");
ctx_isp->substate_machine_irq =
cam_isp_ctx_fs2_state_machine_irq;
ctx_isp->substate_machine =
cam_isp_ctx_fs2_state_machine;
} else if (isp_hw_cmd_args.u.ctx_type == CAM_ISP_CTX_OFFLINE) {
CAM_DBG(CAM_ISP, "Offline Session has PIX and RD resources");
ctx_isp->substate_machine_irq =
cam_isp_ctx_offline_state_machine_irq;
ctx_isp->substate_machine = NULL;
ctx_isp->offline_context = true;
} else {
CAM_DBG(CAM_ISP, "Session has PIX or PIX and RDI resources");
ctx_isp->substate_machine_irq =
@ -4207,7 +4384,7 @@ static int __cam_isp_ctx_config_dev_in_acquired(struct cam_context *ctx,
rc = __cam_isp_ctx_config_dev_in_top_state(ctx, cmd);
if (!rc && (ctx->link_hdl >= 0)) {
if (!rc && ((ctx->link_hdl >= 0) || ctx_isp->offline_context)) {
ctx->state = CAM_CTX_READY;
trace_cam_context_state("ISP", ctx);
}
@ -4368,6 +4545,7 @@ static int __cam_isp_ctx_start_dev_in_ready(struct cam_context *ctx,
start_isp.start_only = false;
atomic_set(&ctx_isp->process_bubble, 0);
atomic_set(&ctx_isp->rxd_epoch, 0);
ctx_isp->frame_id = 0;
ctx_isp->active_req_cnt = 0;
ctx_isp->reported_req_id = 0;
@ -4390,11 +4568,24 @@ static int __cam_isp_ctx_start_dev_in_ready(struct cam_context *ctx,
*/
list_del_init(&req->list);
if (ctx_isp->rdi_only_context || !req_isp->num_fence_map_out) {
if (ctx_isp->offline_context && !req_isp->num_fence_map_out) {
list_add_tail(&req->list, &ctx->free_req_list);
atomic_set(&ctx_isp->rxd_epoch, 1);
CAM_DBG(CAM_REQ,
"Move pending req: %lld to free list(cnt: %d) offline ctx %u",
req->request_id, ctx_isp->active_req_cnt, ctx->ctx_id);
} else if (ctx_isp->rdi_only_context || !req_isp->num_fence_map_out) {
list_add_tail(&req->list, &ctx->wait_req_list);
CAM_DBG(CAM_REQ,
"Move pending req: %lld to wait list(cnt: %d) ctx %u",
req->request_id, ctx_isp->active_req_cnt, ctx->ctx_id);
} else {
list_add_tail(&req->list, &ctx->active_req_list);
ctx_isp->active_req_cnt++;
CAM_DBG(CAM_REQ,
"Move pending req: %lld to active list(cnt: %d) ctx %u offline %d",
req->request_id, ctx_isp->active_req_cnt, ctx->ctx_id,
ctx_isp->offline_context);
}
/*
@ -4539,6 +4730,7 @@ static int __cam_isp_ctx_stop_dev_in_activated_unlock(
ctx_isp->last_applied_req_id = 0;
ctx_isp->req_info.last_bufdone_req_id = 0;
atomic_set(&ctx_isp->process_bubble, 0);
atomic_set(&ctx_isp->rxd_epoch, 0);
atomic64_set(&ctx_isp->state_monitor_head, -1);
for (i = 0; i < CAM_ISP_CTX_EVENT_MAX; i++)

View file

@ -247,13 +247,16 @@ struct cam_isp_context_event_record {
* @event_record: Event record array
* @rdi_only_context: Get context type information.
* true, if context is rdi only context
* @offline_context: Indicate whether context is for offline IFE
* @hw_acquired: Indicate whether HW resources are acquired
* @init_received: Indicate whether init config packet is received
* @split_acquire: Indicate whether a separate acquire is expected
* @custom_enabled: Custom HW enabled for this ctx
* @use_frame_header_ts: Use frame header for qtimer ts
* @init_timestamp: Timestamp at which this context is initialized
* @isp_device_type ISP device type
* @isp_device_type: ISP device type
* @rxd_epoch: Indicate whether epoch has been received. Used to
* decide whether to apply request in offline ctx
*
*/
struct cam_isp_context {
@ -286,6 +289,7 @@ struct cam_isp_context {
struct cam_isp_context_event_record event_record[
CAM_ISP_CTX_EVENT_MAX][CAM_ISP_CTX_EVENT_RECORD_MAX_ENTRIES];
bool rdi_only_context;
bool offline_context;
bool hw_acquired;
bool init_received;
bool split_acquire;
@ -293,6 +297,7 @@ struct cam_isp_context {
bool use_frame_header_ts;
unsigned int init_timestamp;
uint32_t isp_device_type;
atomic_t rxd_epoch;
};
/**

View file

@ -979,90 +979,6 @@ static int cam_ife_mgr_process_base_info(
return 0;
}
static int cam_ife_hw_mgr_acquire_res_bus_rd(
struct cam_ife_hw_mgr_ctx *ife_ctx,
struct cam_isp_in_port_generic_info *in_port)
{
int rc = -EINVAL;
struct cam_vfe_acquire_args vfe_acquire;
struct cam_isp_hw_mgr_res *ife_in_rd_res;
struct cam_hw_intf *hw_intf;
struct cam_isp_hw_mgr_res *ife_src_res;
int i;
CAM_DBG(CAM_ISP, "Enter");
list_for_each_entry(ife_src_res, &ife_ctx->res_list_ife_src, list) {
if (ife_src_res->res_id != CAM_ISP_HW_VFE_IN_RD)
continue;
rc = cam_ife_hw_mgr_get_res(&ife_ctx->free_res_list,
&ife_in_rd_res);
if (rc) {
CAM_ERR(CAM_ISP, "No more free hw mgr resource");
goto err;
}
cam_ife_hw_mgr_put_res(&ife_ctx->res_list_ife_in_rd,
&ife_in_rd_res);
vfe_acquire.rsrc_type = CAM_ISP_RESOURCE_VFE_BUS_RD;
vfe_acquire.tasklet = ife_ctx->common.tasklet_info;
vfe_acquire.vfe_out.cdm_ops = ife_ctx->cdm_ops;
vfe_acquire.priv = ife_ctx;
vfe_acquire.vfe_out.unique_id = ife_ctx->ctx_index;
vfe_acquire.vfe_out.is_dual = ife_src_res->is_dual_isp;
for (i = 0; i < CAM_ISP_HW_SPLIT_MAX; i++) {
if (!ife_src_res->hw_res[i])
continue;
hw_intf = ife_src_res->hw_res[i]->hw_intf;
if (i == CAM_ISP_HW_SPLIT_LEFT) {
vfe_acquire.vfe_out.split_id =
CAM_ISP_HW_SPLIT_LEFT;
if (ife_src_res->is_dual_isp) {
/*TBD */
vfe_acquire.vfe_out.is_master = 1;
vfe_acquire.vfe_out.dual_slave_core =
ife_ctx->slave_hw_idx;
} else {
vfe_acquire.vfe_out.is_master = 0;
vfe_acquire.vfe_out.dual_slave_core =
0;
}
} else {
vfe_acquire.vfe_out.split_id =
CAM_ISP_HW_SPLIT_RIGHT;
vfe_acquire.vfe_out.is_master = 0;
vfe_acquire.vfe_out.dual_slave_core =
ife_ctx->master_hw_idx;
}
rc = hw_intf->hw_ops.reserve(hw_intf->hw_priv,
&vfe_acquire,
sizeof(struct cam_vfe_acquire_args));
if (rc) {
CAM_ERR(CAM_ISP,
"Can not acquire out resource 0x%x",
vfe_acquire.rsrc_type);
goto err;
}
ife_in_rd_res->hw_res[i] =
vfe_acquire.vfe_out.rsrc_node;
CAM_DBG(CAM_ISP, "resource type :0x%x res id:0x%x",
ife_in_rd_res->hw_res[i]->res_type,
ife_in_rd_res->hw_res[i]->res_id);
}
ife_in_rd_res->is_dual_isp = in_port->usage_type;
ife_in_rd_res->res_type = CAM_ISP_RESOURCE_VFE_BUS_RD;
}
return 0;
err:
CAM_DBG(CAM_ISP, "Exit rc(0x%x)", rc);
return rc;
}
static int cam_ife_hw_mgr_acquire_res_ife_out_rdi(
struct cam_ife_hw_mgr_ctx *ife_ctx,
struct cam_isp_hw_mgr_res *ife_src_res,
@ -1297,125 +1213,6 @@ err:
return rc;
}
static int cam_ife_hw_mgr_acquire_res_ife_rd_src(
struct cam_ife_hw_mgr_ctx *ife_ctx,
struct cam_isp_in_port_generic_info *in_port)
{
int rc = -1;
struct cam_isp_hw_mgr_res *csid_res;
struct cam_isp_hw_mgr_res *ife_src_res;
struct cam_vfe_acquire_args vfe_acquire;
struct cam_hw_intf *hw_intf;
struct cam_ife_hw_mgr *ife_hw_mgr;
int vfe_idx = -1, i = 0;
ife_hw_mgr = ife_ctx->hw_mgr;
CAM_DBG(CAM_ISP, "Enter");
list_for_each_entry(csid_res, &ife_ctx->res_list_ife_csid, list) {
if (csid_res->res_id != CAM_IFE_PIX_PATH_RES_RDI_0) {
CAM_DBG(CAM_ISP, "not RDI0: %d", csid_res->res_id);
continue;
}
rc = cam_ife_hw_mgr_get_res(&ife_ctx->free_res_list,
&ife_src_res);
if (rc) {
CAM_ERR(CAM_ISP, "No more free hw mgr resource");
goto err;
}
cam_ife_hw_mgr_put_res(&ife_ctx->res_list_ife_src,
&ife_src_res);
CAM_DBG(CAM_ISP, "csid_res_id %d", csid_res->res_id);
vfe_acquire.rsrc_type = CAM_ISP_RESOURCE_VFE_IN;
vfe_acquire.tasklet = ife_ctx->common.tasklet_info;
vfe_acquire.vfe_in.cdm_ops = ife_ctx->cdm_ops;
vfe_acquire.vfe_in.in_port = in_port;
vfe_acquire.vfe_in.res_id = CAM_ISP_HW_VFE_IN_RD;
vfe_acquire.vfe_in.sync_mode = CAM_ISP_HW_SYNC_NONE;
ife_src_res->res_type = vfe_acquire.rsrc_type;
ife_src_res->res_id = vfe_acquire.vfe_in.res_id;
ife_src_res->is_dual_isp = csid_res->is_dual_isp;
hw_intf =
ife_hw_mgr->ife_devices[csid_res->hw_res[
CAM_ISP_HW_SPLIT_LEFT]->hw_intf->hw_idx];
vfe_idx = csid_res->hw_res[
CAM_ISP_HW_SPLIT_LEFT]->hw_intf->hw_idx;
/*
* fill in more acquire information as needed
*/
if (ife_src_res->is_dual_isp)
vfe_acquire.vfe_in.sync_mode = CAM_ISP_HW_SYNC_MASTER;
rc = hw_intf->hw_ops.reserve(hw_intf->hw_priv,
&vfe_acquire,
sizeof(struct cam_vfe_acquire_args));
if (rc) {
CAM_ERR(CAM_ISP,
"Can not acquire IFE HW res %d",
csid_res->res_id);
goto err;
}
ife_src_res->hw_res[CAM_ISP_HW_SPLIT_LEFT] =
vfe_acquire.vfe_in.rsrc_node;
CAM_DBG(CAM_ISP,
"acquire success IFE:%d res type :0x%x res id:0x%x",
hw_intf->hw_idx,
ife_src_res->hw_res[CAM_ISP_HW_SPLIT_LEFT]->res_type,
ife_src_res->hw_res[CAM_ISP_HW_SPLIT_LEFT]->res_id);
if (!ife_src_res->is_dual_isp)
goto acq;
for (i = 0; i < CAM_ISP_HW_SPLIT_MAX; i++) {
if (i == CAM_ISP_HW_SPLIT_LEFT) {
CAM_DBG(CAM_ISP, "vfe_idx %d is acquired",
vfe_idx);
continue;
}
hw_intf = ife_hw_mgr->ife_devices[i];
/* fill in more acquire information as needed */
if (i == CAM_ISP_HW_SPLIT_RIGHT)
vfe_acquire.vfe_in.sync_mode =
CAM_ISP_HW_SYNC_SLAVE;
rc = hw_intf->hw_ops.reserve(hw_intf->hw_priv,
&vfe_acquire,
sizeof(struct cam_vfe_acquire_args));
if (rc) {
CAM_ERR(CAM_ISP,
"Can not acquire IFE HW res %d",
csid_res->res_id);
goto err;
}
ife_src_res->hw_res[i] = vfe_acquire.vfe_in.rsrc_node;
CAM_DBG(CAM_ISP,
"acquire success IFE:%d res type :0x%x res id:0x%x",
hw_intf->hw_idx,
ife_src_res->hw_res[i]->res_type,
ife_src_res->hw_res[i]->res_id);
}
acq:
/*
* It should be one to one mapping between
* csid resource and ife source resource
*/
csid_res->num_children++;
}
err:
/* release resource at the entry function */
CAM_DBG(CAM_ISP, "Exit rc %d", rc);
return rc;
}
static int cam_convert_hw_idx_to_ife_hw_num(int hw_idx)
{
uint32_t hw_version, rc = 0;
@ -1547,6 +1344,8 @@ static int cam_ife_hw_mgr_acquire_res_ife_src(
vfe_acquire.tasklet = ife_ctx->common.tasklet_info;
vfe_acquire.vfe_in.cdm_ops = ife_ctx->cdm_ops;
vfe_acquire.vfe_in.in_port = in_port;
vfe_acquire.vfe_in.is_fe_enabled = ife_ctx->is_fe_enabled;
vfe_acquire.vfe_in.is_offline = ife_ctx->is_offline;
vfe_acquire.priv = ife_ctx;
vfe_acquire.event_cb = cam_ife_hw_mgr_event_handler;
@ -1800,7 +1599,7 @@ static int cam_ife_mgr_acquire_cid_res(
/* Acquire Left if not already acquired */
/* For dual IFE cases, start acquiring the lower idx first */
if (ife_ctx->is_fe_enable || in_port->usage_type)
if (ife_ctx->is_fe_enabled || in_port->usage_type)
rc = cam_ife_hw_mgr_acquire_csid_hw(ife_hw_mgr,
&csid_acquire, true);
else
@ -2166,7 +1965,7 @@ static int cam_ife_hw_mgr_acquire_res_root(
ife_ctx->res_list_ife_in.res_id = in_port->res_type;
ife_ctx->res_list_ife_in.is_dual_isp = in_port->usage_type;
} else if ((ife_ctx->res_list_ife_in.res_id !=
in_port->res_type) && (!ife_ctx->is_fe_enable)) {
in_port->res_type) && (!ife_ctx->is_fe_enabled)) {
CAM_ERR(CAM_ISP, "No Free resource for this context");
goto err;
} else {
@ -2211,14 +2010,14 @@ static int cam_ife_mgr_check_and_update_fe_v0(
CAM_DBG(CAM_ISP, "in_port%d res_type %d", i,
in_port->res_type);
if (in_port->res_type == CAM_ISP_IFE_IN_RES_RD) {
ife_ctx->is_fe_enable = true;
ife_ctx->is_fe_enabled = true;
break;
}
in_port = (struct cam_isp_in_port_info *)((uint8_t *)in_port +
in_port_length);
}
CAM_DBG(CAM_ISP, "is_fe_enable %d", ife_ctx->is_fe_enable);
CAM_DBG(CAM_ISP, "is_fe_enabled %d", ife_ctx->is_fe_enabled);
return 0;
}
@ -2256,14 +2055,17 @@ static int cam_ife_mgr_check_and_update_fe_v2(
CAM_DBG(CAM_ISP, "in_port%d res_type %d", i,
in_port->res_type);
if (in_port->res_type == CAM_ISP_IFE_IN_RES_RD) {
ife_ctx->is_fe_enable = true;
ife_ctx->is_fe_enabled = true;
if (in_port->offline_mode)
ife_ctx->is_offline = true;
break;
}
in_port = (struct cam_isp_in_port_info_v2 *)
((uint8_t *)in_port + in_port_length);
}
CAM_DBG(CAM_ISP, "is_fe_enable %d", ife_ctx->is_fe_enable);
CAM_DBG(CAM_ISP, "is_fe_enabled %d is_offline %d",
ife_ctx->is_fe_enabled, ife_ctx->is_offline);
return 0;
}
@ -2316,22 +2118,21 @@ static int cam_ife_hw_mgr_preprocess_port(
ife_hw_mgr = ife_ctx->hw_mgr;
if (in_port->res_type == CAM_ISP_IFE_IN_RES_RD) {
if (in_port->res_type == CAM_ISP_IFE_IN_RES_RD)
ife_rd_num++;
} else {
for (i = 0; i < in_port->num_out_res; i++) {
out_port = &in_port->data[i];
if (cam_ife_hw_mgr_is_rdi_res(out_port->res_type))
rdi_num++;
else if (out_port->res_type == CAM_ISP_IFE_OUT_RES_2PD)
ppp_num++;
else if (out_port->res_type == CAM_ISP_IFE_OUT_RES_LCR)
lcr_num++;
else {
CAM_DBG(CAM_ISP, "out_res_type %d",
out_port->res_type);
ipp_num++;
}
for (i = 0; i < in_port->num_out_res; i++) {
out_port = &in_port->data[i];
if (cam_ife_hw_mgr_is_rdi_res(out_port->res_type))
rdi_num++;
else if (out_port->res_type == CAM_ISP_IFE_OUT_RES_2PD)
ppp_num++;
else if (out_port->res_type == CAM_ISP_IFE_OUT_RES_LCR)
lcr_num++;
else {
CAM_DBG(CAM_ISP, "out_res_type %d",
out_port->res_type);
ipp_num++;
}
}
@ -2347,6 +2148,290 @@ static int cam_ife_hw_mgr_preprocess_port(
return 0;
}
static int cam_ife_hw_mgr_acquire_offline_res_ife_bus_rd(
struct cam_ife_hw_mgr_ctx *ife_ctx,
struct cam_isp_in_port_generic_info *in_port)
{
int rc = -EINVAL, j;
int i = CAM_ISP_HW_SPLIT_LEFT;
struct cam_vfe_acquire_args vfe_acquire;
struct cam_isp_hw_mgr_res *ife_bus_rd_res;
struct cam_hw_intf *hw_intf;
struct cam_ife_hw_mgr *ife_hw_mgr;
ife_hw_mgr = ife_ctx->hw_mgr;
rc = cam_ife_hw_mgr_get_res(&ife_ctx->free_res_list, &ife_bus_rd_res);
if (rc) {
CAM_ERR(CAM_ISP, "No more free hw mgr resource");
goto end;
}
vfe_acquire.rsrc_type = CAM_ISP_RESOURCE_VFE_BUS_RD;
vfe_acquire.tasklet = ife_ctx->common.tasklet_info;
vfe_acquire.priv = ife_ctx;
vfe_acquire.event_cb = cam_ife_hw_mgr_event_handler;
vfe_acquire.vfe_bus_rd.cdm_ops = ife_ctx->cdm_ops;
vfe_acquire.vfe_bus_rd.is_dual = (uint32_t)ife_ctx->is_dual;
vfe_acquire.vfe_bus_rd.is_offline = ife_ctx->is_offline;
vfe_acquire.vfe_bus_rd.res_id = CAM_ISP_HW_VFE_IN_RD;
vfe_acquire.vfe_bus_rd.unpacker_fmt = in_port->fe_unpacker_fmt;
for (j = 0; j < CAM_IFE_HW_NUM_MAX; j++) {
if (!ife_hw_mgr->ife_devices[j])
continue;
hw_intf = ife_hw_mgr->ife_devices[j];
rc = hw_intf->hw_ops.reserve(hw_intf->hw_priv,
&vfe_acquire, sizeof(struct cam_vfe_acquire_args));
if (!rc) {
ife_bus_rd_res->hw_res[i] =
vfe_acquire.vfe_bus_rd.rsrc_node;
CAM_DBG(CAM_ISP, "Acquired VFE:%d BUS RD for LEFT", j);
break;
}
}
if (j == CAM_IFE_HW_NUM_MAX || !vfe_acquire.vfe_bus_rd.rsrc_node) {
CAM_ERR(CAM_ISP, "Failed to acquire BUS RD for LEFT", i);
goto put_res;
}
ife_bus_rd_res->res_type = vfe_acquire.rsrc_type;
ife_bus_rd_res->res_id = vfe_acquire.vfe_in.res_id;
ife_bus_rd_res->is_dual_isp = (uint32_t)ife_ctx->is_dual;
cam_ife_hw_mgr_put_res(&ife_ctx->res_list_ife_in_rd, &ife_bus_rd_res);
if (ife_ctx->is_dual) {
for (j = 0; j < CAM_IFE_HW_NUM_MAX; j++) {
if (!ife_hw_mgr->ife_devices[j])
continue;
if (j == ife_bus_rd_res->hw_res[i]->hw_intf->hw_idx)
continue;
hw_intf = ife_hw_mgr->ife_devices[j];
rc = hw_intf->hw_ops.reserve(hw_intf->hw_priv,
&vfe_acquire,
sizeof(struct cam_vfe_acquire_args));
if (!rc) {
ife_bus_rd_res->hw_res[++i] =
vfe_acquire.vfe_bus_rd.rsrc_node;
CAM_DBG(CAM_ISP,
"Acquired VFE:%d BUS RD for RIGHT", j);
break;
}
}
if (j == CAM_IFE_HW_NUM_MAX ||
!vfe_acquire.vfe_bus_rd.rsrc_node) {
CAM_ERR(CAM_ISP, "Failed to acquire BUS RD for RIGHT");
goto end;
}
}
return 0;
put_res:
cam_ife_hw_mgr_put_res(&ife_ctx->free_res_list, &ife_bus_rd_res);
end:
return rc;
}
static int cam_ife_hw_mgr_acquire_offline_res_ife_camif(
struct cam_ife_hw_mgr_ctx *ife_ctx,
struct cam_isp_in_port_generic_info *in_port,
bool acquire_lcr,
uint32_t *acquired_hw_id,
uint32_t *acquired_hw_path)
{
int rc = -1;
int i = CAM_ISP_HW_SPLIT_LEFT;
struct cam_isp_hw_mgr_res *ife_src_res;
struct cam_isp_hw_mgr_res *ife_bus_rd_res;
struct cam_vfe_acquire_args vfe_acquire;
struct cam_hw_intf *hw_intf;
struct cam_ife_hw_mgr *ife_hw_mgr;
ife_hw_mgr = ife_ctx->hw_mgr;
ife_bus_rd_res = list_first_entry(&ife_ctx->res_list_ife_in_rd,
struct cam_isp_hw_mgr_res, list);
if (!ife_bus_rd_res) {
CAM_ERR(CAM_ISP, "BUS RD resource has not been acquired");
rc = -EINVAL;
goto end;
}
rc = cam_ife_hw_mgr_get_res(&ife_ctx->free_res_list, &ife_src_res);
if (rc) {
CAM_ERR(CAM_ISP, "No free resource");
goto end;
}
vfe_acquire.rsrc_type = CAM_ISP_RESOURCE_VFE_IN;
vfe_acquire.tasklet = ife_ctx->common.tasklet_info;
vfe_acquire.priv = ife_ctx;
vfe_acquire.event_cb = cam_ife_hw_mgr_event_handler;
vfe_acquire.vfe_in.cdm_ops = ife_ctx->cdm_ops;
vfe_acquire.vfe_in.in_port = in_port;
vfe_acquire.vfe_in.is_fe_enabled = ife_ctx->is_fe_enabled;
vfe_acquire.vfe_in.is_offline = ife_ctx->is_offline;
if (!acquire_lcr)
vfe_acquire.vfe_in.res_id = CAM_ISP_HW_VFE_IN_CAMIF;
else
vfe_acquire.vfe_in.res_id = CAM_ISP_HW_VFE_IN_LCR;
if (ife_ctx->is_dual)
vfe_acquire.vfe_in.sync_mode = CAM_ISP_HW_SYNC_MASTER;
else
vfe_acquire.vfe_in.sync_mode = CAM_ISP_HW_SYNC_NONE;
hw_intf = ife_hw_mgr->ife_devices[
ife_bus_rd_res->hw_res[i]->hw_intf->hw_idx];
rc = hw_intf->hw_ops.reserve(hw_intf->hw_priv, &vfe_acquire,
sizeof(struct cam_vfe_acquire_args));
if (rc) {
CAM_ERR(CAM_ISP, "Failed to acquire CAMIF for LEFT");
goto put_res;
}
ife_src_res->hw_res[i] = vfe_acquire.vfe_in.rsrc_node;
*acquired_hw_id |= cam_convert_hw_idx_to_ife_hw_num(
hw_intf->hw_idx);
acquired_hw_path[i] |= cam_convert_res_id_to_hw_path(
ife_src_res->hw_res[i]->res_id);
CAM_DBG(CAM_ISP, "Acquired VFE:%d CAMIF for LEFT",
ife_src_res->hw_res[i]->hw_intf->hw_idx);
ife_src_res->res_type = vfe_acquire.rsrc_type;
ife_src_res->res_id = vfe_acquire.vfe_in.res_id;
ife_src_res->is_dual_isp = (uint32_t)ife_ctx->is_dual;
cam_ife_hw_mgr_put_res(&ife_ctx->res_list_ife_src, &ife_src_res);
if (ife_ctx->is_dual) {
vfe_acquire.vfe_in.sync_mode = CAM_ISP_HW_SYNC_SLAVE;
hw_intf = ife_hw_mgr->ife_devices[
ife_bus_rd_res->hw_res[++i]->hw_intf->hw_idx];
rc = hw_intf->hw_ops.reserve(hw_intf->hw_priv, &vfe_acquire,
sizeof(struct cam_vfe_acquire_args));
if (rc) {
CAM_ERR(CAM_ISP, "Failed to acquire CAMIF for RIGHT");
goto end;
}
ife_src_res->hw_res[i] = vfe_acquire.vfe_in.rsrc_node;
*acquired_hw_id |= cam_convert_hw_idx_to_ife_hw_num(
hw_intf->hw_idx);
acquired_hw_path[i] |= cam_convert_res_id_to_hw_path(
ife_src_res->hw_res[i]->res_id);
CAM_DBG(CAM_ISP, "Acquired VFE:%d CAMIF for RIGHT",
ife_src_res->hw_res[i]->hw_intf->hw_idx);
}
ife_bus_rd_res->num_children++;
return rc;
put_res:
cam_ife_hw_mgr_put_res(&ife_ctx->free_res_list, &ife_src_res);
end:
return rc;
}
static int cam_ife_mgr_acquire_hw_for_fe_ctx(
struct cam_ife_hw_mgr_ctx *ife_ctx,
struct cam_isp_in_port_generic_info *in_port,
uint32_t *num_pix_port,
uint32_t *acquired_hw_id,
uint32_t *acquired_hw_path)
{
int rc = -1;
int ipp_count = 0;
int rdi_count = 0;
int ppp_count = 0;
int ife_rd_count = 0;
int lcr_count = 0;
ife_ctx->is_dual = (bool)in_port->usage_type;
cam_ife_hw_mgr_preprocess_port(ife_ctx, in_port, &ipp_count,
&rdi_count, &ppp_count, &ife_rd_count, &lcr_count);
if ((!ipp_count && !lcr_count) || !ife_rd_count) {
CAM_ERR(CAM_ISP,
"Invalid %d BUS RD %d PIX %d LCR ports for FE ctx");
return -EINVAL;
}
if (rdi_count || ppp_count) {
CAM_ERR(CAM_ISP,
"%d RDI %d PPP ports invalid for FE ctx",
rdi_count, ppp_count);
return -EINVAL;
}
rc = cam_ife_hw_mgr_acquire_offline_res_ife_bus_rd(ife_ctx, in_port);
if (rc) {
CAM_ERR(CAM_ISP, "Acquire IFE BUS RD resource Failed");
goto err;
}
if (ipp_count)
rc = cam_ife_hw_mgr_acquire_offline_res_ife_camif(ife_ctx,
in_port, false, acquired_hw_id, acquired_hw_path);
if (rc) {
CAM_ERR(CAM_ISP, "Acquire IFE IPP SRC resource Failed");
goto err;
}
if (lcr_count)
rc = cam_ife_hw_mgr_acquire_offline_res_ife_camif(ife_ctx,
in_port, true, acquired_hw_id, acquired_hw_path);
if (rc) {
CAM_ERR(CAM_ISP, "Acquire IFE LCR SRC resource Failed");
goto err;
}
rc = cam_ife_hw_mgr_acquire_res_ife_out(ife_ctx, in_port);
if (rc) {
CAM_ERR(CAM_ISP, "Acquire IFE OUT resource Failed");
goto err;
}
*num_pix_port += ipp_count + lcr_count;
return 0;
err:
return rc;
}
static int cam_ife_mgr_acquire_hw_for_ctx(
struct cam_ife_hw_mgr_ctx *ife_ctx,
struct cam_isp_in_port_generic_info *in_port,
@ -2373,10 +2458,14 @@ static int cam_ife_mgr_acquire_hw_for_ctx(
cam_ife_hw_mgr_preprocess_port(ife_ctx, in_port, &ipp_count,
&rdi_count, &ppp_count, &ife_rd_count, &lcr_count);
if (!ipp_count && !rdi_count && !ppp_count && !ife_rd_count
&& !lcr_count) {
if (ife_rd_count) {
CAM_ERR(CAM_ISP, "Invalid BUS RD port for non-FE ctx");
return -EINVAL;
}
if (!ipp_count && !rdi_count && !ppp_count && !lcr_count) {
CAM_ERR(CAM_ISP,
"No PIX or RDI or PPP or IFE RD or LCR resource");
"No PIX or RDI or PPP or LCR resource");
return -EINVAL;
}
@ -2421,15 +2510,7 @@ static int cam_ife_mgr_acquire_hw_for_ctx(
}
/* get ife src resource */
if (ife_rd_count) {
rc = cam_ife_hw_mgr_acquire_res_ife_rd_src(ife_ctx, in_port);
rc = cam_ife_hw_mgr_acquire_res_bus_rd(ife_ctx, in_port);
if (rc) {
CAM_ERR(CAM_ISP, "Acquire IFE RD SRC resource Failed");
goto err;
}
} else if (ipp_count || ppp_count || rdi_count) {
if (ipp_count || ppp_count || rdi_count) {
rc = cam_ife_hw_mgr_acquire_res_ife_src(ife_ctx,
in_port, false,
acquired_hw_id, acquired_hw_path);
@ -2633,10 +2714,12 @@ static int cam_ife_mgr_acquire_get_unified_structure_v2(
if (port_info->num_valid_vc_dt == 0 ||
port_info->num_valid_vc_dt >= CAM_ISP_VC_DT_CFG) {
CAM_ERR(CAM_ISP, "Invalid i/p arg invalid vc-dt: %d",
in->num_valid_vc_dt);
rc = -EINVAL;
goto release_mem;
if (in->res_type != CAM_ISP_IFE_IN_RES_RD) {
CAM_ERR(CAM_ISP, "Invalid i/p arg invalid vc-dt: %d",
in->num_valid_vc_dt);
rc = -EINVAL;
goto release_mem;
}
}
for (i = 0; i < port_info->num_valid_vc_dt; i++) {
@ -2644,26 +2727,27 @@ static int cam_ife_mgr_acquire_get_unified_structure_v2(
port_info->dt[i] = in->dt[i];
}
port_info->format = in->format;
port_info->test_pattern = in->test_pattern;
port_info->usage_type = in->usage_type;
port_info->left_start = in->left_start;
port_info->left_stop = in->left_stop;
port_info->left_width = in->left_width;
port_info->right_start = in->right_start;
port_info->right_stop = in->right_stop;
port_info->right_width = in->right_width;
port_info->line_start = in->line_start;
port_info->line_stop = in->line_stop;
port_info->height = in->height;
port_info->pixel_clk = in->pixel_clk;
port_info->batch_size = in->batch_size;
port_info->dsp_mode = in->dsp_mode;
port_info->hbi_cnt = in->hbi_cnt;
port_info->cust_node = in->cust_node;
port_info->horizontal_bin = in->horizontal_bin;
port_info->qcfa_bin = in->qcfa_bin;
port_info->num_out_res = in->num_out_res;
port_info->format = in->format;
port_info->test_pattern = in->test_pattern;
port_info->usage_type = in->usage_type;
port_info->left_start = in->left_start;
port_info->left_stop = in->left_stop;
port_info->left_width = in->left_width;
port_info->right_start = in->right_start;
port_info->right_stop = in->right_stop;
port_info->right_width = in->right_width;
port_info->line_start = in->line_start;
port_info->line_stop = in->line_stop;
port_info->height = in->height;
port_info->pixel_clk = in->pixel_clk;
port_info->batch_size = in->batch_size;
port_info->dsp_mode = in->dsp_mode;
port_info->fe_unpacker_fmt = in->format;
port_info->hbi_cnt = in->hbi_cnt;
port_info->cust_node = in->cust_node;
port_info->horizontal_bin = in->horizontal_bin;
port_info->qcfa_bin = in->qcfa_bin;
port_info->num_out_res = in->num_out_res;
port_info->data = kcalloc(in->num_out_res,
sizeof(struct cam_isp_out_port_generic_info),
@ -2822,10 +2906,17 @@ static int cam_ife_mgr_acquire_hw(void *hw_mgr_priv, void *acquire_hw_args)
goto free_mem;
}
rc = cam_ife_mgr_acquire_hw_for_ctx(ife_ctx, in_port,
&num_pix_port_per_in, &num_rdi_port_per_in,
&acquire_args->acquired_hw_id[i],
acquire_args->acquired_hw_path[i]);
if (ife_ctx->is_fe_enabled)
rc = cam_ife_mgr_acquire_hw_for_fe_ctx(
ife_ctx, in_port,
&num_pix_port_per_in,
&acquire_args->acquired_hw_id[i],
acquire_args->acquired_hw_path[i]);
else
rc = cam_ife_mgr_acquire_hw_for_ctx(ife_ctx, in_port,
&num_pix_port_per_in, &num_rdi_port_per_in,
&acquire_args->acquired_hw_id[i],
acquire_args->acquired_hw_path[i]);
total_pix_port += num_pix_port_per_in;
total_rdi_port += num_rdi_port_per_in;
@ -2915,6 +3006,7 @@ void cam_ife_mgr_acquire_get_unified_dev_str(struct cam_isp_in_port_info *in,
gen_port_info->batch_size = in->batch_size;
gen_port_info->dsp_mode = in->dsp_mode;
gen_port_info->hbi_cnt = in->hbi_cnt;
gen_port_info->fe_unpacker_fmt = in->format;
gen_port_info->cust_node = 0;
gen_port_info->num_out_res = in->num_out_res;
@ -3788,11 +3880,6 @@ static int cam_ife_mgr_stop_hw(void *hw_mgr_priv, void *stop_hw_args)
for (i = 0; i < CAM_IFE_HW_OUT_RES_MAX; i++)
cam_ife_hw_mgr_stop_hw_res(&ctx->res_list_ife_out[i]);
/* IFE bus rd resources */
list_for_each_entry(hw_mgr_res, &ctx->res_list_ife_in_rd, list) {
cam_ife_hw_mgr_stop_hw_res(hw_mgr_res);
}
CAM_DBG(CAM_ISP, "Going to stop IFE Mux");
/* IFE mux in resources */
@ -3800,6 +3887,11 @@ static int cam_ife_mgr_stop_hw(void *hw_mgr_priv, void *stop_hw_args)
cam_ife_hw_mgr_stop_hw_res(hw_mgr_res);
}
/* IFE bus rd resources */
list_for_each_entry(hw_mgr_res, &ctx->res_list_ife_in_rd, list) {
cam_ife_hw_mgr_stop_hw_res(hw_mgr_res);
}
cam_tasklet_stop(ctx->common.tasklet_info);
cam_ife_mgr_pause_hw(ctx);
@ -4090,18 +4182,6 @@ start_only:
}
}
CAM_DBG(CAM_ISP, "START IFE BUS RD ... in ctx id:%d",
ctx->ctx_index);
/* Start the IFE mux in devices */
list_for_each_entry(hw_mgr_res, &ctx->res_list_ife_in_rd, list) {
rc = cam_ife_hw_mgr_start_hw_res(hw_mgr_res, ctx);
if (rc) {
CAM_ERR(CAM_ISP, "Can not start IFE BUS RD (%d)",
hw_mgr_res->res_id);
goto err;
}
}
if (primary_rdi_out_res < CAM_ISP_IFE_OUT_RES_MAX)
primary_rdi_src_res =
cam_convert_rdi_out_res_id_to_src(primary_rdi_out_res);
@ -4114,15 +4194,25 @@ start_only:
hw_mgr_res->hw_res[0]->rdi_only_ctx =
ctx->is_rdi_only_context;
}
rc = cam_ife_hw_mgr_start_hw_res(hw_mgr_res, ctx);
if (rc) {
CAM_ERR(CAM_ISP, "Can not start IFE MUX (%d)",
CAM_ERR(CAM_ISP, "Can not start IFE Mux (%d)",
hw_mgr_res->res_id);
goto err;
}
}
CAM_DBG(CAM_ISP, "START IFE BUS RD ... in ctx id:%d", ctx->ctx_index);
/* Start IFE Bus RD devices */
list_for_each_entry(hw_mgr_res, &ctx->res_list_ife_in_rd, list) {
rc = cam_ife_hw_mgr_start_hw_res(hw_mgr_res, ctx);
if (rc) {
CAM_ERR(CAM_ISP, "Can not start IFE BUS RD (%d)",
hw_mgr_res->res_id);
goto err;
}
}
CAM_DBG(CAM_ISP, "START CSID HW ... in ctx id:%d",
ctx->ctx_index);
/* Start the IFE CSID HW devices */
@ -5838,6 +5928,18 @@ static int cam_ife_mgr_prepare_hw_update(void *hw_mgr_priv,
}
}
/* add go_cmd for offline context */
if (prepare->num_out_map_entries && prepare->num_in_map_entries &&
ctx->is_offline) {
rc = cam_isp_add_go_cmd(prepare, &ctx->res_list_ife_in_rd,
ctx->base[i].idx, &kmd_buf);
if (rc)
CAM_ERR(CAM_ISP,
"Add GO_CMD faled i: %d, idx: %d, rc: %d",
i, ctx->base[i].idx, rc);
}
/*
* reg update will be done later for the initial configure.
* need to plus one to the op_code and only take the lower
@ -6075,7 +6177,10 @@ static int cam_ife_mgr_cmd(void *hw_mgr_priv, void *cmd_args)
isp_hw_cmd_args->u.sof_irq_enable);
break;
case CAM_ISP_HW_MGR_CMD_CTX_TYPE:
if (ctx->is_fe_enable)
if (ctx->is_fe_enabled && ctx->is_offline)
isp_hw_cmd_args->u.ctx_type =
CAM_ISP_CTX_OFFLINE;
else if (ctx->is_fe_enabled && !ctx->is_offline)
isp_hw_cmd_args->u.ctx_type = CAM_ISP_CTX_FS2;
else if (ctx->is_rdi_only_context)
isp_hw_cmd_args->u.ctx_type = CAM_ISP_CTX_RDI;
@ -6309,6 +6414,17 @@ end:
return rc;
}
static inline void cam_ife_hw_mgr_get_offline_sof_timestamp(
uint64_t *timestamp,
uint64_t *boot_time)
{
struct timespec64 ts;
ktime_get_boottime_ts64(&ts);
*timestamp = (uint64_t)((ts.tv_sec * 1000000000) + ts.tv_nsec);
*boot_time = *timestamp;
}
static int cam_ife_mgr_cmd_get_sof_timestamp(
struct cam_ife_hw_mgr_ctx *ife_ctx,
uint64_t *time_stamp,
@ -6681,6 +6797,7 @@ static int cam_ife_hw_mgr_handle_hw_rup(
case CAM_ISP_HW_VFE_IN_PDLIB:
case CAM_ISP_HW_VFE_IN_LCR:
case CAM_ISP_HW_VFE_IN_RD:
break;
default:
CAM_ERR_RATE_LIMIT(CAM_ISP, "Invalid res_id: %d",
@ -6810,6 +6927,8 @@ static int cam_ife_hw_mgr_handle_hw_sof(
struct cam_isp_hw_sof_event_data sof_done_event_data;
int rc = 0;
memset(&sof_done_event_data, 0, sizeof(sof_done_event_data));
ife_hw_irq_sof_cb =
ife_hw_mgr_ctx->common.event_cb[CAM_ISP_HW_EVENT_SOF];
@ -6820,10 +6939,15 @@ static int cam_ife_hw_mgr_handle_hw_sof(
rc = cam_ife_hw_mgr_check_irq_for_dual_vfe(ife_hw_mgr_ctx,
CAM_ISP_HW_EVENT_SOF);
if (!rc) {
cam_ife_mgr_cmd_get_sof_timestamp(
ife_hw_mgr_ctx,
&sof_done_event_data.timestamp,
&sof_done_event_data.boot_time);
if (ife_hw_mgr_ctx->is_offline)
cam_ife_hw_mgr_get_offline_sof_timestamp(
&sof_done_event_data.timestamp,
&sof_done_event_data.boot_time);
else
cam_ife_mgr_cmd_get_sof_timestamp(
ife_hw_mgr_ctx,
&sof_done_event_data.timestamp,
&sof_done_event_data.boot_time);
/* if frame header is enabled reset qtimer ts */
if (ife_hw_mgr_ctx->use_frame_header_ts)

View file

@ -82,12 +82,13 @@ struct cam_ife_hw_mgr_debug {
* @last_dump_flush_req_id Last req id for which reg dump on flush was called
* @last_dump_err_req_id Last req id for which reg dump on error was called
* @init_done indicate whether init hw is done
* @is_fe_enable indicate whether fetch engine\read path is enabled
* @is_fe_enabled Indicate whether fetch engine\read path is enabled
* @is_dual indicate whether context is in dual VFE mode
* @custom_enabled update the flag if context is connected to custom HW
* @use_frame_header_ts obtain qtimer ts using frame header
* @ts captured timestamp when the ctx is acquired
* @is_tpg indicate whether context is using PHY TPG
* @is_offline Indicate whether context is for offline IFE
*/
struct cam_ife_hw_mgr_ctx {
struct list_head list;
@ -133,12 +134,13 @@ struct cam_ife_hw_mgr_ctx {
uint64_t last_dump_flush_req_id;
uint64_t last_dump_err_req_id;
bool init_done;
bool is_fe_enable;
bool is_fe_enabled;
bool is_dual;
bool custom_enabled;
bool use_frame_header_ts;
struct timespec64 ts;
bool is_tpg;
bool is_offline;
};
/**

View file

@ -947,7 +947,7 @@ int cam_isp_add_reg_update(
return rc;
CAM_DBG(CAM_ISP, "Reg update added for res %d hw_id %d",
res->res_id, res->hw_intf->hw_idx);
res->res_type, res->hw_intf->hw_idx);
reg_update_size += get_regup.cmd.used_bytes;
}
}
@ -981,3 +981,100 @@ int cam_isp_add_reg_update(
return rc;
}
int cam_isp_add_go_cmd(
struct cam_hw_prepare_update_args *prepare,
struct list_head *res_list_isp_rd,
uint32_t base_idx,
struct cam_kmd_buf_info *kmd_buf_info)
{
int rc = -EINVAL;
struct cam_isp_resource_node *res;
struct cam_isp_hw_mgr_res *hw_mgr_res;
struct cam_hw_update_entry *hw_entry;
struct cam_isp_hw_get_cmd_update get_regup;
uint32_t kmd_buf_remain_size, num_ent, i, reg_update_size;
hw_entry = prepare->hw_update_entries;
if (prepare->num_hw_update_entries + 1 >=
prepare->max_hw_update_entries) {
CAM_ERR(CAM_ISP, "Insufficient HW entries current: %d max: %d",
prepare->num_hw_update_entries,
prepare->max_hw_update_entries);
return -EINVAL;
}
reg_update_size = 0;
list_for_each_entry(hw_mgr_res, res_list_isp_rd, list) {
if (hw_mgr_res->res_type == CAM_ISP_RESOURCE_UNINT)
continue;
for (i = 0; i < CAM_ISP_HW_SPLIT_MAX; i++) {
if (!hw_mgr_res->hw_res[i])
continue;
res = hw_mgr_res->hw_res[i];
if (res->hw_intf->hw_idx != base_idx)
continue;
if (kmd_buf_info->size > (kmd_buf_info->used_bytes +
reg_update_size)) {
kmd_buf_remain_size = kmd_buf_info->size -
(kmd_buf_info->used_bytes +
reg_update_size);
} else {
CAM_ERR(CAM_ISP, "no free mem %d %d %d",
base_idx, kmd_buf_info->size,
kmd_buf_info->used_bytes +
reg_update_size);
rc = -EINVAL;
return rc;
}
get_regup.cmd.cmd_buf_addr = kmd_buf_info->cpu_addr +
kmd_buf_info->used_bytes/4 +
reg_update_size/4;
get_regup.cmd.size = kmd_buf_remain_size;
get_regup.cmd_type = CAM_ISP_HW_CMD_FE_TRIGGER_CMD;
get_regup.res = res;
rc = res->process_cmd(res->res_priv,
CAM_ISP_HW_CMD_FE_TRIGGER_CMD, &get_regup,
sizeof(struct cam_isp_hw_get_cmd_update));
if (rc)
return rc;
CAM_DBG(CAM_ISP, "GO_CMD added for RD res %d hw_id %d",
res->res_type, res->hw_intf->hw_idx);
reg_update_size += get_regup.cmd.used_bytes;
}
}
if (reg_update_size) {
/* Update the HW entries */
num_ent = prepare->num_hw_update_entries;
prepare->hw_update_entries[num_ent].handle =
kmd_buf_info->handle;
prepare->hw_update_entries[num_ent].len = reg_update_size;
prepare->hw_update_entries[num_ent].offset =
kmd_buf_info->offset;
prepare->hw_update_entries[num_ent].flags =
CAM_ISP_IOCFG_BL;
CAM_DBG(CAM_ISP,
"num_ent=%d handle=0x%x, len=%u, offset=%u",
num_ent,
prepare->hw_update_entries[num_ent].handle,
prepare->hw_update_entries[num_ent].len,
prepare->hw_update_entries[num_ent].offset);
num_ent++;
kmd_buf_info->used_bytes += reg_update_size;
kmd_buf_info->offset += reg_update_size;
prepare->num_hw_update_entries = num_ent;
rc = 0;
}
return rc;
}

View file

@ -176,4 +176,23 @@ int cam_isp_add_reg_update(
uint32_t base_idx,
struct cam_kmd_buf_info *kmd_buf_info);
/*
* cam_isp_add_go_cmd()
*
* @brief Add go_cmd in the hw entries list for each rd source
*
* @prepare: Contain the packet and HW update variables
* @res_list_isp_rd: Resource list for BUS RD ports
* @base_idx: Base or dev index of the IFE/VFE HW instance
* @kmd_buf_info: Kmd buffer to store the change base command
* @return: 0 for success
* -EINVAL for Fail
*/
int cam_isp_add_go_cmd(
struct cam_hw_prepare_update_args *prepare,
struct list_head *res_list_isp_rd,
uint32_t base_idx,
struct cam_kmd_buf_info *kmd_buf_info);
#endif /*_CAM_ISP_HW_PARSER_H */

View file

@ -239,6 +239,7 @@ enum cam_isp_ctx_type {
CAM_ISP_CTX_FS2 = 1,
CAM_ISP_CTX_RDI,
CAM_ISP_CTX_PIX,
CAM_ISP_CTX_OFFLINE,
CAM_ISP_CTX_MAX,
};
/**

View file

@ -97,6 +97,7 @@ struct cam_isp_in_port_generic_info {
uint32_t batch_size;
uint32_t dsp_mode;
uint32_t hbi_cnt;
uint32_t fe_unpacker_fmt;
uint32_t cust_node;
uint32_t num_out_res;
uint32_t horizontal_bin;

View file

@ -77,8 +77,8 @@ enum cam_isp_resource_type {
CAM_ISP_RESOURCE_CID,
CAM_ISP_RESOURCE_PIX_PATH,
CAM_ISP_RESOURCE_VFE_IN,
CAM_ISP_RESOURCE_VFE_OUT,
CAM_ISP_RESOURCE_VFE_BUS_RD,
CAM_ISP_RESOURCE_VFE_OUT,
CAM_ISP_RESOURCE_TPG,
CAM_ISP_RESOURCE_TFE_IN,
CAM_ISP_RESOURCE_TFE_OUT,
@ -114,6 +114,7 @@ enum cam_isp_hw_cmd_type {
CAM_ISP_HW_CMD_TPG_PHY_CLOCK_UPDATE,
CAM_ISP_HW_CMD_GET_IRQ_REGISTER_DUMP,
CAM_ISP_HW_CMD_DUMP_HW,
CAM_ISP_HW_CMD_FE_TRIGGER_CMD,
CAM_ISP_HW_CMD_MAX,
};

View file

@ -102,6 +102,27 @@ struct cam_vfe_hw_get_hw_cap {
uint32_t max_rdi_num;
};
/*
* struct cam_vfe_hw_vfe_bus_rd_acquire_args:
*
* @rsrc_node: Pointer to Resource Node object, filled if acquire
* is successful
* @res_id: Unique Identity of port to associate with this
* resource.
* @is_dual: Flag to indicate dual VFE usecase
* @cdm_ops: CDM operations
* @unpacket_fmt: Unpacker format for read engine
* @is_offline: Flag to indicate offline usecase
*/
struct cam_vfe_hw_vfe_bus_rd_acquire_args {
struct cam_isp_resource_node *rsrc_node;
uint32_t res_id;
uint32_t is_dual;
struct cam_cdm_utils_ops *cdm_ops;
uint32_t unpacker_fmt;
bool is_offline;
};
/*
* struct cam_vfe_hw_vfe_out_acquire_args:
*
@ -143,6 +164,8 @@ struct cam_vfe_hw_vfe_out_acquire_args {
* @sync_mode: In case of Dual VFE, this is Master or Slave.
* (Default is Master in case of Single VFE)
* @in_port: Input port details to acquire
* @is_fe_enabled: Flag to indicate if FE is enabled
* @is_offline: Flag to indicate Offline IFE
*/
struct cam_vfe_hw_vfe_in_acquire_args {
struct cam_isp_resource_node *rsrc_node;
@ -152,6 +175,8 @@ struct cam_vfe_hw_vfe_in_acquire_args {
void *cdm_ops;
enum cam_isp_hw_sync_mode sync_mode;
struct cam_isp_in_port_generic_info *in_port;
bool is_fe_enabled;
bool is_offline;
};
/*
@ -173,9 +198,9 @@ struct cam_vfe_acquire_args {
void *priv;
cam_hw_mgr_event_cb_func event_cb;
union {
struct cam_vfe_hw_vfe_out_acquire_args vfe_out;
struct cam_vfe_hw_vfe_out_acquire_args vfe_bus_rd;
struct cam_vfe_hw_vfe_in_acquire_args vfe_in;
struct cam_vfe_hw_vfe_out_acquire_args vfe_out;
struct cam_vfe_hw_vfe_bus_rd_acquire_args vfe_bus_rd;
struct cam_vfe_hw_vfe_in_acquire_args vfe_in;
};
};

View file

@ -407,6 +407,7 @@ static struct cam_vfe_bus_rd_ver1_hw_info vfe175_130_bus_rd_hw_info = {
.max_height = -1,
},
},
.top_irq_shift = 23,
};
static struct cam_vfe_bus_ver2_hw_info vfe175_130_bus_hw_info = {

View file

@ -1360,6 +1360,7 @@ static struct cam_vfe_bus_rd_ver1_hw_info vfe480_bus_rd_hw_info = {
.max_height = -1,
},
},
.top_irq_shift = 8,
};
struct cam_vfe_hw_info cam_vfe480_hw_info = {

View file

@ -1,6 +1,6 @@
/* SPDX-License-Identifier: GPL-2.0-only */
/*
* Copyright (c) 2018-2019, The Linux Foundation. All rights reserved.
* Copyright (c) 2018-2020, The Linux Foundation. All rights reserved.
*/
#ifndef _CAM_VFE_BUS_R_VER1_H_
@ -88,6 +88,7 @@ struct cam_vfe_bus_rd_ver1_hw_info {
uint32_t num_bus_rd_resc;
struct cam_vfe_bus_rd_ver1_vfe_bus_hw_info
vfe_bus_rd_hw_info[CAM_VFE_BUS_RD_VER1_VFE_BUSRD_MAX];
uint32_t top_irq_shift;
};
/*

View file

@ -54,6 +54,8 @@ struct cam_vfe_mux_camif_ver3_data {
uint32_t qcfa_bin;
uint32_t dual_hw_idx;
uint32_t is_dual;
bool is_fe_enabled;
bool is_offline;
};
static int cam_vfe_camif_ver3_get_evt_payload(
@ -248,19 +250,20 @@ int cam_vfe_camif_ver3_acquire_resource(
return rc;
}
camif_data->sync_mode = acquire_data->vfe_in.sync_mode;
camif_data->pix_pattern = acquire_data->vfe_in.in_port->test_pattern;
camif_data->dsp_mode = acquire_data->vfe_in.in_port->dsp_mode;
camif_data->first_pixel = acquire_data->vfe_in.in_port->left_start;
camif_data->last_pixel = acquire_data->vfe_in.in_port->left_stop;
camif_data->first_line = acquire_data->vfe_in.in_port->line_start;
camif_data->last_line = acquire_data->vfe_in.in_port->line_stop;
camif_data->sync_mode = acquire_data->vfe_in.sync_mode;
camif_data->pix_pattern = acquire_data->vfe_in.in_port->test_pattern;
camif_data->dsp_mode = acquire_data->vfe_in.in_port->dsp_mode;
camif_data->first_pixel = acquire_data->vfe_in.in_port->left_start;
camif_data->last_pixel = acquire_data->vfe_in.in_port->left_stop;
camif_data->first_line = acquire_data->vfe_in.in_port->line_start;
camif_data->last_line = acquire_data->vfe_in.in_port->line_stop;
camif_data->is_fe_enabled = acquire_data->vfe_in.is_fe_enabled;
camif_data->is_offline = acquire_data->vfe_in.is_offline;
camif_data->event_cb = acquire_data->event_cb;
camif_data->priv = acquire_data->priv;
camif_data->qcfa_bin = acquire_data->vfe_in.in_port->qcfa_bin;
camif_data->horizontal_bin =
acquire_data->vfe_in.in_port->horizontal_bin;
camif_data->qcfa_bin = acquire_data->vfe_in.in_port->qcfa_bin;
camif_data->event_cb = acquire_data->event_cb;
camif_data->priv = acquire_data->priv;
camif_data->is_dual = acquire_data->vfe_in.is_dual;
if (acquire_data->vfe_in.is_dual)
camif_data->dual_hw_idx = acquire_data->vfe_in.dual_hw_idx;
@ -417,12 +420,20 @@ static int cam_vfe_camif_ver3_resource_start(
val |= (rsrc_data->cam_common_cfg.input_mux_sel_pp & 0x3) <<
CAM_SHIFT_TOP_CORE_CFG_INPUTMUX_PP;
if (rsrc_data->is_fe_enabled && !rsrc_data->is_offline)
val |= 0x2 << rsrc_data->reg_data->operating_mode_shift;
else
val |= 0x1 << rsrc_data->reg_data->operating_mode_shift;
if (rsrc_data->is_dual && rsrc_data->reg_data->dual_vfe_sync_mask) {
val |= (((rsrc_data->dual_hw_idx &
rsrc_data->reg_data->dual_vfe_sync_mask) + 1) <<
rsrc_data->reg_data->dual_ife_sync_sel_shift);
}
CAM_DBG(CAM_ISP, "VFE:%d TOP core_cfg: 0x%X",
camif_res->hw_intf->hw_idx, val);
cam_io_w_mb(val, rsrc_data->mem_base +
rsrc_data->common_reg->core_cfg_0);
@ -459,11 +470,14 @@ static int cam_vfe_camif_ver3_resource_start(
camif_res->res_state = CAM_ISP_RESOURCE_STATE_STREAMING;
/* Reg Update */
cam_io_w_mb(rsrc_data->reg_data->reg_update_cmd_data,
rsrc_data->mem_base + rsrc_data->camif_reg->reg_update_cmd);
CAM_DBG(CAM_ISP, "VFE:%d CAMIF RUP val:0x%X",
camif_res->hw_intf->hw_idx,
rsrc_data->reg_data->reg_update_cmd_data);
if (!rsrc_data->is_offline) {
cam_io_w_mb(rsrc_data->reg_data->reg_update_cmd_data,
rsrc_data->mem_base +
rsrc_data->camif_reg->reg_update_cmd);
CAM_DBG(CAM_ISP, "VFE:%d CAMIF RUP val:0x%X",
camif_res->hw_intf->hw_idx,
rsrc_data->reg_data->reg_update_cmd_data);
}
/* disable sof irq debug flag */
rsrc_data->enable_sof_irq_debug = false;
@ -606,6 +620,18 @@ static int cam_vfe_camif_ver3_reg_dump(
CAM_INFO(CAM_ISP, "offset 0x%X value 0x%X", offset, val);
}
CAM_INFO(CAM_ISP, "IFE:%d BUS RD", camif_res->hw_intf->hw_idx);
for (offset = 0xA800; offset <= 0xA89C; offset += 0x4) {
val = cam_soc_util_r(camif_priv->soc_info, 0, offset);
CAM_INFO(CAM_ISP, "offset 0x%X value 0x%X", offset, val);
if (offset == 0xA838)
offset = 0xA844;
if (offset == 0xA864)
offset = 0xA874;
if (offset == 0xA878)
offset = 0xA87C;
}
CAM_INFO(CAM_ISP, "IFE:%d BUS WR", camif_res->hw_intf->hw_idx);
for (offset = 0xAA00; offset <= 0xAADC; offset += 0x4) {
val = cam_soc_util_r(camif_priv->soc_info, 0, offset);