diff --git a/drivers/cam_isp/cam_isp_context.c b/drivers/cam_isp/cam_isp_context.c index 02f51ff13c..0e9918f80f 100644 --- a/drivers/cam_isp/cam_isp_context.c +++ b/drivers/cam_isp/cam_isp_context.c @@ -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++) diff --git a/drivers/cam_isp/cam_isp_context.h b/drivers/cam_isp/cam_isp_context.h index 94c61af5e0..beec13e3ff 100644 --- a/drivers/cam_isp/cam_isp_context.h +++ b/drivers/cam_isp/cam_isp_context.h @@ -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; }; /** diff --git a/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c b/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c index c6e5e9d752..d12a375daf 100644 --- a/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c +++ b/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c @@ -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) diff --git a/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.h b/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.h index 91caeb314f..627c7fc780 100644 --- a/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.h +++ b/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.h @@ -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; }; /** diff --git a/drivers/cam_isp/isp_hw_mgr/hw_utils/cam_isp_packet_parser.c b/drivers/cam_isp/isp_hw_mgr/hw_utils/cam_isp_packet_parser.c index b6027db649..15b01a3558 100644 --- a/drivers/cam_isp/isp_hw_mgr/hw_utils/cam_isp_packet_parser.c +++ b/drivers/cam_isp/isp_hw_mgr/hw_utils/cam_isp_packet_parser.c @@ -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; +} + diff --git a/drivers/cam_isp/isp_hw_mgr/hw_utils/include/cam_isp_packet_parser.h b/drivers/cam_isp/isp_hw_mgr/hw_utils/include/cam_isp_packet_parser.h index ca56b155e9..92632b689a 100644 --- a/drivers/cam_isp/isp_hw_mgr/hw_utils/include/cam_isp_packet_parser.h +++ b/drivers/cam_isp/isp_hw_mgr/hw_utils/include/cam_isp_packet_parser.h @@ -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 */ diff --git a/drivers/cam_isp/isp_hw_mgr/include/cam_isp_hw_mgr_intf.h b/drivers/cam_isp/isp_hw_mgr/include/cam_isp_hw_mgr_intf.h index f68a6ec3a8..9ee05756c3 100644 --- a/drivers/cam_isp/isp_hw_mgr/include/cam_isp_hw_mgr_intf.h +++ b/drivers/cam_isp/isp_hw_mgr/include/cam_isp_hw_mgr_intf.h @@ -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, }; /** diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/include/cam_ife_csid_hw_intf.h b/drivers/cam_isp/isp_hw_mgr/isp_hw/include/cam_ife_csid_hw_intf.h index c242bdaa17..78c457b6a7 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/include/cam_ife_csid_hw_intf.h +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/include/cam_ife_csid_hw_intf.h @@ -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; diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/include/cam_isp_hw.h b/drivers/cam_isp/isp_hw_mgr/isp_hw/include/cam_isp_hw.h index 02c1948e90..2f00b14769 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/include/cam_isp_hw.h +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/include/cam_isp_hw.h @@ -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, }; diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/include/cam_vfe_hw_intf.h b/drivers/cam_isp/isp_hw_mgr/isp_hw/include/cam_vfe_hw_intf.h index c3f2aabf56..531e695583 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/include/cam_vfe_hw_intf.h +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/include/cam_vfe_hw_intf.h @@ -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; }; }; diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe175_130.h b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe175_130.h index 1a80dc7f8f..946ac2267d 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe175_130.h +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe175_130.h @@ -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 = { diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe480.h b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe480.h index 0cd59de02f..18a0071bf0 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe480.h +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe17x/cam_vfe480.h @@ -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 = { diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_rd_ver1.c b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_rd_ver1.c index 28e4218a7b..3f7ce6a4a5 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_rd_ver1.c +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_rd_ver1.c @@ -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. */ #include @@ -39,24 +39,29 @@ static const char drv_name[] = "vfe_bus_rd"; buf_array[(index)++] = val; \ } while (0) +#define BUS_RD_VER1_DEFAULT_LATENCY_BUF_ALLOC 512 + enum cam_vfe_bus_rd_ver1_unpacker_format { - BUS_RD_VER1_PACKER_FMT_PLAIN_128 = 0x0, - BUS_RD_VER1_PACKER_FMT_PLAIN_8 = 0x1, - BUS_RD_VER1_PACKER_FMT_PLAIN_16_10BPP = 0x2, - BUS_RD_VER1_PACKER_FMT_PLAIN_16_12BPP = 0x3, - BUS_RD_VER1_PACKER_FMT_PLAIN_16_14BPP = 0x4, - BUS_RD_VER1_PACKER_FMT_PLAIN_16_16BPP = 0x5, - BUS_RD_VER1_PACKER_FMT_ARGB_10 = 0x6, - BUS_RD_VER1_PACKER_FMT_ARGB_12 = 0x7, - BUS_RD_VER1_PACKER_FMT_ARGB_14 = 0x8, - BUS_RD_VER1_PACKER_FMT_PLAIN_32_20BPP = 0x9, - BUS_RD_VER1_PACKER_FMT_PLAIN_64 = 0xA, - BUS_RD_VER1_PACKER_FMT_TP_10 = 0xB, - BUS_RD_VER1_PACKER_FMT_PLAIN_32_32BPP = 0xC, - BUS_RD_VER1_PACKER_FMT_PLAIN_8_ODD_EVEN = 0xD, - BUS_RD_VER1_PACKER_FMT_PLAIN_8_LSB_MSB_10 = 0xE, - BUS_RD_VER1_PACKER_FMT_PLAIN_8_LSB_MSB_10_ODD_EVEN = 0xF, - BUS_RD_VER1_PACKER_FMT_MAX = 0xF, + BUS_RD_VER1_UNPACKER_FMT_PLAIN_128 = 0x0, + BUS_RD_VER1_UNPACKER_FMT_PLAIN_8 = 0x1, + BUS_RD_VER1_UNPACKER_FMT_PLAIN_16_10BPP = 0x2, + BUS_RD_VER1_UNPACKER_FMT_PLAIN_16_12BPP = 0x3, + BUS_RD_VER1_UNPACKER_FMT_PLAIN_16_14BPP = 0x4, + BUS_RD_VER1_UNPACKER_FMT_PLAIN_32_20BPP = 0x5, + BUS_RD_VER1_UNPACKER_FMT_ARGB_10 = 0x6, + BUS_RD_VER1_UNPACKER_FMT_ARGB_12 = 0x7, + BUS_RD_VER1_UNPACKER_FMT_ARGB_14 = 0x8, + BUS_RD_VER1_UNPACKER_FMT_PLAIN_32 = 0x9, + BUS_RD_VER1_UNPACKER_FMT_PLAIN_64 = 0xA, + BUS_RD_VER1_UNPACKER_FMT_TP_10 = 0xB, + BUS_RD_VER1_UNPACKER_FMT_MIPI8 = 0xC, + BUS_RD_VER1_UNPACKER_FMT_MIPI10 = 0xD, + BUS_RD_VER1_UNPACKER_FMT_MIPI12 = 0xE, + BUS_RD_VER1_UNPACKER_FMT_MIPI14 = 0xF, + BUS_RD_VER1_UNPACKER_FMT_PLAIN_16_16BPP = 0x10, + BUS_RD_VER1_UNPACKER_FMT_PLAIN_128_ODD_EVEN = 0x11, + BUS_RD_VER1_UNPACKER_FMT_PLAIN_8_ODD_EVEN = 0x12, + BUS_RD_VER1_UNPACKER_FMT_MAX = 0x13, }; struct cam_vfe_bus_rd_ver1_common_data { @@ -76,6 +81,7 @@ struct cam_vfe_bus_rd_ver1_common_data { uint32_t num_sec_out; uint32_t fs_sync_enable; uint32_t go_cmd_sel; + cam_hw_mgr_event_cb_func event_cb; }; struct cam_vfe_bus_rd_ver1_rm_resource_data { @@ -85,7 +91,6 @@ struct cam_vfe_bus_rd_ver1_rm_resource_data { void *ctx; bool init_cfg_done; - bool hfr_cfg_done; uint32_t offset; @@ -127,12 +132,16 @@ struct cam_vfe_bus_rd_ver1_vfe_bus_rd_data { uint32_t max_height; struct cam_cdm_utils_ops *cdm_util_ops; uint32_t secure_mode; + int irq_handle; + void *priv; + uint32_t status; + bool is_offline; }; struct cam_vfe_bus_rd_ver1_priv { struct cam_vfe_bus_rd_ver1_common_data common_data; - uint32_t num_client; - uint32_t num_bus_rd_resc; + uint32_t num_client; + uint32_t num_bus_rd_resc; struct cam_isp_resource_node bus_client[ CAM_VFE_BUS_RD_VER1_MAX_CLIENTS]; @@ -140,32 +149,105 @@ struct cam_vfe_bus_rd_ver1_priv { CAM_VFE_BUS_RD_VER1_VFE_BUSRD_MAX]; int irq_handle; - int error_irq_handle; + void *tasklet_info; + uint32_t top_irq_shift; }; -static int cam_vfe_bus_process_cmd( +static int cam_vfe_bus_rd_process_cmd( struct cam_isp_resource_node *priv, uint32_t cmd_type, void *cmd_args, uint32_t arg_size); +static void cam_vfe_bus_rd_pxls_to_bytes(uint32_t pxls, uint32_t fmt, + uint32_t *bytes) +{ + switch (fmt) { + case BUS_RD_VER1_UNPACKER_FMT_PLAIN_128: + *bytes = pxls * 16; + break; + case BUS_RD_VER1_UNPACKER_FMT_PLAIN_8: + case BUS_RD_VER1_UNPACKER_FMT_PLAIN_8_ODD_EVEN: + case BUS_RD_VER1_UNPACKER_FMT_PLAIN_16_10BPP: + case BUS_RD_VER1_UNPACKER_FMT_PLAIN_16_12BPP: + case BUS_RD_VER1_UNPACKER_FMT_PLAIN_16_14BPP: + case BUS_RD_VER1_UNPACKER_FMT_PLAIN_16_16BPP: + case BUS_RD_VER1_UNPACKER_FMT_ARGB_10: + case BUS_RD_VER1_UNPACKER_FMT_ARGB_12: + case BUS_RD_VER1_UNPACKER_FMT_ARGB_14: + *bytes = pxls * 2; + break; + case BUS_RD_VER1_UNPACKER_FMT_PLAIN_32_20BPP: + case BUS_RD_VER1_UNPACKER_FMT_PLAIN_32: + *bytes = pxls * 4; + break; + case BUS_RD_VER1_UNPACKER_FMT_PLAIN_64: + *bytes = pxls * 8; + break; + case BUS_RD_VER1_UNPACKER_FMT_TP_10: + *bytes = ALIGNUP(pxls, 3) * 4 / 3; + break; + case BUS_RD_VER1_UNPACKER_FMT_MIPI8: + *bytes = pxls; + break; + case BUS_RD_VER1_UNPACKER_FMT_MIPI10: + *bytes = ALIGNUP(pxls * 5, 4) / 4; + break; + case BUS_RD_VER1_UNPACKER_FMT_MIPI12: + *bytes = ALIGNUP(pxls * 3, 2) / 2; + break; + case BUS_RD_VER1_UNPACKER_FMT_MIPI14: + *bytes = ALIGNUP(pxls * 7, 4) / 4; + break; + default: + CAM_ERR(CAM_ISP, "Invalid unpacker_fmt:%d", fmt); + break; + } +} + static enum cam_vfe_bus_rd_ver1_unpacker_format cam_vfe_bus_get_unpacker_fmt(uint32_t unpack_fmt) { switch (unpack_fmt) { + case CAM_FORMAT_PLAIN128: + return BUS_RD_VER1_UNPACKER_FMT_PLAIN_128; + case CAM_FORMAT_PLAIN8: + return BUS_RD_VER1_UNPACKER_FMT_PLAIN_8; + case CAM_FORMAT_PLAIN16_10: + return BUS_RD_VER1_UNPACKER_FMT_PLAIN_16_10BPP; + case CAM_FORMAT_PLAIN16_12: + return BUS_RD_VER1_UNPACKER_FMT_PLAIN_16_12BPP; + case CAM_FORMAT_PLAIN16_14: + return BUS_RD_VER1_UNPACKER_FMT_PLAIN_16_14BPP; + case CAM_FORMAT_PLAIN32_20: + return BUS_RD_VER1_UNPACKER_FMT_PLAIN_32_20BPP; + case CAM_FORMAT_ARGB_10: + return BUS_RD_VER1_UNPACKER_FMT_ARGB_10; + case CAM_FORMAT_ARGB_12: + return BUS_RD_VER1_UNPACKER_FMT_ARGB_12; + case CAM_FORMAT_ARGB_14: + return BUS_RD_VER1_UNPACKER_FMT_ARGB_14; + case CAM_FORMAT_PLAIN32: + case CAM_FORMAT_ARGB: + return BUS_RD_VER1_UNPACKER_FMT_PLAIN_32; + case CAM_FORMAT_PLAIN64: + case CAM_FORMAT_ARGB_16: + case CAM_FORMAT_PD10: + return BUS_RD_VER1_UNPACKER_FMT_PLAIN_64; + case CAM_FORMAT_TP10: + return BUS_RD_VER1_UNPACKER_FMT_TP_10; + case CAM_FORMAT_MIPI_RAW_8: + return BUS_RD_VER1_UNPACKER_FMT_MIPI8; case CAM_FORMAT_MIPI_RAW_10: - return BUS_RD_VER1_PACKER_FMT_PLAIN_8_ODD_EVEN; + return BUS_RD_VER1_UNPACKER_FMT_MIPI10; + case CAM_FORMAT_MIPI_RAW_12: + return BUS_RD_VER1_UNPACKER_FMT_MIPI12; + case CAM_FORMAT_MIPI_RAW_14: + return BUS_RD_VER1_UNPACKER_FMT_MIPI14; + case CAM_FORMAT_PLAIN16_16: + return BUS_RD_VER1_UNPACKER_FMT_PLAIN_16_16BPP; + case CAM_FORMAT_PLAIN8_SWAP: + return BUS_RD_VER1_UNPACKER_FMT_PLAIN_8_ODD_EVEN; default: - return BUS_RD_VER1_PACKER_FMT_MAX; - } -} - -static bool cam_vfe_bus_can_be_secure(uint32_t out_type) -{ - switch (out_type) { - case CAM_VFE_BUS_RD_VER1_VFE_BUSRD_RDI0: - return false; - - default: - return false; + return BUS_RD_VER1_UNPACKER_FMT_MAX; } } @@ -187,12 +269,58 @@ static int cam_vfe_bus_get_num_rm( case CAM_VFE_BUS_RD_VER1_VFE_BUSRD_RDI0: return 1; default: - break; + CAM_ERR(CAM_ISP, "Unsupported resource_type %u", res_type); + return -EINVAL; + } +} + +static int cam_vfe_bus_rd_handle_irq_top_half(uint32_t evt_id, + struct cam_irq_th_payload *th_payload) +{ + struct cam_isp_resource_node *bus_rd = NULL; + struct cam_vfe_bus_rd_ver1_vfe_bus_rd_data *rsrc_data = NULL; + + bus_rd = th_payload->handler_priv; + if (!bus_rd) { + CAM_ERR_RATE_LIMIT(CAM_ISP, "No resource"); + return -ENODEV; + } + rsrc_data = bus_rd->res_priv; + rsrc_data->status = th_payload->evt_status_arr[0]; + + CAM_DBG(CAM_ISP, "VFE:%d Bus RD IRQ status_0: 0x%X", + rsrc_data->common_data->core_index, + th_payload->evt_status_arr[0]); + + return 0; +} + +static int cam_vfe_bus_rd_handle_irq_bottom_half( + void *handler_priv, void *evt_payload_priv) +{ + struct cam_isp_resource_node *bus_rd = NULL; + struct cam_vfe_bus_rd_ver1_vfe_bus_rd_data *rsrc_data = NULL; + + bus_rd = (struct cam_isp_resource_node *)handler_priv; + if (!bus_rd) { + CAM_ERR_RATE_LIMIT(CAM_ISP, "No resource"); + return -ENODEV; + } + rsrc_data = bus_rd->res_priv; + + if (rsrc_data->status & 0x2) + CAM_DBG(CAM_ISP, "Received VFE:%d BUS RD RUP", + rsrc_data->common_data->core_index); + else if (rsrc_data->status & 0x4) + CAM_DBG(CAM_ISP, "Received VFE:%d BUS RD BUF DONE", + rsrc_data->common_data->core_index); + else if (rsrc_data->status & 0x10000) { + CAM_ERR(CAM_ISP, "Received VFE:%d BUS RD CCIF Violation", + rsrc_data->common_data->core_index); + return CAM_VFE_IRQ_STATUS_VIOLATION; } - CAM_ERR(CAM_ISP, "Unsupported resource_type %u", - res_type); - return -EINVAL; + return CAM_VFE_IRQ_STATUS_SUCCESS; } static int cam_vfe_bus_get_rm_idx( @@ -219,19 +347,18 @@ static int cam_vfe_bus_get_rm_idx( } static int cam_vfe_bus_acquire_rm( - struct cam_vfe_bus_rd_ver1_priv *ver1_bus_rd_priv, - struct cam_isp_out_port_generic_info *out_port_info, - void *tasklet, - void *ctx, - enum cam_vfe_bus_rd_ver1_vfe_bus_rd_type vfe_bus_rd_res_id, - enum cam_vfe_bus_plane_type plane, - uint32_t subscribe_irq, - struct cam_isp_resource_node **rm_res, - uint32_t *client_done_mask, - uint32_t is_dual) + struct cam_vfe_bus_rd_ver1_priv *ver1_bus_rd_priv, + void *tasklet, + void *ctx, + enum cam_vfe_bus_rd_ver1_vfe_bus_rd_type vfe_bus_rd_res_id, + enum cam_vfe_bus_plane_type plane, + struct cam_isp_resource_node **rm_res, + uint32_t *client_done_mask, + uint32_t is_dual, + uint32_t unpacker_fmt) { - uint32_t rm_idx = 0; - struct cam_isp_resource_node *rm_res_local = NULL; + uint32_t rm_idx = 0; + struct cam_isp_resource_node *rm_res_local = NULL; struct cam_vfe_bus_rd_ver1_rm_resource_data *rsrc_data = NULL; *rm_res = NULL; @@ -240,14 +367,15 @@ static int cam_vfe_bus_acquire_rm( /* No need to allocate for BUS VER2. VFE OUT to RM is fixed. */ rm_idx = cam_vfe_bus_get_rm_idx(vfe_bus_rd_res_id, plane); if (rm_idx < 0 || rm_idx >= ver1_bus_rd_priv->num_client) { - CAM_ERR(CAM_ISP, "Unsupported VFE out %d plane %d", + CAM_ERR(CAM_ISP, "Unsupported VFE RM:%d plane:%d", vfe_bus_rd_res_id, plane); return -EINVAL; } rm_res_local = &ver1_bus_rd_priv->bus_client[rm_idx]; if (rm_res_local->res_state != CAM_ISP_RESOURCE_STATE_AVAILABLE) { - CAM_ERR(CAM_ISP, "RM res not available state:%d", + CAM_ERR(CAM_ISP, "VFE:%d RM:%d res not available state:%d", + ver1_bus_rd_priv->common_data.core_index, rm_idx, rm_res_local->res_state); return -EALREADY; } @@ -257,18 +385,22 @@ static int cam_vfe_bus_acquire_rm( rsrc_data = rm_res_local->res_priv; rsrc_data->ctx = ctx; rsrc_data->is_dual = is_dual; + rsrc_data->unpacker_cfg = cam_vfe_bus_get_unpacker_fmt(unpacker_fmt); + rsrc_data->latency_buf_allocation = + BUS_RD_VER1_DEFAULT_LATENCY_BUF_ALLOC; /* Set RM offset value to default */ rsrc_data->offset = 0; - *client_done_mask = (1 << rm_idx); + *client_done_mask = (1 << (rm_idx + 2)); *rm_res = rm_res_local; - CAM_DBG(CAM_ISP, "RM %d: Acquired"); + CAM_DBG(CAM_ISP, "VFE:%d RM:%d Acquired", + rsrc_data->common_data->core_index, rsrc_data->index); return 0; } -static int cam_vfe_bus_release_rm(void *bus_priv, - struct cam_isp_resource_node *rm_res) +static int cam_vfe_bus_release_rm(void *bus_priv, + struct cam_isp_resource_node *rm_res) { struct cam_vfe_bus_rd_ver1_rm_resource_data *rsrc_data = rm_res->res_priv; @@ -281,68 +413,49 @@ static int cam_vfe_bus_release_rm(void *bus_priv, rsrc_data->unpacker_cfg = 0; rsrc_data->burst_len = 0; rsrc_data->init_cfg_done = false; - rsrc_data->hfr_cfg_done = false; rsrc_data->en_cfg = 0; rsrc_data->is_dual = 0; rm_res->tasklet_info = NULL; rm_res->res_state = CAM_ISP_RESOURCE_STATE_AVAILABLE; + CAM_DBG(CAM_ISP, "VFE:%d RM:%d released", + rsrc_data->common_data->core_index, rsrc_data->index); return 0; } static int cam_vfe_bus_start_rm(struct cam_isp_resource_node *rm_res) { - int rc = 0; - struct cam_vfe_bus_rd_ver1_rm_resource_data *rm_data = - rm_res->res_priv; - struct cam_vfe_bus_rd_ver1_common_data *common_data = - rm_data->common_data; - uint32_t buf_size; - uint32_t val; - uint32_t offset; + struct cam_vfe_bus_rd_ver1_rm_resource_data *rm_data; + struct cam_vfe_bus_rd_ver1_common_data *common_data; + uint32_t buf_size; - CAM_DBG(CAM_ISP, "w: 0x%x", rm_data->width); - CAM_DBG(CAM_ISP, "h: 0x%x", rm_data->height); - CAM_DBG(CAM_ISP, "format: 0x%x", rm_data->format); - CAM_DBG(CAM_ISP, "unpacker_cfg: 0x%x", rm_data->unpacker_cfg); - CAM_DBG(CAM_ISP, "latency_buf_allocation: 0x%x", - rm_data->latency_buf_allocation); - CAM_DBG(CAM_ISP, "stride: 0x%x", rm_data->stride); - CAM_DBG(CAM_ISP, "go_cmd_sel: 0x%x", rm_data->go_cmd_sel); - CAM_DBG(CAM_ISP, "fs_sync_enable: 0x%x", rm_data->fs_sync_enable); - CAM_DBG(CAM_ISP, "hbi_count: 0x%x", rm_data->hbi_count); - CAM_DBG(CAM_ISP, "fs_line_sync_en: 0x%x", rm_data->fs_line_sync_en); - CAM_DBG(CAM_ISP, "fs_mode: 0x%x", rm_data->fs_mode); - CAM_DBG(CAM_ISP, "min_vbi: 0x%x", rm_data->min_vbi); + rm_data = rm_res->res_priv; + common_data = rm_data->common_data; - /* Write All the values*/ - offset = rm_data->hw_regs->buf_size; buf_size = ((rm_data->width)&(0x0000FFFF)) | ((rm_data->height<<16)&(0xFFFF0000)); - cam_io_w_mb(buf_size, common_data->mem_base + offset); - CAM_DBG(CAM_ISP, "buf_size: 0x%x", buf_size); + cam_io_w_mb(buf_size, common_data->mem_base + + rm_data->hw_regs->buf_size); + cam_io_w_mb(rm_data->width, common_data->mem_base + + rm_data->hw_regs->stride); + cam_io_w_mb(rm_data->unpacker_cfg, common_data->mem_base + + rm_data->hw_regs->unpacker_cfg); + cam_io_w_mb(rm_data->latency_buf_allocation, common_data->mem_base + + rm_data->hw_regs->latency_buf_allocation); + cam_io_w_mb(0x1, common_data->mem_base + rm_data->hw_regs->cfg); - val = rm_data->width; - offset = rm_data->hw_regs->stride; - CAM_DBG(CAM_ISP, "offset:0x%x, value:0x%x", offset, val); - cam_io_w_mb(val, common_data->mem_base + offset); + rm_res->res_state = CAM_ISP_RESOURCE_STATE_STREAMING; - CAM_DBG(CAM_ISP, "rm_data->unpacker_cfg:0x%x", rm_data->unpacker_cfg); - val = cam_vfe_bus_get_unpacker_fmt(rm_data->unpacker_cfg); - CAM_DBG(CAM_ISP, " value:0x%x", val); - offset = rm_data->hw_regs->unpacker_cfg; - CAM_DBG(CAM_ISP, "offset:0x%x, value:0x%x", offset, val); - cam_io_w_mb(val, common_data->mem_base + offset); + CAM_DBG(CAM_ISP, + "Start VFE:%d RM:%d offset:0x%X en_cfg:0x%X width:%d height:%d", + rm_data->common_data->core_index, rm_data->index, + (uint32_t) rm_data->hw_regs->cfg, rm_data->en_cfg, + rm_data->width, rm_data->height); + CAM_DBG(CAM_ISP, "RM:%d pk_fmt:%d stride:%d", rm_data->index, + rm_data->unpacker_cfg, rm_data->stride); - val = rm_data->latency_buf_allocation; - offset = rm_data->hw_regs->latency_buf_allocation; - CAM_DBG(CAM_ISP, "offset:0x%x, value:0x%x", offset, val); - cam_io_w_mb(val, common_data->mem_base + offset); - - cam_io_w_mb(0x1, common_data->mem_base + - rm_data->hw_regs->cfg); - return rc; + return 0; } static int cam_vfe_bus_stop_rm(struct cam_isp_resource_node *rm_res) @@ -354,12 +467,13 @@ static int cam_vfe_bus_stop_rm(struct cam_isp_resource_node *rm_res) rsrc_data->common_data; /* Disable RM */ - cam_io_w_mb(0x0, - common_data->mem_base + rsrc_data->hw_regs->cfg); + cam_io_w_mb(0x0, common_data->mem_base + rsrc_data->hw_regs->cfg); rm_res->res_state = CAM_ISP_RESOURCE_STATE_RESERVED; rsrc_data->init_cfg_done = false; - rsrc_data->hfr_cfg_done = false; + + CAM_DBG(CAM_ISP, "VFE:%d RM:%d stopped", + rsrc_data->common_data->core_index, rsrc_data->index); return rc; } @@ -374,7 +488,8 @@ static int cam_vfe_bus_init_rm_resource(uint32_t index, rsrc_data = kzalloc(sizeof(struct cam_vfe_bus_rd_ver1_rm_resource_data), GFP_KERNEL); if (!rsrc_data) { - CAM_DBG(CAM_ISP, "Failed to alloc for RM res priv"); + CAM_DBG(CAM_ISP, "Failed to alloc VFE:%d RM res priv", + ver1_bus_rd_priv->common_data.core_index); return -ENOMEM; } rm_res->res_priv = rsrc_data; @@ -390,7 +505,6 @@ static int cam_vfe_bus_init_rm_resource(uint32_t index, rm_res->stop = cam_vfe_bus_stop_rm; rm_res->hw_intf = ver1_bus_rd_priv->common_data.hw_intf; - return 0; } @@ -430,15 +544,13 @@ static int cam_vfe_bus_acquire_vfe_bus_rd(void *bus_priv, void *acquire_args, int i; enum cam_vfe_bus_rd_ver1_vfe_bus_rd_type bus_rd_res_id; int num_rm; - uint32_t subscribe_irq; uint32_t client_done_mask; struct cam_vfe_bus_rd_ver1_priv *ver1_bus_rd_priv = bus_priv; struct cam_vfe_acquire_args *acq_args = acquire_args; - struct cam_vfe_hw_vfe_out_acquire_args *bus_rd_acquire_args; + struct cam_vfe_hw_vfe_bus_rd_acquire_args *bus_rd_acquire_args; struct cam_isp_resource_node *rsrc_node = NULL; struct cam_vfe_bus_rd_ver1_vfe_bus_rd_data *rsrc_data = NULL; - uint32_t secure_caps = 0, mode; if (!bus_priv || !acquire_args) { CAM_ERR(CAM_ISP, "Invalid Param"); @@ -447,9 +559,6 @@ static int cam_vfe_bus_acquire_vfe_bus_rd(void *bus_priv, void *acquire_args, bus_rd_acquire_args = &acq_args->vfe_bus_rd; - CAM_DBG(CAM_ISP, "Acquiring resource type 0x%x", - acq_args->rsrc_type); - bus_rd_res_id = cam_vfe_bus_get_bus_rd_res_id( acq_args->rsrc_type); if (bus_rd_res_id == CAM_VFE_BUS_RD_VER1_VFE_BUSRD_MAX) @@ -461,61 +570,40 @@ static int cam_vfe_bus_acquire_vfe_bus_rd(void *bus_priv, void *acquire_args, rsrc_node = &ver1_bus_rd_priv->vfe_bus_rd[bus_rd_res_id]; if (rsrc_node->res_state != CAM_ISP_RESOURCE_STATE_AVAILABLE) { - CAM_ERR(CAM_ISP, "Resource not available: Res_id %d state:%d", - bus_rd_res_id, rsrc_node->res_state); + CAM_ERR(CAM_ISP, "VFE:%d RM:0x%x not available state:%d", + ver1_bus_rd_priv->common_data.core_index, + acq_args->rsrc_type, rsrc_node->res_state); return -EBUSY; } + rsrc_node->res_id = acq_args->rsrc_type; rsrc_data = rsrc_node->res_priv; - secure_caps = cam_vfe_bus_can_be_secure( - rsrc_data->bus_rd_type); - mode = bus_rd_acquire_args->out_port_info->secure_mode; - mutex_lock(&rsrc_data->common_data->bus_mutex); - if (secure_caps) { - if (!rsrc_data->common_data->num_sec_out) { - rsrc_data->secure_mode = mode; - rsrc_data->common_data->secure_mode = mode; - } else { - if (mode == rsrc_data->common_data->secure_mode) { - rsrc_data->secure_mode = - rsrc_data->common_data->secure_mode; - } else { - rc = -EINVAL; - CAM_ERR_RATE_LIMIT(CAM_ISP, - "Mismatch: Acquire mode[%d], drvr mode[%d]", - rsrc_data->common_data->secure_mode, - mode); - mutex_unlock( - &rsrc_data->common_data->bus_mutex); - return -EINVAL; - } - } - rsrc_data->common_data->num_sec_out++; - } - mutex_unlock(&rsrc_data->common_data->bus_mutex); + CAM_DBG(CAM_ISP, "VFE:%d acquire RD type:0x%x", + rsrc_data->common_data->core_index, acq_args->rsrc_type); rsrc_data->num_rm = num_rm; rsrc_node->tasklet_info = acq_args->tasklet; + ver1_bus_rd_priv->tasklet_info = acq_args->tasklet; rsrc_node->cdm_ops = bus_rd_acquire_args->cdm_ops; rsrc_data->cdm_util_ops = bus_rd_acquire_args->cdm_ops; - - subscribe_irq = 1; + rsrc_data->common_data->event_cb = acq_args->event_cb; + rsrc_data->priv = acq_args->priv; + rsrc_data->is_offline = bus_rd_acquire_args->is_offline; for (i = 0; i < num_rm; i++) { rc = cam_vfe_bus_acquire_rm(ver1_bus_rd_priv, - bus_rd_acquire_args->out_port_info, acq_args->tasklet, acq_args->priv, bus_rd_res_id, i, - subscribe_irq, &rsrc_data->rm_res[i], &client_done_mask, - bus_rd_acquire_args->is_dual); + bus_rd_acquire_args->is_dual, + bus_rd_acquire_args->unpacker_fmt); if (rc) { CAM_ERR(CAM_ISP, - "VFE%d RM acquire failed for Out %d rc=%d", + "VFE:%d RM:%d acquire failed rc:%d", rsrc_data->common_data->core_index, bus_rd_res_id, rc); goto release_rm; @@ -525,7 +613,8 @@ static int cam_vfe_bus_acquire_vfe_bus_rd(void *bus_priv, void *acquire_args, rsrc_node->res_state = CAM_ISP_RESOURCE_STATE_RESERVED; bus_rd_acquire_args->rsrc_node = rsrc_node; - CAM_DBG(CAM_ISP, "Acquire successful"); + CAM_DBG(CAM_ISP, "VFE:%d acquire RD 0x%x successful", + rsrc_data->common_data->core_index, acq_args->rsrc_type); return rc; release_rm: @@ -540,7 +629,6 @@ static int cam_vfe_bus_release_vfe_bus_rd(void *bus_priv, void *release_args, uint32_t i; struct cam_isp_resource_node *vfe_bus_rd = NULL; struct cam_vfe_bus_rd_ver1_vfe_bus_rd_data *rsrc_data = NULL; - uint32_t secure_caps = 0; if (!bus_priv || !release_args) { CAM_ERR(CAM_ISP, "Invalid input bus_priv %pK release_args %pK", @@ -552,8 +640,10 @@ static int cam_vfe_bus_release_vfe_bus_rd(void *bus_priv, void *release_args, rsrc_data = vfe_bus_rd->res_priv; if (vfe_bus_rd->res_state != CAM_ISP_RESOURCE_STATE_RESERVED) { - CAM_ERR(CAM_ISP, "Invalid resource state:%d", - vfe_bus_rd->res_state); + CAM_ERR(CAM_ISP, + "VFE:%d RD type:0x%x invalid resource state:%d", + rsrc_data->common_data->core_index, + vfe_bus_rd->res_id, vfe_bus_rd->res_state); } for (i = 0; i < rsrc_data->num_rm; i++) @@ -564,32 +654,6 @@ static int cam_vfe_bus_release_vfe_bus_rd(void *bus_priv, void *release_args, vfe_bus_rd->cdm_ops = NULL; rsrc_data->cdm_util_ops = NULL; - secure_caps = cam_vfe_bus_can_be_secure(rsrc_data->bus_rd_type); - mutex_lock(&rsrc_data->common_data->bus_mutex); - if (secure_caps) { - if (rsrc_data->secure_mode == - rsrc_data->common_data->secure_mode) { - rsrc_data->common_data->num_sec_out--; - rsrc_data->secure_mode = - CAM_SECURE_MODE_NON_SECURE; - } else { - /* - * The validity of the mode is properly - * checked while acquiring the output port. - * not expected to reach here, unless there is - * some corruption. - */ - CAM_ERR(CAM_ISP, "driver[%d],resource[%d] mismatch", - rsrc_data->common_data->secure_mode, - rsrc_data->secure_mode); - } - - if (!rsrc_data->common_data->num_sec_out) - rsrc_data->common_data->secure_mode = - CAM_SECURE_MODE_NON_SECURE; - } - mutex_unlock(&rsrc_data->common_data->bus_mutex); - if (vfe_bus_rd->res_state == CAM_ISP_RESOURCE_STATE_RESERVED) vfe_bus_rd->res_state = CAM_ISP_RESOURCE_STATE_AVAILABLE; @@ -597,31 +661,56 @@ static int cam_vfe_bus_release_vfe_bus_rd(void *bus_priv, void *release_args, } static int cam_vfe_bus_start_vfe_bus_rd( - struct cam_isp_resource_node *vfe_out) + struct cam_isp_resource_node *vfe_bus_rd) { int rc = 0, i; - struct cam_vfe_bus_rd_ver1_vfe_bus_rd_data *rsrc_data = NULL; - struct cam_vfe_bus_rd_ver1_common_data *common_data = NULL; + struct cam_vfe_bus_rd_ver1_vfe_bus_rd_data *rsrc_data = NULL; + struct cam_vfe_bus_rd_ver1_common_data *common_data = NULL; + uint32_t irq_reg_mask[1] = {0x6}, val = 0; - if (!vfe_out) { + if (!vfe_bus_rd) { CAM_ERR(CAM_ISP, "Invalid input"); return -EINVAL; } - rsrc_data = vfe_out->res_priv; + rsrc_data = vfe_bus_rd->res_priv; common_data = rsrc_data->common_data; - CAM_DBG(CAM_ISP, "Start resource type: %x", rsrc_data->bus_rd_type); + CAM_DBG(CAM_ISP, "VFE:%d start RD type:0x%x", vfe_bus_rd->res_id); - if (vfe_out->res_state != CAM_ISP_RESOURCE_STATE_RESERVED) { + if (vfe_bus_rd->res_state != CAM_ISP_RESOURCE_STATE_RESERVED) { CAM_ERR(CAM_ISP, "Invalid resource state:%d", - vfe_out->res_state); + vfe_bus_rd->res_state); return -EACCES; } + if (!rsrc_data->is_offline) { + val = (common_data->fs_sync_enable << 5) | + (common_data->go_cmd_sel << 4); + cam_io_w_mb(val, common_data->mem_base + + common_data->common_reg->input_if_cmd); + } + for (i = 0; i < rsrc_data->num_rm; i++) rc = cam_vfe_bus_start_rm(rsrc_data->rm_res[i]); - vfe_out->res_state = CAM_ISP_RESOURCE_STATE_STREAMING; + + rsrc_data->irq_handle = cam_irq_controller_subscribe_irq( + common_data->bus_irq_controller, + CAM_IRQ_PRIORITY_1, + irq_reg_mask, + vfe_bus_rd, + cam_vfe_bus_rd_handle_irq_top_half, + cam_vfe_bus_rd_handle_irq_bottom_half, + vfe_bus_rd->tasklet_info, + &tasklet_bh_api); + + if (rsrc_data->irq_handle < 1) { + CAM_ERR(CAM_ISP, "Failed to subscribe BUS RD IRQ"); + rsrc_data->irq_handle = 0; + return -EFAULT; + } + + vfe_bus_rd->res_state = CAM_ISP_RESOURCE_STATE_STREAMING; return rc; } @@ -631,7 +720,6 @@ static int cam_vfe_bus_stop_vfe_bus_rd( int rc = 0, i; struct cam_vfe_bus_rd_ver1_vfe_bus_rd_data *rsrc_data = NULL; - CAM_DBG(CAM_ISP, "E:Stop rd Res"); if (!vfe_bus_rd) { CAM_ERR(CAM_ISP, "Invalid input"); return -EINVAL; @@ -641,14 +729,26 @@ static int cam_vfe_bus_stop_vfe_bus_rd( if (vfe_bus_rd->res_state == CAM_ISP_RESOURCE_STATE_AVAILABLE || vfe_bus_rd->res_state == CAM_ISP_RESOURCE_STATE_RESERVED) { - CAM_DBG(CAM_ISP, "vfe_out res_state is %d", + CAM_DBG(CAM_ISP, "VFE:%d Bus RD 0x%x state: %d", + rsrc_data->common_data->core_index, vfe_bus_rd->res_id, vfe_bus_rd->res_state); return rc; } for (i = 0; i < rsrc_data->num_rm; i++) rc = cam_vfe_bus_stop_rm(rsrc_data->rm_res[i]); + if (rsrc_data->irq_handle) { + rc = cam_irq_controller_unsubscribe_irq( + rsrc_data->common_data->bus_irq_controller, + rsrc_data->irq_handle); + rsrc_data->irq_handle = 0; + } + vfe_bus_rd->res_state = CAM_ISP_RESOURCE_STATE_RESERVED; + + CAM_DBG(CAM_ISP, "VFE:%d stopped Bus RD:0x%x", + rsrc_data->common_data->core_index, + vfe_bus_rd->res_id); return rc; } @@ -663,7 +763,7 @@ static int cam_vfe_bus_init_vfe_bus_read_resource(uint32_t index, bus_rd_hw_info->vfe_bus_rd_hw_info[index].vfe_bus_rd_type; if (vfe_bus_rd_resc_type < 0 || - vfe_bus_rd_resc_type > CAM_VFE_BUS_RD_VER1_VFE_BUSRD_RDI0) { + vfe_bus_rd_resc_type >= CAM_VFE_BUS_RD_VER1_VFE_BUSRD_MAX) { CAM_ERR(CAM_ISP, "Init VFE Out failed, Invalid type=%d", vfe_bus_rd_resc_type); return -EINVAL; @@ -701,7 +801,7 @@ static int cam_vfe_bus_init_vfe_bus_read_resource(uint32_t index, vfe_bus_rd->start = cam_vfe_bus_start_vfe_bus_rd; vfe_bus_rd->stop = cam_vfe_bus_stop_vfe_bus_rd; - vfe_bus_rd->process_cmd = cam_vfe_bus_process_cmd; + vfe_bus_rd->process_cmd = cam_vfe_bus_rd_process_cmd; vfe_bus_rd->hw_intf = bus_rd_priv->common_data.hw_intf; return 0; @@ -740,13 +840,18 @@ static int cam_vfe_bus_deinit_vfe_bus_rd_resource( } static int cam_vfe_bus_rd_ver1_handle_irq(uint32_t evt_id, - struct cam_irq_th_payload *th_payload) + struct cam_irq_th_payload *th_payload) { - struct cam_vfe_bus_rd_ver1_priv *bus_priv; + struct cam_vfe_bus_rd_ver1_priv *bus_priv; + int rc = 0; - bus_priv = th_payload->handler_priv; - CAM_DBG(CAM_ISP, "BUS READ IRQ Received"); - return 0; + bus_priv = th_payload->handler_priv; + CAM_DBG(CAM_ISP, "Top Bus RD IRQ Received"); + + rc = cam_irq_controller_handle_irq(evt_id, + bus_priv->common_data.bus_irq_controller); + + return (rc == IRQ_HANDLED) ? 0 : -EINVAL; } static int cam_vfe_bus_rd_update_rm(void *priv, void *cmd_args, @@ -759,7 +864,6 @@ static int cam_vfe_bus_rd_update_rm(void *priv, void *cmd_args, struct cam_vfe_bus_rd_ver1_rm_resource_data *rm_data = NULL; uint32_t *reg_val_pair; uint32_t i, j, size = 0; - uint32_t val; uint32_t buf_size = 0; bus_priv = (struct cam_vfe_bus_rd_ver1_priv *) priv; @@ -796,39 +900,32 @@ static int cam_vfe_bus_rd_update_rm(void *priv, void *cmd_args, rm_data = vfe_bus_rd_data->rm_res[i]->res_priv; /* update size register */ - rm_data->width = io_cfg->planes[i].width; + cam_vfe_bus_rd_pxls_to_bytes(io_cfg->planes[i].width, + rm_data->unpacker_cfg, &rm_data->width); rm_data->height = io_cfg->planes[i].height; - CAM_DBG(CAM_ISP, "RM %d image w 0x%x h 0x%x image size 0x%x", - rm_data->index, rm_data->width, rm_data->height, - buf_size); buf_size = ((rm_data->width)&(0x0000FFFF)) | ((rm_data->height<<16)&(0xFFFF0000)); - CAM_DBG(CAM_ISP, "size offset 0x%x buf_size 0x%x", - rm_data->hw_regs->buf_size, buf_size); CAM_VFE_ADD_REG_VAL_PAIR(reg_val_pair, j, rm_data->hw_regs->buf_size, buf_size); - CAM_DBG(CAM_ISP, "RM %d image size 0x%x", + CAM_DBG(CAM_ISP, "VFE:%d RM:%d image_size:0x%X", + rm_data->common_data->core_index, rm_data->index, reg_val_pair[j-1]); - val = rm_data->width; - CAM_DBG(CAM_ISP, "io_cfg stride 0x%x", val); + rm_data->stride = io_cfg->planes[i].plane_stride; CAM_VFE_ADD_REG_VAL_PAIR(reg_val_pair, j, - rm_data->hw_regs->stride, - val); - rm_data->stride = val; - CAM_DBG(CAM_ISP, "RM %d image stride 0x%x", + rm_data->hw_regs->stride, rm_data->stride); + CAM_DBG(CAM_ISP, "VFE:%d RM:%d image_stride:0x%X", + rm_data->common_data->core_index, rm_data->index, reg_val_pair[j-1]); - /* RM Image address */ - CAM_DBG(CAM_ISP, "image_addr offset %x", - rm_data->hw_regs->image_addr); CAM_VFE_ADD_REG_VAL_PAIR(reg_val_pair, j, rm_data->hw_regs->image_addr, update_buf->rm_update->image_buf[i] + rm_data->offset); - CAM_DBG(CAM_ISP, "RM %d image address 0x%x", + CAM_DBG(CAM_ISP, "VFE:%d RM:%d image_address:0x%X", + rm_data->common_data->core_index, rm_data->index, reg_val_pair[j-1]); rm_data->img_addr = reg_val_pair[j-1]; @@ -889,43 +986,93 @@ static int cam_vfe_bus_rd_update_fs_cfg(void *priv, void *cmd_args, common_data = rm_data->common_data; rm_data->format = fe_cfg->format; - CAM_DBG(CAM_ISP, "format: 0x%x", rm_data->format); - rm_data->unpacker_cfg = fe_cfg->unpacker_cfg; - CAM_DBG(CAM_ISP, "unpacker_cfg: 0x%x", rm_data->unpacker_cfg); - rm_data->latency_buf_allocation = fe_cfg->latency_buf_size; - CAM_DBG(CAM_ISP, "latency_buf_allocation: 0x%x", - rm_data->latency_buf_allocation); - rm_data->stride = fe_cfg->stride; - CAM_DBG(CAM_ISP, "stride: 0x%x", rm_data->stride); - rm_data->go_cmd_sel = fe_cfg->go_cmd_sel; - CAM_DBG(CAM_ISP, "go_cmd_sel: 0x%x", rm_data->go_cmd_sel); - rm_data->fs_sync_enable = fe_cfg->fs_sync_enable; - CAM_DBG(CAM_ISP, "fs_sync_enable: 0x%x", - rm_data->fs_sync_enable); - rm_data->hbi_count = fe_cfg->hbi_count; - CAM_DBG(CAM_ISP, "hbi_count: 0x%x", rm_data->hbi_count); - rm_data->fs_line_sync_en = fe_cfg->fs_line_sync_en; - CAM_DBG(CAM_ISP, "fs_line_sync_en: 0x%x", - rm_data->fs_line_sync_en); - rm_data->fs_mode = fe_cfg->fs_mode; - CAM_DBG(CAM_ISP, "fs_mode: 0x%x", rm_data->fs_mode); - rm_data->min_vbi = fe_cfg->min_vbi; - CAM_DBG(CAM_ISP, "min_vbi: 0x%x", rm_data->min_vbi); + + CAM_DBG(CAM_ISP, + "VFE:%d RM:%d format:0x%x unpacker_cfg:0x%x", + rm_data->format, rm_data->unpacker_cfg); + CAM_DBG(CAM_ISP, + "latency_buf_alloc:0x%x stride:0x%x go_cmd_sel:0x%x", + rm_data->latency_buf_allocation, rm_data->stride, + rm_data->go_cmd_sel); + CAM_DBG(CAM_ISP, + "fs_sync_en:%d hbi_cnt:0x%x fs_mode:0x%x min_vbi:0x%x", + rm_data->fs_sync_enable, rm_data->hbi_count, + rm_data->fs_mode, rm_data->min_vbi); } bus_priv->common_data.fs_sync_enable = fe_cfg->fs_sync_enable; bus_priv->common_data.go_cmd_sel = fe_cfg->go_cmd_sel; return 0; } +static int cam_vfe_bus_rd_add_go_cmd(void *priv, void *cmd_args, + uint32_t arg_size) +{ + struct cam_vfe_bus_rd_ver1_vfe_bus_rd_data *rd_data; + struct cam_isp_hw_get_cmd_update *cdm_args = cmd_args; + struct cam_cdm_utils_ops *cdm_util_ops = NULL; + uint32_t reg_val_pair[2 * CAM_VFE_BUS_RD_VER1_VFE_BUSRD_MAX]; + struct cam_vfe_bus_rd_ver1_rm_resource_data *rsrc_data; + int i = 0; + uint32_t val = 0, size = 0, offset = 0; + + if (arg_size != sizeof(struct cam_isp_hw_get_cmd_update)) { + CAM_ERR(CAM_ISP, "invalid ars size"); + return -EINVAL; + } + + if (!cdm_args || !cdm_args->res) { + CAM_ERR(CAM_ISP, "Invalid args"); + return -EINVAL; + } + + rd_data = (struct cam_vfe_bus_rd_ver1_vfe_bus_rd_data *) priv; + + cdm_util_ops = (struct cam_cdm_utils_ops *)cdm_args->res->cdm_ops; + + if (!cdm_util_ops) { + CAM_ERR(CAM_ISP, "Invalid CDM ops"); + return -EINVAL; + } + + for (i = 0; i < rd_data->num_rm; i++) { + size = cdm_util_ops->cdm_required_size_reg_random(1); + /* since cdm returns dwords, we need to convert it into bytes */ + if ((size * 4) > cdm_args->cmd.size) { + CAM_ERR(CAM_ISP, + "buf size:%d is not sufficient, expected: %d", + cdm_args->cmd.size, size); + return -EINVAL; + } + + rsrc_data = rd_data->rm_res[i]->res_priv; + offset = rsrc_data->common_data->common_reg->input_if_cmd; + val = cam_io_r_mb(rsrc_data->common_data->mem_base + offset); + val |= 0x1; + reg_val_pair[i * 2] = offset; + reg_val_pair[i * 2 + 1] = val; + CAM_DBG(CAM_ISP, "VFE:%d Bus RD go_cmd: 0x%x offset 0x%x", + rd_data->common_data->core_index, + reg_val_pair[i * 2 + 1], reg_val_pair[i * 2]); + } + + cdm_util_ops->cdm_write_regrandom(cdm_args->cmd.cmd_buf_addr, + 1, reg_val_pair); + + cdm_args->cmd.used_bytes = size * 4; + + return 0; + +} + static int cam_vfe_bus_start_hw(void *hw_priv, void *start_hw_args, uint32_t arg_size) { @@ -943,7 +1090,7 @@ static int cam_vfe_bus_init_hw(void *hw_priv, { struct cam_vfe_bus_rd_ver1_priv *bus_priv = hw_priv; uint32_t top_irq_reg_mask[3] = {0}; - uint32_t offset = 0, val = 0; + uint32_t offset = 0; struct cam_vfe_bus_rd_ver1_reg_offset_common *common_reg; if (!bus_priv) { @@ -951,7 +1098,7 @@ static int cam_vfe_bus_init_hw(void *hw_priv, return -EINVAL; } common_reg = bus_priv->common_data.common_reg; - top_irq_reg_mask[0] = (1 << 23); + top_irq_reg_mask[0] = (1 << bus_priv->top_irq_shift); bus_priv->irq_handle = cam_irq_controller_subscribe_irq( bus_priv->common_data.vfe_irq_controller, @@ -968,23 +1115,15 @@ static int cam_vfe_bus_init_hw(void *hw_priv, bus_priv->irq_handle = 0; return -EFAULT; } + /* no clock gating at bus input */ offset = common_reg->cgc_ovd; - cam_io_w_mb(0x0, bus_priv->common_data.mem_base + offset); + cam_io_w_mb(0x1, bus_priv->common_data.mem_base + offset); /* BUS_RD_TEST_BUS_CTRL */ offset = common_reg->test_bus_ctrl; cam_io_w_mb(0x0, bus_priv->common_data.mem_base + offset); - /* Read irq mask */ - offset = common_reg->irq_reg_info.irq_reg_set->mask_reg_offset; - cam_io_w_mb(0x5, bus_priv->common_data.mem_base + offset); - - /* INPUT_IF_CMD */ - val = (bus_priv->common_data.fs_sync_enable << 5) | - (bus_priv->common_data.go_cmd_sel << 4); - offset = common_reg->input_if_cmd; - cam_io_w_mb(val, bus_priv->common_data.mem_base + offset); return 0; } @@ -999,13 +1138,6 @@ static int cam_vfe_bus_deinit_hw(void *hw_priv, return -EINVAL; } - if (bus_priv->error_irq_handle) { - rc = cam_irq_controller_unsubscribe_irq( - bus_priv->common_data.bus_irq_controller, - bus_priv->error_irq_handle); - bus_priv->error_irq_handle = 0; - } - if (bus_priv->irq_handle) { rc = cam_irq_controller_unsubscribe_irq( bus_priv->common_data.vfe_irq_controller, @@ -1016,13 +1148,13 @@ static int cam_vfe_bus_deinit_hw(void *hw_priv, return rc; } -static int __cam_vfe_bus_process_cmd(void *priv, +static int __cam_vfe_bus_rd_process_cmd(void *priv, uint32_t cmd_type, void *cmd_args, uint32_t arg_size) { - return cam_vfe_bus_process_cmd(priv, cmd_type, cmd_args, arg_size); + return cam_vfe_bus_rd_process_cmd(priv, cmd_type, cmd_args, arg_size); } -static int cam_vfe_bus_process_cmd( +static int cam_vfe_bus_rd_process_cmd( struct cam_isp_resource_node *priv, uint32_t cmd_type, void *cmd_args, uint32_t arg_size) { @@ -1046,6 +1178,9 @@ static int cam_vfe_bus_process_cmd( case CAM_ISP_HW_CMD_FE_UPDATE_BUS_RD: rc = cam_vfe_bus_rd_update_fs_cfg(priv, cmd_args, arg_size); break; + case CAM_ISP_HW_CMD_FE_TRIGGER_CMD: + rc = cam_vfe_bus_rd_add_go_cmd(priv, cmd_args, arg_size); + break; default: CAM_ERR_RATE_LIMIT(CAM_ISP, "Invalid camif process command:%d", cmd_type); @@ -1104,6 +1239,7 @@ int cam_vfe_bus_rd_ver1_init( bus_priv->common_data.hw_intf = hw_intf; bus_priv->common_data.vfe_irq_controller = vfe_irq_controller; bus_priv->common_data.common_reg = &bus_rd_hw_info->common_reg; + bus_priv->top_irq_shift = bus_rd_hw_info->top_irq_shift; mutex_init(&bus_priv->common_data.bus_mutex); @@ -1143,7 +1279,7 @@ int cam_vfe_bus_rd_ver1_init( vfe_bus_local->hw_ops.deinit = cam_vfe_bus_deinit_hw; vfe_bus_local->top_half_handler = cam_vfe_bus_rd_ver1_handle_irq; vfe_bus_local->bottom_half_handler = NULL; - vfe_bus_local->hw_ops.process_cmd = __cam_vfe_bus_process_cmd; + vfe_bus_local->hw_ops.process_cmd = __cam_vfe_bus_rd_process_cmd; *vfe_bus = vfe_bus_local; diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_rd_ver1.h b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_rd_ver1.h index 19cc864963..90229b179c 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_rd_ver1.h +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_rd_ver1.h @@ -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; }; /* diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_camif_ver3.c b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_camif_ver3.c index d9fe166d39..ca0cf15ba2 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_camif_ver3.c +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_camif_ver3.c @@ -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);