diff options
Diffstat (limited to 'drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c')
-rw-r--r-- | drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c | 375 |
1 files changed, 205 insertions, 170 deletions
diff --git a/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c b/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c index c1aa501e229d..e5c54d6a85ed 100644 --- a/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c +++ b/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c @@ -225,6 +225,8 @@ static int cam_ife_hw_mgr_start_hw_res( CAM_ERR(CAM_ISP, "Can not start HW resources"); goto err; } + CAM_DBG(CAM_ISP, "Start HW %d Res %d", hw_intf->hw_idx, + isp_hw_res->hw_res[i]->res_id); } else { CAM_ERR(CAM_ISP, "function null"); goto err; @@ -366,7 +368,8 @@ static int cam_ife_mgr_csid_stop_hw( isp_res = hw_mgr_res->hw_res[i]; if (isp_res->hw_intf->hw_idx != base_idx) continue; - + CAM_DBG(CAM_ISP, "base_idx %d res_id %d cnt %u", + base_idx, isp_res->res_id, cnt); stop_res[cnt] = isp_res; cnt++; } @@ -483,8 +486,8 @@ static void cam_ife_mgr_add_base_info( "Add split id = %d for base idx = %d num_base=%d", split_id, base_idx, ctx->num_base); } else { - /*Check if base index is alreay exist in the list */ - for (i = 0; i < CAM_IFE_HW_NUM_MAX; i++) { + /*Check if base index already exists in the list */ + for (i = 0; i < ctx->num_base; i++) { if (ctx->base[i].idx == base_idx) { if (split_id != CAM_ISP_HW_SPLIT_MAX && ctx->base[i].split_id == @@ -495,7 +498,7 @@ static void cam_ife_mgr_add_base_info( } } - if (i == CAM_IFE_HW_NUM_MAX) { + if (i == ctx->num_base) { ctx->base[ctx->num_base].split_id = split_id; ctx->base[ctx->num_base].idx = base_idx; ctx->num_base++; @@ -845,7 +848,8 @@ static int cam_ife_hw_mgr_acquire_res_ife_src( } ife_src_res->hw_res[i] = vfe_acquire.vfe_in.rsrc_node; CAM_DBG(CAM_ISP, - "acquire success res type :0x%x res id:0x%x", + "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); @@ -871,29 +875,75 @@ err: static int cam_ife_mgr_acquire_cid_res( struct cam_ife_hw_mgr_ctx *ife_ctx, struct cam_isp_in_port_info *in_port, - uint32_t *cid_res_id, + struct cam_ife_hw_mgr_res **cid_res, enum cam_ife_pix_path_res_id csid_path) { int rc = -1; int i, j; struct cam_ife_hw_mgr *ife_hw_mgr; - struct cam_ife_hw_mgr_res *cid_res; struct cam_hw_intf *hw_intf; + struct cam_ife_hw_mgr_res *cid_res_temp, *cid_res_iterator; struct cam_csid_hw_reserve_resource_args csid_acquire; + uint32_t acquired_cnt = 0; ife_hw_mgr = ife_ctx->hw_mgr; + *cid_res = NULL; - rc = cam_ife_hw_mgr_get_res(&ife_ctx->free_res_list, &cid_res); + rc = cam_ife_hw_mgr_get_res(&ife_ctx->free_res_list, cid_res); if (rc) { CAM_ERR(CAM_ISP, "No more free hw mgr resource"); - goto err; + goto end; } - cam_ife_hw_mgr_put_res(&ife_ctx->res_list_ife_cid, &cid_res); + + cid_res_temp = *cid_res; csid_acquire.res_type = CAM_ISP_RESOURCE_CID; csid_acquire.in_port = in_port; csid_acquire.res_id = csid_path; + CAM_DBG(CAM_ISP, "path %d", csid_path); + + /* Try acquiring CID resource from previously acquired HW */ + list_for_each_entry(cid_res_iterator, &ife_ctx->res_list_ife_cid, + list) { + + for (i = 0; i < CAM_ISP_HW_SPLIT_MAX; i++) { + if (!cid_res_iterator->hw_res[i]) + continue; + hw_intf = cid_res_iterator->hw_res[i]->hw_intf; + rc = hw_intf->hw_ops.reserve(hw_intf->hw_priv, + &csid_acquire, sizeof(csid_acquire)); + if (rc) { + CAM_DBG(CAM_ISP, + "No ife cid resource from hw %d", + hw_intf->hw_idx); + continue; + } + + cid_res_temp->hw_res[acquired_cnt++] = + csid_acquire.node_res; + + CAM_DBG(CAM_ISP, + "acquired csid(%s)=%d CID rsrc successfully", + (i == 0) ? "left" : "right", + hw_intf->hw_idx); + + if (in_port->usage_type && acquired_cnt == 1 && + csid_path == CAM_IFE_PIX_PATH_RES_IPP) + /* Continue to acquire Right */ + continue; + + if (acquired_cnt) + /* + * If successfully acquired CID from + * previously acquired HW, skip the next + * part + */ + goto acquire_successful; + } + } + + /* Acquire Left if not already acquired */ for (i = 0; i < CAM_IFE_CSID_HW_NUM_MAX; i++) { if (!ife_hw_mgr->csid_devices[i]) continue; @@ -903,31 +953,45 @@ static int cam_ife_mgr_acquire_cid_res( sizeof(csid_acquire)); if (rc) continue; - else + else { + cid_res_temp->hw_res[acquired_cnt++] = + csid_acquire.node_res; break; + } } if (i == CAM_IFE_CSID_HW_NUM_MAX || !csid_acquire.node_res) { - CAM_ERR(CAM_ISP, "Can not acquire ife csid rdi resource"); - goto err; + CAM_ERR(CAM_ISP, "Can not acquire ife cid resource for path %d", + csid_path); + goto put_res; } - cid_res->res_type = CAM_IFE_HW_MGR_RES_CID; - cid_res->res_id = csid_acquire.node_res->res_id; - cid_res->is_dual_vfe = in_port->usage_type; - cid_res->hw_res[0] = csid_acquire.node_res; - cid_res->hw_res[1] = NULL; +acquire_successful: + CAM_DBG(CAM_ISP, "CID left acquired success is_dual %d", + in_port->usage_type); + + cid_res_temp->res_type = CAM_IFE_HW_MGR_RES_CID; /* CID(DT_ID) value of acquire device, require for path */ - *cid_res_id = csid_acquire.node_res->res_id; + cid_res_temp->res_id = csid_acquire.node_res->res_id; + cid_res_temp->is_dual_vfe = in_port->usage_type; + cam_ife_hw_mgr_put_res(&ife_ctx->res_list_ife_cid, cid_res); - if (cid_res->is_dual_vfe) { + /* + * Acquire Right if not already acquired. + * Dual IFE for RDI is not currently supported. + */ + if (cid_res_temp->is_dual_vfe && csid_path + == CAM_IFE_PIX_PATH_RES_IPP && acquired_cnt == 1) { csid_acquire.node_res = NULL; csid_acquire.res_type = CAM_ISP_RESOURCE_CID; csid_acquire.in_port = in_port; - for (j = i + 1; j < CAM_IFE_CSID_HW_NUM_MAX; j++) { + for (j = 0; j < CAM_IFE_CSID_HW_NUM_MAX; j++) { if (!ife_hw_mgr->csid_devices[j]) continue; + if (j == cid_res_temp->hw_res[0]->hw_intf->hw_idx) + continue; + hw_intf = ife_hw_mgr->csid_devices[j]; rc = hw_intf->hw_ops.reserve(hw_intf->hw_priv, &csid_acquire, sizeof(csid_acquire)); @@ -940,16 +1004,20 @@ static int cam_ife_mgr_acquire_cid_res( if (j == CAM_IFE_CSID_HW_NUM_MAX) { CAM_ERR(CAM_ISP, "Can not acquire ife csid rdi resource"); - goto err; + goto end; } - cid_res->hw_res[1] = csid_acquire.node_res; + cid_res_temp->hw_res[1] = csid_acquire.node_res; + CAM_DBG(CAM_ISP, "CID right acquired success is_dual %d", + in_port->usage_type); } - cid_res->parent = &ife_ctx->res_list_ife_in; + cid_res_temp->parent = &ife_ctx->res_list_ife_in; ife_ctx->res_list_ife_in.child[ - ife_ctx->res_list_ife_in.num_children++] = cid_res; + ife_ctx->res_list_ife_in.num_children++] = cid_res_temp; return 0; -err: +put_res: + cam_ife_hw_mgr_put_res(&ife_ctx->free_res_list, cid_res); +end: return rc; } @@ -966,35 +1034,25 @@ static int cam_ife_hw_mgr_acquire_res_ife_csid_ipp( struct cam_ife_hw_mgr_res *csid_res; struct cam_ife_hw_mgr_res *cid_res; struct cam_hw_intf *hw_intf; - uint32_t cid_res_id; struct cam_csid_hw_reserve_resource_args csid_acquire; + ife_hw_mgr = ife_ctx->hw_mgr; /* get cid resource */ - rc = cam_ife_mgr_acquire_cid_res(ife_ctx, in_port, &cid_res_id, + rc = cam_ife_mgr_acquire_cid_res(ife_ctx, in_port, &cid_res, CAM_IFE_PIX_PATH_RES_IPP); if (rc) { CAM_ERR(CAM_ISP, "Acquire IFE CID resource Failed"); - goto err; + goto end; } - ife_hw_mgr = ife_ctx->hw_mgr; - rc = cam_ife_hw_mgr_get_res(&ife_ctx->free_res_list, &csid_res); if (rc) { CAM_ERR(CAM_ISP, "No more free hw mgr resource"); - goto err; + goto end; } - cam_ife_hw_mgr_put_res(&ife_ctx->res_list_ife_csid, &csid_res); - - csid_acquire.res_type = CAM_ISP_RESOURCE_PIX_PATH; - csid_acquire.res_id = CAM_IFE_PIX_PATH_RES_IPP; - csid_acquire.cid = cid_res_id; - csid_acquire.in_port = in_port; - csid_acquire.out_port = in_port->data; csid_res->res_type = CAM_ISP_RESOURCE_PIX_PATH; csid_res->res_id = CAM_IFE_PIX_PATH_RES_IPP; - csid_res->is_dual_vfe = in_port->usage_type; if (in_port->usage_type) csid_res->is_dual_vfe = 1; @@ -1003,66 +1061,60 @@ static int cam_ife_hw_mgr_acquire_res_ife_csid_ipp( csid_acquire.sync_mode = CAM_ISP_HW_SYNC_NONE; } - list_for_each_entry(cid_res, &ife_ctx->res_list_ife_cid, - list) { - if (cid_res->res_id != cid_res_id) - continue; - - for (i = 0; i < CAM_ISP_HW_SPLIT_MAX; i++) { - if (!cid_res->hw_res[i]) - continue; + /* IPP resource needs to be from same HW as CID resource */ + for (i = 0; i <= csid_res->is_dual_vfe; i++) { + CAM_DBG(CAM_ISP, "i %d is_dual %d", i, csid_res->is_dual_vfe); + csid_acquire.res_type = CAM_ISP_RESOURCE_PIX_PATH; + csid_acquire.res_id = CAM_IFE_PIX_PATH_RES_IPP; + csid_acquire.cid = cid_res->hw_res[i]->res_id; + csid_acquire.in_port = in_port; + csid_acquire.out_port = in_port->data; + csid_acquire.node_res = NULL; - hw_intf = ife_hw_mgr->csid_devices[ - cid_res->hw_res[i]->hw_intf->hw_idx]; + hw_intf = cid_res->hw_res[i]->hw_intf; - csid_acquire.node_res = NULL; - if (csid_res->is_dual_vfe) { - if (i == CAM_ISP_HW_SPLIT_LEFT) { - master_idx = hw_intf->hw_idx; - csid_acquire.sync_mode = - CAM_ISP_HW_SYNC_MASTER; - } else { - if (master_idx == -1) { - CAM_ERR(CAM_ISP, - "No Master found"); - goto err; - } - csid_acquire.sync_mode = - CAM_ISP_HW_SYNC_SLAVE; - csid_acquire.master_idx = master_idx; + if (csid_res->is_dual_vfe) { + if (i == CAM_ISP_HW_SPLIT_LEFT) { + master_idx = hw_intf->hw_idx; + csid_acquire.sync_mode = + CAM_ISP_HW_SYNC_MASTER; + } else { + if (master_idx == -1) { + CAM_ERR(CAM_ISP, + "No Master found"); + goto put_res; } + csid_acquire.sync_mode = + CAM_ISP_HW_SYNC_SLAVE; + csid_acquire.master_idx = master_idx; } - - rc = hw_intf->hw_ops.reserve(hw_intf->hw_priv, - &csid_acquire, sizeof(csid_acquire)); - if (rc) { - CAM_ERR(CAM_ISP, - "Cannot acquire ife csid ipp resource"); - goto err; - } - - csid_res->hw_res[i] = csid_acquire.node_res; - CAM_DBG(CAM_ISP, - "acquired csid(%s)=%d ipp rsrc successfully", - (i == 0) ? "left" : "right", - hw_intf->hw_idx); - } - if (i == CAM_IFE_CSID_HW_NUM_MAX) { + rc = hw_intf->hw_ops.reserve(hw_intf->hw_priv, + &csid_acquire, sizeof(csid_acquire)); + if (rc) { CAM_ERR(CAM_ISP, - "Can not acquire ife csid ipp resource"); - goto err; + "Cannot acquire ife csid ipp resource"); + goto put_res; } - csid_res->parent = cid_res; - cid_res->child[cid_res->num_children++] = csid_res; + csid_res->hw_res[i] = csid_acquire.node_res; + CAM_DBG(CAM_ISP, + "acquired csid(%s)=%d ipp rsrc successfully", + (i == 0) ? "left" : "right", + hw_intf->hw_idx); } + cam_ife_hw_mgr_put_res(&ife_ctx->res_list_ife_csid, &csid_res); + + csid_res->parent = cid_res; + cid_res->child[cid_res->num_children++] = csid_res; CAM_DBG(CAM_ISP, "acquire res %d", csid_acquire.res_id); return 0; -err: +put_res: + cam_ife_hw_mgr_put_res(&ife_ctx->free_res_list, &csid_res); +end: return rc; } @@ -1099,111 +1151,88 @@ static int cam_ife_hw_mgr_acquire_res_ife_csid_rdi( struct cam_ife_hw_mgr_ctx *ife_ctx, struct cam_isp_in_port_info *in_port) { - int rc = -1; - int i, j; + int rc = -EINVAL; + int i; struct cam_ife_hw_mgr *ife_hw_mgr; struct cam_ife_hw_mgr_res *csid_res; struct cam_ife_hw_mgr_res *cid_res; struct cam_hw_intf *hw_intf; struct cam_isp_out_port_info *out_port; - uint32_t cid_res_id; struct cam_csid_hw_reserve_resource_args csid_acquire; + enum cam_ife_pix_path_res_id path_type; ife_hw_mgr = ife_ctx->hw_mgr; 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)) + path_type = cam_ife_hw_mgr_get_ife_csid_rdi_res_type( + out_port->res_type); + if (path_type == CAM_IFE_PIX_PATH_RES_MAX) continue; - /* get cid resource */ - rc = cam_ife_mgr_acquire_cid_res(ife_ctx, - in_port, &cid_res_id, - cam_ife_hw_mgr_get_ife_csid_rdi_res_type( - out_port->res_type)); - if (rc) { - CAM_ERR(CAM_ISP, - "Acquire IFE CID resource Failed"); - goto err; + /* get cid resource */ + rc = cam_ife_mgr_acquire_cid_res(ife_ctx, in_port, &cid_res, + path_type); + if (rc) { + CAM_ERR(CAM_ISP, "Acquire IFE CID resource Failed"); + goto end; } + /* For each RDI we need CID + PATH resource */ rc = cam_ife_hw_mgr_get_res(&ife_ctx->free_res_list, &csid_res); if (rc) { CAM_ERR(CAM_ISP, "No more free hw mgr resource"); - goto err; + goto end; } - cam_ife_hw_mgr_put_res(&ife_ctx->res_list_ife_csid, &csid_res); - - /* - * no need to check since we are doing one to one mapping - * between the csid rdi type and out port rdi type - */ memset(&csid_acquire, 0, sizeof(csid_acquire)); - csid_acquire.res_id = - cam_ife_hw_mgr_get_ife_csid_rdi_res_type( - out_port->res_type); + csid_acquire.res_id = path_type; csid_acquire.res_type = CAM_ISP_RESOURCE_PIX_PATH; - csid_acquire.cid = cid_res_id; + csid_acquire.cid = cid_res->hw_res[0]->res_id; csid_acquire.in_port = in_port; csid_acquire.out_port = out_port; csid_acquire.sync_mode = CAM_ISP_HW_SYNC_NONE; + csid_acquire.node_res = NULL; - list_for_each_entry(cid_res, &ife_ctx->res_list_ife_cid, - list) { - if (cid_res->res_id != cid_res_id) - continue; - - for (j = 0; j < CAM_ISP_HW_SPLIT_MAX; j++) { - if (!cid_res->hw_res[j]) - continue; - - csid_acquire.node_res = NULL; - - hw_intf = ife_hw_mgr->csid_devices[ - cid_res->hw_res[j]->hw_intf->hw_idx]; - rc = hw_intf->hw_ops.reserve(hw_intf->hw_priv, - &csid_acquire, sizeof(csid_acquire)); - if (rc) { - CAM_DBG(CAM_ISP, - "CSID Path reserve failed hw=%d rc=%d", - hw_intf->hw_idx, rc); - continue; - } + hw_intf = cid_res->hw_res[0]->hw_intf; + rc = hw_intf->hw_ops.reserve(hw_intf->hw_priv, + &csid_acquire, sizeof(csid_acquire)); + if (rc) { + CAM_ERR(CAM_ISP, + "CSID Path reserve failed hw=%d rc=%d cid=%d", + hw_intf->hw_idx, rc, + cid_res->hw_res[0]->res_id); - /* RDI does not need Dual ISP. Break */ - break; - } + goto put_res; + } - if (j == CAM_ISP_HW_SPLIT_MAX && - csid_acquire.node_res == NULL) { - CAM_ERR(CAM_ISP, - "acquire csid rdi rsrc failed, cid %d", - cid_res_id); - goto err; - } + if (csid_acquire.node_res == NULL) { + CAM_ERR(CAM_ISP, "Acquire CSID RDI rsrc failed"); - csid_res->res_type = CAM_ISP_RESOURCE_PIX_PATH; - csid_res->res_id = csid_acquire.res_id; - csid_res->is_dual_vfe = 0; - csid_res->hw_res[0] = csid_acquire.node_res; - csid_res->hw_res[1] = NULL; - CAM_DBG(CAM_ISP, "acquire res %d", - csid_acquire.res_id); - csid_res->parent = cid_res; - cid_res->child[cid_res->num_children++] = - csid_res; - - /* Done with cid_res_id. Break */ - break; + goto put_res; } + + csid_res->res_type = (enum cam_ife_hw_mgr_res_type) + CAM_ISP_RESOURCE_PIX_PATH; + csid_res->res_id = csid_acquire.res_id; + csid_res->is_dual_vfe = 0; + csid_res->hw_res[0] = csid_acquire.node_res; + csid_res->hw_res[1] = NULL; + CAM_DBG(CAM_ISP, "acquire res %d", + csid_acquire.res_id); + csid_res->parent = cid_res; + cid_res->child[cid_res->num_children++] = + csid_res; + cam_ife_hw_mgr_put_res(&ife_ctx->res_list_ife_csid, &csid_res); } return 0; -err: +put_res: + cam_ife_hw_mgr_put_res(&ife_ctx->free_res_list, &csid_res); +end: return rc; } @@ -1870,33 +1899,39 @@ static int cam_ife_mgr_stop_hw(void *hw_mgr_priv, void *stop_hw_args) */ if (i == ctx->num_base) master_base_idx = ctx->base[0].idx; + CAM_DBG(CAM_ISP, "Stopping master CSID idx %d", master_base_idx); - /* Stop the master CIDs first */ - cam_ife_mgr_csid_stop_hw(ctx, &ctx->res_list_ife_cid, - master_base_idx, csid_halt_type); + /* Stop the master CSID path first */ + cam_ife_mgr_csid_stop_hw(ctx, &ctx->res_list_ife_csid, + master_base_idx, CAM_CSID_HALT_AT_FRAME_BOUNDARY); - /* stop rest of the CIDs */ + /* stop rest of the CSID paths */ for (i = 0; i < ctx->num_base; i++) { - if (i == master_base_idx) + if (ctx->base[i].idx == master_base_idx) continue; - cam_ife_mgr_csid_stop_hw(ctx, &ctx->res_list_ife_cid, - ctx->base[i].idx, csid_halt_type); + CAM_DBG(CAM_ISP, "Stopping CSID idx %d i %d master %d", + ctx->base[i].idx, i, master_base_idx); + + cam_ife_mgr_csid_stop_hw(ctx, &ctx->res_list_ife_csid, + ctx->base[i].idx, CAM_CSID_HALT_AT_FRAME_BOUNDARY); } - /* Stop the master CSID path first */ - cam_ife_mgr_csid_stop_hw(ctx, &ctx->res_list_ife_csid, + CAM_DBG(CAM_ISP, "Stopping master CID idx %d", master_base_idx); + + /* Stop the master CIDs first */ + cam_ife_mgr_csid_stop_hw(ctx, &ctx->res_list_ife_cid, master_base_idx, csid_halt_type); - /* stop rest of the CSID paths */ + /* stop rest of the CIDs */ for (i = 0; i < ctx->num_base; i++) { - if (i == master_base_idx) + if (ctx->base[i].idx == master_base_idx) continue; - - cam_ife_mgr_csid_stop_hw(ctx, &ctx->res_list_ife_csid, + CAM_DBG(CAM_ISP, "Stopping CID idx %d i %d master %d", + ctx->base[i].idx, i, master_base_idx); + cam_ife_mgr_csid_stop_hw(ctx, &ctx->res_list_ife_cid, ctx->base[i].idx, csid_halt_type); } - /* Deinit IFE CID */ list_for_each_entry(hw_mgr_res, &ctx->res_list_ife_cid, list) { CAM_DBG(CAM_ISP, "%s: Going to DeInit IFE CID\n", __func__); @@ -4218,7 +4253,7 @@ int cam_ife_hw_mgr_init(struct cam_hw_mgr_intf *hw_mgr_intf) /* Create Worker for ife_hw_mgr with 10 tasks */ rc = cam_req_mgr_workq_create("cam_ife_worker", 10, - &g_ife_hw_mgr.workq, CRM_WORKQ_USAGE_NON_IRQ); + &g_ife_hw_mgr.workq, CRM_WORKQ_USAGE_NON_IRQ, 0); if (rc < 0) { CAM_ERR(CAM_ISP, "Unable to create worker"); goto end; |