msm: camera: isp: Add support for offline IFE

This change adds new IRQ state machine and updates the acquire
logic to enable offline IFE. This change also adds the fixes
necessary to enable bus read for various buffer formats and
append go command at the end of each packet for offline
context.

CRs-Fixed: 2513939
Change-Id: Ie068670ed11aa6713e8f0cb817e4b5d4c209e696
Signed-off-by: Venkat Chinta <vchinta@codeaurora.org>
This commit is contained in:
Venkat Chinta
2020-02-04 16:18:46 -08:00
parent 131b4115d5
commit 8e79606ada
15 changed files with 1210 additions and 578 deletions

View File

@@ -1028,6 +1028,96 @@ static int __cam_isp_ctx_handle_buf_done_in_activated_state(
return rc; 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( static int __cam_isp_ctx_reg_upd_in_epoch_bubble_state(
struct cam_isp_context *ctx_isp, void *evt_data) struct cam_isp_context *ctx_isp, void *evt_data)
{ {
@@ -1811,6 +1901,9 @@ end:
} while (req->request_id < ctx_isp->last_applied_req_id); } 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) { if (ctx->ctx_crm_intf && ctx->ctx_crm_intf->notify_err) {
notify.link_hdl = ctx->link_hdl; notify.link_hdl = ctx->link_hdl;
notify.dev_hdl = ctx->dev_hdl; notify.dev_hdl = ctx->dev_hdl;
@@ -1861,6 +1954,7 @@ end:
CAM_DBG(CAM_ISP, "Exit"); CAM_DBG(CAM_ISP, "Exit");
exit:
return rc; 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( static int __cam_isp_ctx_apply_req_in_activated_state(
struct cam_context *ctx, struct cam_req_mgr_apply_request *apply, struct cam_context *ctx, struct cam_req_mgr_apply_request *apply,
enum cam_isp_ctx_activated_substate next_state) enum cam_isp_ctx_activated_substate next_state)
@@ -2796,6 +2947,7 @@ static int __cam_isp_ctx_flush_req_in_top_state(
end: end:
ctx_isp->bubble_frame_cnt = 0; ctx_isp->bubble_frame_cnt = 0;
atomic_set(&ctx_isp->process_bubble, 0); atomic_set(&ctx_isp->process_bubble, 0);
atomic_set(&ctx_isp->rxd_epoch, 0);
return rc; return rc;
} }
@@ -3685,8 +3837,11 @@ static int __cam_isp_ctx_config_dev_in_top_state(
ctx->state); ctx->state);
} }
} else { } else {
if (ctx->state != CAM_CTX_FLUSHED && ctx->state >= CAM_CTX_READY if (ctx_isp->offline_context) {
&& ctx->ctx_crm_intf->add_req) { __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.link_hdl = ctx->link_hdl;
add_req.dev_hdl = ctx->dev_hdl; add_req.dev_hdl = ctx->dev_hdl;
add_req.req_id = req->request_id; 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", "Preprocessing Config req_id %lld successful on ctx %u",
req->request_id, ctx->ctx_id); 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; return rc;
put_ref: 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; cam_isp_ctx_rdi_only_activated_state_machine;
ctx_isp->rdi_only_context = true; ctx_isp->rdi_only_context = true;
} else if (isp_hw_cmd_args.u.ctx_type == CAM_ISP_CTX_FS2) { } 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 = ctx_isp->substate_machine_irq =
cam_isp_ctx_fs2_state_machine_irq; cam_isp_ctx_fs2_state_machine_irq;
ctx_isp->substate_machine = ctx_isp->substate_machine =
cam_isp_ctx_fs2_state_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 { } else {
CAM_DBG(CAM_ISP, "Session has PIX or PIX and RDI resources"); CAM_DBG(CAM_ISP, "Session has PIX or PIX and RDI resources");
ctx_isp->substate_machine_irq = 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; cam_isp_ctx_rdi_only_activated_state_machine;
ctx_isp->rdi_only_context = true; ctx_isp->rdi_only_context = true;
} else if (isp_hw_cmd_args.u.ctx_type == CAM_ISP_CTX_FS2) { } 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 = ctx_isp->substate_machine_irq =
cam_isp_ctx_fs2_state_machine_irq; cam_isp_ctx_fs2_state_machine_irq;
ctx_isp->substate_machine = ctx_isp->substate_machine =
cam_isp_ctx_fs2_state_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 { } else {
CAM_DBG(CAM_ISP, "Session has PIX or PIX and RDI resources"); CAM_DBG(CAM_ISP, "Session has PIX or PIX and RDI resources");
ctx_isp->substate_machine_irq = 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; cam_isp_ctx_rdi_only_activated_state_machine;
ctx_isp->rdi_only_context = true; ctx_isp->rdi_only_context = true;
} else if (isp_hw_cmd_args.u.ctx_type == CAM_ISP_CTX_FS2) { } 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 = ctx_isp->substate_machine_irq =
cam_isp_ctx_fs2_state_machine_irq; cam_isp_ctx_fs2_state_machine_irq;
ctx_isp->substate_machine = ctx_isp->substate_machine =
cam_isp_ctx_fs2_state_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 { } else {
CAM_DBG(CAM_ISP, "Session has PIX or PIX and RDI resources"); CAM_DBG(CAM_ISP, "Session has PIX or PIX and RDI resources");
ctx_isp->substate_machine_irq = 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); 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; ctx->state = CAM_CTX_READY;
trace_cam_context_state("ISP", ctx); 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; start_isp.start_only = false;
atomic_set(&ctx_isp->process_bubble, 0); atomic_set(&ctx_isp->process_bubble, 0);
atomic_set(&ctx_isp->rxd_epoch, 0);
ctx_isp->frame_id = 0; ctx_isp->frame_id = 0;
ctx_isp->active_req_cnt = 0; ctx_isp->active_req_cnt = 0;
ctx_isp->reported_req_id = 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); 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); 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 { } else {
list_add_tail(&req->list, &ctx->active_req_list); list_add_tail(&req->list, &ctx->active_req_list);
ctx_isp->active_req_cnt++; 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->last_applied_req_id = 0;
ctx_isp->req_info.last_bufdone_req_id = 0; ctx_isp->req_info.last_bufdone_req_id = 0;
atomic_set(&ctx_isp->process_bubble, 0); atomic_set(&ctx_isp->process_bubble, 0);
atomic_set(&ctx_isp->rxd_epoch, 0);
atomic64_set(&ctx_isp->state_monitor_head, -1); atomic64_set(&ctx_isp->state_monitor_head, -1);
for (i = 0; i < CAM_ISP_CTX_EVENT_MAX; i++) 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 * @event_record: Event record array
* @rdi_only_context: Get context type information. * @rdi_only_context: Get context type information.
* true, if context is rdi only context * true, if context is rdi only context
* @offline_context: Indicate whether context is for offline IFE
* @hw_acquired: Indicate whether HW resources are acquired * @hw_acquired: Indicate whether HW resources are acquired
* @init_received: Indicate whether init config packet is received * @init_received: Indicate whether init config packet is received
* @split_acquire: Indicate whether a separate acquire is expected * @split_acquire: Indicate whether a separate acquire is expected
* @custom_enabled: Custom HW enabled for this ctx * @custom_enabled: Custom HW enabled for this ctx
* @use_frame_header_ts: Use frame header for qtimer ts * @use_frame_header_ts: Use frame header for qtimer ts
* @init_timestamp: Timestamp at which this context is initialized * @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 { struct cam_isp_context {
@@ -286,6 +289,7 @@ struct cam_isp_context {
struct cam_isp_context_event_record event_record[ struct cam_isp_context_event_record event_record[
CAM_ISP_CTX_EVENT_MAX][CAM_ISP_CTX_EVENT_RECORD_MAX_ENTRIES]; CAM_ISP_CTX_EVENT_MAX][CAM_ISP_CTX_EVENT_RECORD_MAX_ENTRIES];
bool rdi_only_context; bool rdi_only_context;
bool offline_context;
bool hw_acquired; bool hw_acquired;
bool init_received; bool init_received;
bool split_acquire; bool split_acquire;
@@ -293,6 +297,7 @@ struct cam_isp_context {
bool use_frame_header_ts; bool use_frame_header_ts;
unsigned int init_timestamp; unsigned int init_timestamp;
uint32_t isp_device_type; 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; 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( static int cam_ife_hw_mgr_acquire_res_ife_out_rdi(
struct cam_ife_hw_mgr_ctx *ife_ctx, struct cam_ife_hw_mgr_ctx *ife_ctx,
struct cam_isp_hw_mgr_res *ife_src_res, struct cam_isp_hw_mgr_res *ife_src_res,
@@ -1297,125 +1213,6 @@ err:
return rc; 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) static int cam_convert_hw_idx_to_ife_hw_num(int hw_idx)
{ {
uint32_t hw_version, rc = 0; 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.tasklet = ife_ctx->common.tasklet_info;
vfe_acquire.vfe_in.cdm_ops = ife_ctx->cdm_ops; vfe_acquire.vfe_in.cdm_ops = ife_ctx->cdm_ops;
vfe_acquire.vfe_in.in_port = in_port; 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.priv = ife_ctx;
vfe_acquire.event_cb = cam_ife_hw_mgr_event_handler; 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 */ /* Acquire Left if not already acquired */
/* For dual IFE cases, start acquiring the lower idx first */ /* 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, rc = cam_ife_hw_mgr_acquire_csid_hw(ife_hw_mgr,
&csid_acquire, true); &csid_acquire, true);
else 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.res_id = in_port->res_type;
ife_ctx->res_list_ife_in.is_dual_isp = in_port->usage_type; ife_ctx->res_list_ife_in.is_dual_isp = in_port->usage_type;
} else if ((ife_ctx->res_list_ife_in.res_id != } 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"); CAM_ERR(CAM_ISP, "No Free resource for this context");
goto err; goto err;
} else { } 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, CAM_DBG(CAM_ISP, "in_port%d res_type %d", i,
in_port->res_type); in_port->res_type);
if (in_port->res_type == CAM_ISP_IFE_IN_RES_RD) { if (in_port->res_type == CAM_ISP_IFE_IN_RES_RD) {
ife_ctx->is_fe_enable = true; ife_ctx->is_fe_enabled = true;
break; break;
} }
in_port = (struct cam_isp_in_port_info *)((uint8_t *)in_port + in_port = (struct cam_isp_in_port_info *)((uint8_t *)in_port +
in_port_length); 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; 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, CAM_DBG(CAM_ISP, "in_port%d res_type %d", i,
in_port->res_type); in_port->res_type);
if (in_port->res_type == CAM_ISP_IFE_IN_RES_RD) { 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; break;
} }
in_port = (struct cam_isp_in_port_info_v2 *) in_port = (struct cam_isp_in_port_info_v2 *)
((uint8_t *)in_port + in_port_length); ((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; return 0;
} }
@@ -2316,22 +2118,21 @@ static int cam_ife_hw_mgr_preprocess_port(
ife_hw_mgr = ife_ctx->hw_mgr; 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++; ife_rd_num++;
} else {
for (i = 0; i < in_port->num_out_res; i++) { for (i = 0; i < in_port->num_out_res; i++) {
out_port = &in_port->data[i]; out_port = &in_port->data[i];
if (cam_ife_hw_mgr_is_rdi_res(out_port->res_type)) if (cam_ife_hw_mgr_is_rdi_res(out_port->res_type))
rdi_num++; rdi_num++;
else if (out_port->res_type == CAM_ISP_IFE_OUT_RES_2PD) else if (out_port->res_type == CAM_ISP_IFE_OUT_RES_2PD)
ppp_num++; ppp_num++;
else if (out_port->res_type == CAM_ISP_IFE_OUT_RES_LCR) else if (out_port->res_type == CAM_ISP_IFE_OUT_RES_LCR)
lcr_num++; lcr_num++;
else { else {
CAM_DBG(CAM_ISP, "out_res_type %d", CAM_DBG(CAM_ISP, "out_res_type %d",
out_port->res_type); out_port->res_type);
ipp_num++; ipp_num++;
}
} }
} }
@@ -2347,6 +2148,290 @@ static int cam_ife_hw_mgr_preprocess_port(
return 0; 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( static int cam_ife_mgr_acquire_hw_for_ctx(
struct cam_ife_hw_mgr_ctx *ife_ctx, struct cam_ife_hw_mgr_ctx *ife_ctx,
struct cam_isp_in_port_generic_info *in_port, 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, cam_ife_hw_mgr_preprocess_port(ife_ctx, in_port, &ipp_count,
&rdi_count, &ppp_count, &ife_rd_count, &lcr_count); &rdi_count, &ppp_count, &ife_rd_count, &lcr_count);
if (!ipp_count && !rdi_count && !ppp_count && !ife_rd_count if (ife_rd_count) {
&& !lcr_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, 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; return -EINVAL;
} }
@@ -2421,15 +2510,7 @@ static int cam_ife_mgr_acquire_hw_for_ctx(
} }
/* get ife src resource */ /* get ife src resource */
if (ife_rd_count) { if (ipp_count || ppp_count || rdi_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) {
rc = cam_ife_hw_mgr_acquire_res_ife_src(ife_ctx, rc = cam_ife_hw_mgr_acquire_res_ife_src(ife_ctx,
in_port, false, in_port, false,
acquired_hw_id, acquired_hw_path); 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 || if (port_info->num_valid_vc_dt == 0 ||
port_info->num_valid_vc_dt >= CAM_ISP_VC_DT_CFG) { port_info->num_valid_vc_dt >= CAM_ISP_VC_DT_CFG) {
CAM_ERR(CAM_ISP, "Invalid i/p arg invalid vc-dt: %d", if (in->res_type != CAM_ISP_IFE_IN_RES_RD) {
in->num_valid_vc_dt); CAM_ERR(CAM_ISP, "Invalid i/p arg invalid vc-dt: %d",
rc = -EINVAL; in->num_valid_vc_dt);
goto release_mem; rc = -EINVAL;
goto release_mem;
}
} }
for (i = 0; i < port_info->num_valid_vc_dt; i++) { 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->dt[i] = in->dt[i];
} }
port_info->format = in->format; port_info->format = in->format;
port_info->test_pattern = in->test_pattern; port_info->test_pattern = in->test_pattern;
port_info->usage_type = in->usage_type; port_info->usage_type = in->usage_type;
port_info->left_start = in->left_start; port_info->left_start = in->left_start;
port_info->left_stop = in->left_stop; port_info->left_stop = in->left_stop;
port_info->left_width = in->left_width; port_info->left_width = in->left_width;
port_info->right_start = in->right_start; port_info->right_start = in->right_start;
port_info->right_stop = in->right_stop; port_info->right_stop = in->right_stop;
port_info->right_width = in->right_width; port_info->right_width = in->right_width;
port_info->line_start = in->line_start; port_info->line_start = in->line_start;
port_info->line_stop = in->line_stop; port_info->line_stop = in->line_stop;
port_info->height = in->height; port_info->height = in->height;
port_info->pixel_clk = in->pixel_clk; port_info->pixel_clk = in->pixel_clk;
port_info->batch_size = in->batch_size; port_info->batch_size = in->batch_size;
port_info->dsp_mode = in->dsp_mode; port_info->dsp_mode = in->dsp_mode;
port_info->hbi_cnt = in->hbi_cnt; port_info->fe_unpacker_fmt = in->format;
port_info->cust_node = in->cust_node; port_info->hbi_cnt = in->hbi_cnt;
port_info->horizontal_bin = in->horizontal_bin; port_info->cust_node = in->cust_node;
port_info->qcfa_bin = in->qcfa_bin; port_info->horizontal_bin = in->horizontal_bin;
port_info->num_out_res = in->num_out_res; port_info->qcfa_bin = in->qcfa_bin;
port_info->num_out_res = in->num_out_res;
port_info->data = kcalloc(in->num_out_res, port_info->data = kcalloc(in->num_out_res,
sizeof(struct cam_isp_out_port_generic_info), 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; goto free_mem;
} }
rc = cam_ife_mgr_acquire_hw_for_ctx(ife_ctx, in_port, if (ife_ctx->is_fe_enabled)
&num_pix_port_per_in, &num_rdi_port_per_in, rc = cam_ife_mgr_acquire_hw_for_fe_ctx(
&acquire_args->acquired_hw_id[i], ife_ctx, in_port,
acquire_args->acquired_hw_path[i]); &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_pix_port += num_pix_port_per_in;
total_rdi_port += num_rdi_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->batch_size = in->batch_size;
gen_port_info->dsp_mode = in->dsp_mode; gen_port_info->dsp_mode = in->dsp_mode;
gen_port_info->hbi_cnt = in->hbi_cnt; 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->cust_node = 0;
gen_port_info->num_out_res = in->num_out_res; 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++) for (i = 0; i < CAM_IFE_HW_OUT_RES_MAX; i++)
cam_ife_hw_mgr_stop_hw_res(&ctx->res_list_ife_out[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"); CAM_DBG(CAM_ISP, "Going to stop IFE Mux");
/* IFE mux in resources */ /* 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); 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_tasklet_stop(ctx->common.tasklet_info);
cam_ife_mgr_pause_hw(ctx); 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) if (primary_rdi_out_res < CAM_ISP_IFE_OUT_RES_MAX)
primary_rdi_src_res = primary_rdi_src_res =
cam_convert_rdi_out_res_id_to_src(primary_rdi_out_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 = hw_mgr_res->hw_res[0]->rdi_only_ctx =
ctx->is_rdi_only_context; ctx->is_rdi_only_context;
} }
rc = cam_ife_hw_mgr_start_hw_res(hw_mgr_res, ctx); rc = cam_ife_hw_mgr_start_hw_res(hw_mgr_res, ctx);
if (rc) { 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); hw_mgr_res->res_id);
goto err; 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", CAM_DBG(CAM_ISP, "START CSID HW ... in ctx id:%d",
ctx->ctx_index); ctx->ctx_index);
/* Start the IFE CSID HW devices */ /* 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. * reg update will be done later for the initial configure.
* need to plus one to the op_code and only take the lower * 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); isp_hw_cmd_args->u.sof_irq_enable);
break; break;
case CAM_ISP_HW_MGR_CMD_CTX_TYPE: 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; isp_hw_cmd_args->u.ctx_type = CAM_ISP_CTX_FS2;
else if (ctx->is_rdi_only_context) else if (ctx->is_rdi_only_context)
isp_hw_cmd_args->u.ctx_type = CAM_ISP_CTX_RDI; isp_hw_cmd_args->u.ctx_type = CAM_ISP_CTX_RDI;
@@ -6309,6 +6414,17 @@ end:
return rc; 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( static int cam_ife_mgr_cmd_get_sof_timestamp(
struct cam_ife_hw_mgr_ctx *ife_ctx, struct cam_ife_hw_mgr_ctx *ife_ctx,
uint64_t *time_stamp, 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_PDLIB:
case CAM_ISP_HW_VFE_IN_LCR: case CAM_ISP_HW_VFE_IN_LCR:
case CAM_ISP_HW_VFE_IN_RD:
break; break;
default: default:
CAM_ERR_RATE_LIMIT(CAM_ISP, "Invalid res_id: %d", 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; struct cam_isp_hw_sof_event_data sof_done_event_data;
int rc = 0; int rc = 0;
memset(&sof_done_event_data, 0, sizeof(sof_done_event_data));
ife_hw_irq_sof_cb = ife_hw_irq_sof_cb =
ife_hw_mgr_ctx->common.event_cb[CAM_ISP_HW_EVENT_SOF]; 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, rc = cam_ife_hw_mgr_check_irq_for_dual_vfe(ife_hw_mgr_ctx,
CAM_ISP_HW_EVENT_SOF); CAM_ISP_HW_EVENT_SOF);
if (!rc) { if (!rc) {
cam_ife_mgr_cmd_get_sof_timestamp( if (ife_hw_mgr_ctx->is_offline)
ife_hw_mgr_ctx, cam_ife_hw_mgr_get_offline_sof_timestamp(
&sof_done_event_data.timestamp, &sof_done_event_data.timestamp,
&sof_done_event_data.boot_time); &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 frame header is enabled reset qtimer ts */
if (ife_hw_mgr_ctx->use_frame_header_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_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 * @last_dump_err_req_id Last req id for which reg dump on error was called
* @init_done indicate whether init hw is done * @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 * @is_dual indicate whether context is in dual VFE mode
* @custom_enabled update the flag if context is connected to custom HW * @custom_enabled update the flag if context is connected to custom HW
* @use_frame_header_ts obtain qtimer ts using frame header * @use_frame_header_ts obtain qtimer ts using frame header
* @ts captured timestamp when the ctx is acquired * @ts captured timestamp when the ctx is acquired
* @is_tpg indicate whether context is using PHY TPG * @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 cam_ife_hw_mgr_ctx {
struct list_head list; 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_flush_req_id;
uint64_t last_dump_err_req_id; uint64_t last_dump_err_req_id;
bool init_done; bool init_done;
bool is_fe_enable; bool is_fe_enabled;
bool is_dual; bool is_dual;
bool custom_enabled; bool custom_enabled;
bool use_frame_header_ts; bool use_frame_header_ts;
struct timespec64 ts; struct timespec64 ts;
bool is_tpg; bool is_tpg;
bool is_offline;
}; };
/** /**

View File

@@ -947,7 +947,7 @@ int cam_isp_add_reg_update(
return rc; return rc;
CAM_DBG(CAM_ISP, "Reg update added for res %d hw_id %d", 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; reg_update_size += get_regup.cmd.used_bytes;
} }
} }
@@ -981,3 +981,100 @@ int cam_isp_add_reg_update(
return rc; 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, uint32_t base_idx,
struct cam_kmd_buf_info *kmd_buf_info); 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 */ #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_FS2 = 1,
CAM_ISP_CTX_RDI, CAM_ISP_CTX_RDI,
CAM_ISP_CTX_PIX, CAM_ISP_CTX_PIX,
CAM_ISP_CTX_OFFLINE,
CAM_ISP_CTX_MAX, CAM_ISP_CTX_MAX,
}; };
/** /**

View File

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

View File

@@ -77,8 +77,8 @@ enum cam_isp_resource_type {
CAM_ISP_RESOURCE_CID, CAM_ISP_RESOURCE_CID,
CAM_ISP_RESOURCE_PIX_PATH, CAM_ISP_RESOURCE_PIX_PATH,
CAM_ISP_RESOURCE_VFE_IN, CAM_ISP_RESOURCE_VFE_IN,
CAM_ISP_RESOURCE_VFE_OUT,
CAM_ISP_RESOURCE_VFE_BUS_RD, CAM_ISP_RESOURCE_VFE_BUS_RD,
CAM_ISP_RESOURCE_VFE_OUT,
CAM_ISP_RESOURCE_TPG, CAM_ISP_RESOURCE_TPG,
CAM_ISP_RESOURCE_TFE_IN, CAM_ISP_RESOURCE_TFE_IN,
CAM_ISP_RESOURCE_TFE_OUT, 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_TPG_PHY_CLOCK_UPDATE,
CAM_ISP_HW_CMD_GET_IRQ_REGISTER_DUMP, CAM_ISP_HW_CMD_GET_IRQ_REGISTER_DUMP,
CAM_ISP_HW_CMD_DUMP_HW, CAM_ISP_HW_CMD_DUMP_HW,
CAM_ISP_HW_CMD_FE_TRIGGER_CMD,
CAM_ISP_HW_CMD_MAX, CAM_ISP_HW_CMD_MAX,
}; };

View File

@@ -102,6 +102,27 @@ struct cam_vfe_hw_get_hw_cap {
uint32_t max_rdi_num; 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: * 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. * @sync_mode: In case of Dual VFE, this is Master or Slave.
* (Default is Master in case of Single VFE) * (Default is Master in case of Single VFE)
* @in_port: Input port details to acquire * @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_vfe_hw_vfe_in_acquire_args {
struct cam_isp_resource_node *rsrc_node; struct cam_isp_resource_node *rsrc_node;
@@ -152,6 +175,8 @@ struct cam_vfe_hw_vfe_in_acquire_args {
void *cdm_ops; void *cdm_ops;
enum cam_isp_hw_sync_mode sync_mode; enum cam_isp_hw_sync_mode sync_mode;
struct cam_isp_in_port_generic_info *in_port; 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; void *priv;
cam_hw_mgr_event_cb_func event_cb; cam_hw_mgr_event_cb_func event_cb;
union { union {
struct cam_vfe_hw_vfe_out_acquire_args vfe_out; 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_bus_rd_acquire_args vfe_bus_rd;
struct cam_vfe_hw_vfe_in_acquire_args vfe_in; 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, .max_height = -1,
}, },
}, },
.top_irq_shift = 23,
}; };
static struct cam_vfe_bus_ver2_hw_info vfe175_130_bus_hw_info = { 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, .max_height = -1,
}, },
}, },
.top_irq_shift = 8,
}; };
struct cam_vfe_hw_info cam_vfe480_hw_info = { struct cam_vfe_hw_info cam_vfe480_hw_info = {

View File

@@ -1,6 +1,6 @@
/* SPDX-License-Identifier: GPL-2.0-only */ /* 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_ #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; uint32_t num_bus_rd_resc;
struct cam_vfe_bus_rd_ver1_vfe_bus_hw_info struct cam_vfe_bus_rd_ver1_vfe_bus_hw_info
vfe_bus_rd_hw_info[CAM_VFE_BUS_RD_VER1_VFE_BUSRD_MAX]; 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 qcfa_bin;
uint32_t dual_hw_idx; uint32_t dual_hw_idx;
uint32_t is_dual; uint32_t is_dual;
bool is_fe_enabled;
bool is_offline;
}; };
static int cam_vfe_camif_ver3_get_evt_payload( static int cam_vfe_camif_ver3_get_evt_payload(
@@ -248,19 +250,20 @@ int cam_vfe_camif_ver3_acquire_resource(
return rc; return rc;
} }
camif_data->sync_mode = acquire_data->vfe_in.sync_mode; camif_data->sync_mode = acquire_data->vfe_in.sync_mode;
camif_data->pix_pattern = acquire_data->vfe_in.in_port->test_pattern; 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->dsp_mode = acquire_data->vfe_in.in_port->dsp_mode;
camif_data->first_pixel = acquire_data->vfe_in.in_port->left_start; 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->last_pixel = acquire_data->vfe_in.in_port->left_stop;
camif_data->first_line = acquire_data->vfe_in.in_port->line_start; 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->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 = camif_data->horizontal_bin =
acquire_data->vfe_in.in_port->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) if (acquire_data->vfe_in.is_dual)
camif_data->dual_hw_idx = acquire_data->vfe_in.dual_hw_idx; 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) << val |= (rsrc_data->cam_common_cfg.input_mux_sel_pp & 0x3) <<
CAM_SHIFT_TOP_CORE_CFG_INPUTMUX_PP; 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) { if (rsrc_data->is_dual && rsrc_data->reg_data->dual_vfe_sync_mask) {
val |= (((rsrc_data->dual_hw_idx & val |= (((rsrc_data->dual_hw_idx &
rsrc_data->reg_data->dual_vfe_sync_mask) + 1) << rsrc_data->reg_data->dual_vfe_sync_mask) + 1) <<
rsrc_data->reg_data->dual_ife_sync_sel_shift); 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 + cam_io_w_mb(val, rsrc_data->mem_base +
rsrc_data->common_reg->core_cfg_0); 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; camif_res->res_state = CAM_ISP_RESOURCE_STATE_STREAMING;
/* Reg Update */ /* Reg Update */
cam_io_w_mb(rsrc_data->reg_data->reg_update_cmd_data, if (!rsrc_data->is_offline) {
rsrc_data->mem_base + rsrc_data->camif_reg->reg_update_cmd); cam_io_w_mb(rsrc_data->reg_data->reg_update_cmd_data,
CAM_DBG(CAM_ISP, "VFE:%d CAMIF RUP val:0x%X", rsrc_data->mem_base +
camif_res->hw_intf->hw_idx, rsrc_data->camif_reg->reg_update_cmd);
rsrc_data->reg_data->reg_update_cmd_data); 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 */ /* disable sof irq debug flag */
rsrc_data->enable_sof_irq_debug = false; 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, "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); CAM_INFO(CAM_ISP, "IFE:%d BUS WR", camif_res->hw_intf->hw_idx);
for (offset = 0xAA00; offset <= 0xAADC; offset += 0x4) { for (offset = 0xAA00; offset <= 0xAADC; offset += 0x4) {
val = cam_soc_util_r(camif_priv->soc_info, 0, offset); val = cam_soc_util_r(camif_priv->soc_info, 0, offset);