Merge "msm: camera: isp: Add support to discard set number of frames" into camera-kernel.lnx.5.0
This commit is contained in:

کامیت شده توسط
Gerrit - the friendly Code Review server

کامیت
5427c398a4
@@ -7318,6 +7318,54 @@ static int cam_isp_blob_hfr_update(
|
|||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int cam_isp_blob_csid_discard_init_frame_update(
|
||||||
|
struct cam_isp_generic_blob_info *blob_info,
|
||||||
|
struct cam_isp_discard_initial_frames *discard_config,
|
||||||
|
struct cam_hw_prepare_update_args *prepare)
|
||||||
|
{
|
||||||
|
struct cam_ife_hw_mgr_ctx *ctx = NULL;
|
||||||
|
struct cam_ife_hw_mgr *ife_hw_mgr;
|
||||||
|
struct cam_hw_intf *hw_intf;
|
||||||
|
struct cam_isp_hw_mgr_res *hw_mgr_res;
|
||||||
|
struct cam_isp_resource_node *res;
|
||||||
|
struct cam_ife_csid_discard_init_frame_args discard_args;
|
||||||
|
int rc = -EINVAL, i;
|
||||||
|
|
||||||
|
ctx = prepare->ctxt_to_hw_map;
|
||||||
|
ife_hw_mgr = ctx->hw_mgr;
|
||||||
|
discard_args.num_frames = discard_config->num_frames;
|
||||||
|
|
||||||
|
list_for_each_entry(hw_mgr_res, &ctx->res_list_ife_csid, list) {
|
||||||
|
for (i = 0; i < CAM_ISP_HW_SPLIT_MAX; i++) {
|
||||||
|
if (!hw_mgr_res->hw_res[i])
|
||||||
|
continue;
|
||||||
|
|
||||||
|
hw_intf = hw_mgr_res->hw_res[i]->hw_intf;
|
||||||
|
res = hw_mgr_res->hw_res[i];
|
||||||
|
if (hw_intf && hw_intf->hw_ops.process_cmd) {
|
||||||
|
if (hw_intf->hw_idx != blob_info->base_info->idx)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
discard_args.res = res;
|
||||||
|
rc = hw_intf->hw_ops.process_cmd(
|
||||||
|
hw_intf->hw_priv,
|
||||||
|
CAM_ISP_HW_CMD_CSID_DISCARD_INIT_FRAMES,
|
||||||
|
&discard_args,
|
||||||
|
sizeof(struct cam_ife_csid_discard_init_frame_args));
|
||||||
|
if (rc) {
|
||||||
|
CAM_ERR(CAM_ISP,
|
||||||
|
"Failed to update discard frame cfg for res: %s on CSID[%u]",
|
||||||
|
res->res_name, blob_info->base_info->idx);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static int cam_isp_blob_csid_mup_update(
|
static int cam_isp_blob_csid_mup_update(
|
||||||
uint32_t blob_type,
|
uint32_t blob_type,
|
||||||
struct cam_isp_generic_blob_info *blob_info,
|
struct cam_isp_generic_blob_info *blob_info,
|
||||||
@@ -8439,6 +8487,26 @@ static int cam_isp_packet_generic_blob_handler(void *user_data,
|
|||||||
if (rc)
|
if (rc)
|
||||||
CAM_ERR(CAM_ISP,
|
CAM_ERR(CAM_ISP,
|
||||||
"TPG config failed rc: %d", rc);
|
"TPG config failed rc: %d", rc);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case CAM_ISP_GENERIC_BLOB_TYPE_DISCARD_INITIAL_FRAMES: {
|
||||||
|
struct cam_isp_discard_initial_frames *discard_config;
|
||||||
|
|
||||||
|
if (blob_size < sizeof(struct cam_isp_discard_initial_frames)) {
|
||||||
|
CAM_ERR(CAM_ISP,
|
||||||
|
"Invalid discard frames blob size %u expected %u",
|
||||||
|
blob_size,
|
||||||
|
sizeof(struct cam_isp_discard_initial_frames));
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
discard_config = (struct cam_isp_discard_initial_frames *)blob_data;
|
||||||
|
|
||||||
|
rc = cam_isp_blob_csid_discard_init_frame_update(
|
||||||
|
blob_info, discard_config, prepare);
|
||||||
|
if (rc)
|
||||||
|
CAM_ERR(CAM_ISP, "Discard initial frames update failed rc: %d", rc);
|
||||||
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case CAM_ISP_GENERIC_BLOB_TYPE_SFE_CLOCK_CONFIG:
|
case CAM_ISP_GENERIC_BLOB_TYPE_SFE_CLOCK_CONFIG:
|
||||||
@@ -8878,6 +8946,7 @@ static int cam_sfe_packet_generic_blob_handler(void *user_data,
|
|||||||
case CAM_ISP_GENERIC_BLOB_TYPE_CSID_QCFA_CONFIG:
|
case CAM_ISP_GENERIC_BLOB_TYPE_CSID_QCFA_CONFIG:
|
||||||
case CAM_ISP_GENERIC_BLOB_TYPE_SENSOR_BLANKING_CONFIG:
|
case CAM_ISP_GENERIC_BLOB_TYPE_SENSOR_BLANKING_CONFIG:
|
||||||
case CAM_ISP_GENERIC_BLOB_TYPE_TPG_CORE_CONFIG:
|
case CAM_ISP_GENERIC_BLOB_TYPE_TPG_CORE_CONFIG:
|
||||||
|
case CAM_ISP_GENERIC_BLOB_TYPE_DISCARD_INITIAL_FRAMES:
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
CAM_WARN(CAM_ISP, "Invalid blob type: %u", blob_type);
|
CAM_WARN(CAM_ISP, "Invalid blob type: %u", blob_type);
|
||||||
|
@@ -3762,6 +3762,10 @@ static int cam_ife_csid_ver1_process_cmd(void *hw_priv,
|
|||||||
case CAM_ISP_HW_CMD_CSID_CHANGE_HALT_MODE:
|
case CAM_ISP_HW_CMD_CSID_CHANGE_HALT_MODE:
|
||||||
rc = cam_ife_csid_halt(csid_hw, cmd_args);
|
rc = cam_ife_csid_halt(csid_hw, cmd_args);
|
||||||
break;
|
break;
|
||||||
|
case CAM_ISP_HW_CMD_CSID_DISCARD_INIT_FRAMES:
|
||||||
|
/* Not supported for V1 */
|
||||||
|
rc = 0;
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
CAM_ERR(CAM_ISP, "CSID:%d unsupported cmd:%d",
|
CAM_ERR(CAM_ISP, "CSID:%d unsupported cmd:%d",
|
||||||
csid_hw->hw_intf->hw_idx, cmd_type);
|
csid_hw->hw_intf->hw_idx, cmd_type);
|
||||||
|
@@ -535,6 +535,153 @@ static int cam_ife_csid_ver2_path_top_half(
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline void cam_ife_csid_ver2_reset_discard_frame_cfg(
|
||||||
|
char *res_name,
|
||||||
|
struct cam_ife_csid_ver2_hw *csid_hw,
|
||||||
|
struct cam_ife_csid_ver2_path_cfg *path_cfg)
|
||||||
|
{
|
||||||
|
int rc;
|
||||||
|
|
||||||
|
/* Reset discard config params */
|
||||||
|
path_cfg->discard_init_frames = false;
|
||||||
|
path_cfg->num_frames_discard = 0;
|
||||||
|
path_cfg->sof_cnt = 0;
|
||||||
|
|
||||||
|
/* Decrement discard frame ref cnt for this path */
|
||||||
|
atomic_dec(&csid_hw->discard_frame_per_path);
|
||||||
|
|
||||||
|
/* If input SOF irq is enabled explicitly - unsubscribe in th*/
|
||||||
|
if (path_cfg->discard_irq_handle > 0) {
|
||||||
|
rc = cam_irq_controller_unsubscribe_irq(
|
||||||
|
csid_hw->csid_irq_controller,
|
||||||
|
path_cfg->discard_irq_handle);
|
||||||
|
if (rc)
|
||||||
|
CAM_WARN(CAM_ISP,
|
||||||
|
"Failed to unsubscribe input SOF for res: %s",
|
||||||
|
res_name);
|
||||||
|
|
||||||
|
path_cfg->discard_irq_handle = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
CAM_DBG(CAM_ISP, "CSID[%u] Reset discard frame config for res: %s discard_ref_cnt: %u",
|
||||||
|
csid_hw->hw_intf->hw_idx, res_name,
|
||||||
|
atomic_read(&csid_hw->discard_frame_per_path));
|
||||||
|
}
|
||||||
|
|
||||||
|
static int cam_ife_csid_ver2_discard_sof_pix_top_half(
|
||||||
|
uint32_t evt_id,
|
||||||
|
struct cam_irq_th_payload *th_payload)
|
||||||
|
{
|
||||||
|
struct cam_hw_info *hw_info;
|
||||||
|
struct cam_ife_csid_ver2_hw *csid_hw = NULL;
|
||||||
|
struct cam_isp_resource_node *res;
|
||||||
|
struct cam_ife_csid_ver2_reg_info *csid_reg = NULL;
|
||||||
|
const struct cam_ife_csid_ver2_pxl_reg_info *path_reg = NULL;
|
||||||
|
struct cam_ife_csid_ver2_path_cfg *path_cfg;
|
||||||
|
struct cam_hw_soc_info *soc_info;
|
||||||
|
void __iomem *base;
|
||||||
|
uint32_t val;
|
||||||
|
|
||||||
|
res = th_payload->handler_priv;
|
||||||
|
|
||||||
|
if (!res) {
|
||||||
|
CAM_ERR_RATE_LIMIT(CAM_ISP, "No private returned");
|
||||||
|
return -ENODEV;
|
||||||
|
}
|
||||||
|
|
||||||
|
hw_info = (struct cam_hw_info *)res->hw_intf->hw_priv;
|
||||||
|
csid_hw = (struct cam_ife_csid_ver2_hw *)hw_info->core_info;
|
||||||
|
csid_reg = (struct cam_ife_csid_ver2_reg_info *)
|
||||||
|
csid_hw->core_info->csid_reg;
|
||||||
|
path_cfg = (struct cam_ife_csid_ver2_path_cfg *)res->res_priv;
|
||||||
|
soc_info = &csid_hw->hw_info->soc_info;
|
||||||
|
base = soc_info->reg_map[CAM_IFE_CSID_CLC_MEM_BASE_ID].mem_base;
|
||||||
|
|
||||||
|
if (res->res_id == CAM_IFE_PIX_PATH_RES_IPP) {
|
||||||
|
path_reg = csid_reg->ipp_reg;
|
||||||
|
} else if (res->res_id == CAM_IFE_PIX_PATH_RES_PPP) {
|
||||||
|
path_reg = csid_reg->ppp_reg;
|
||||||
|
} else {
|
||||||
|
CAM_WARN(CAM_ISP, "Invalid res_id: 0x%x", res->res_id);
|
||||||
|
return -ENODEV;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Count SOFs */
|
||||||
|
path_cfg->sof_cnt++;
|
||||||
|
|
||||||
|
CAM_DBG(CAM_ISP, "CSID[%u] Discard frame on %s path, num SOFs: %u",
|
||||||
|
csid_hw->hw_intf->hw_idx, res->res_name, path_cfg->sof_cnt);
|
||||||
|
|
||||||
|
/* Check with requested number of frames to be dropped */
|
||||||
|
if (path_cfg->sof_cnt == path_cfg->num_frames_discard) {
|
||||||
|
if (path_cfg->sync_mode == CAM_ISP_HW_SYNC_MASTER ||
|
||||||
|
path_cfg->sync_mode == CAM_ISP_HW_SYNC_NONE) {
|
||||||
|
val = cam_io_r_mb(base + path_reg->ctrl_addr);
|
||||||
|
val |= path_reg->resume_frame_boundary;
|
||||||
|
cam_io_w_mb(val, base + path_reg->ctrl_addr);
|
||||||
|
CAM_DBG(CAM_ISP,
|
||||||
|
"CSID[%u] start cmd programmed for %s sof_cnt %u",
|
||||||
|
csid_hw->hw_intf->hw_idx,
|
||||||
|
res->res_name,
|
||||||
|
path_cfg->sof_cnt);
|
||||||
|
}
|
||||||
|
cam_ife_csid_ver2_reset_discard_frame_cfg(res->res_name, csid_hw, path_cfg);
|
||||||
|
}
|
||||||
|
|
||||||
|
return IRQ_HANDLED;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int cam_ife_csid_ver2_discard_sof_rdi_top_half(
|
||||||
|
uint32_t evt_id,
|
||||||
|
struct cam_irq_th_payload *th_payload)
|
||||||
|
{
|
||||||
|
struct cam_hw_info *hw_info;
|
||||||
|
struct cam_ife_csid_ver2_hw *csid_hw = NULL;
|
||||||
|
struct cam_isp_resource_node *res;
|
||||||
|
struct cam_ife_csid_ver2_reg_info *csid_reg = NULL;
|
||||||
|
const struct cam_ife_csid_ver2_rdi_reg_info *path_reg = NULL;
|
||||||
|
struct cam_ife_csid_ver2_path_cfg *path_cfg;
|
||||||
|
struct cam_hw_soc_info *soc_info;
|
||||||
|
void __iomem *base;
|
||||||
|
uint32_t val;
|
||||||
|
|
||||||
|
res = th_payload->handler_priv;
|
||||||
|
|
||||||
|
if (!res) {
|
||||||
|
CAM_ERR_RATE_LIMIT(CAM_ISP, "No private returned");
|
||||||
|
return -ENODEV;
|
||||||
|
}
|
||||||
|
|
||||||
|
hw_info = (struct cam_hw_info *)res->hw_intf->hw_priv;
|
||||||
|
csid_hw = (struct cam_ife_csid_ver2_hw *)hw_info->core_info;
|
||||||
|
csid_reg = (struct cam_ife_csid_ver2_reg_info *)
|
||||||
|
csid_hw->core_info->csid_reg;
|
||||||
|
path_cfg = (struct cam_ife_csid_ver2_path_cfg *)res->res_priv;
|
||||||
|
soc_info = &csid_hw->hw_info->soc_info;
|
||||||
|
base = soc_info->reg_map[CAM_IFE_CSID_CLC_MEM_BASE_ID].mem_base;
|
||||||
|
path_reg = csid_reg->rdi_reg[res->res_id];
|
||||||
|
|
||||||
|
/* Count SOFs */
|
||||||
|
path_cfg->sof_cnt++;
|
||||||
|
CAM_DBG(CAM_ISP, "CSID[%u] Discard frame on %s path, num SOFs: %u",
|
||||||
|
csid_hw->hw_intf->hw_idx, res->res_name, path_cfg->sof_cnt);
|
||||||
|
|
||||||
|
/* Check with requested number of frames to be dropped */
|
||||||
|
if (path_cfg->sof_cnt == path_cfg->num_frames_discard) {
|
||||||
|
val = cam_io_r_mb(base + path_reg->ctrl_addr);
|
||||||
|
val |= path_reg->resume_frame_boundary;
|
||||||
|
cam_io_w_mb(val, base + path_reg->ctrl_addr);
|
||||||
|
CAM_DBG(CAM_ISP,
|
||||||
|
"CSID[%u] start cmd programmed for %s sof_cnt %u",
|
||||||
|
csid_hw->hw_intf->hw_idx,
|
||||||
|
res->res_name, path_cfg->sof_cnt);
|
||||||
|
|
||||||
|
cam_ife_csid_ver2_reset_discard_frame_cfg(res->res_name, csid_hw, path_cfg);
|
||||||
|
}
|
||||||
|
|
||||||
|
return IRQ_HANDLED;
|
||||||
|
}
|
||||||
|
|
||||||
static int cam_ife_csid_ver2_stop_csi2_in_err(
|
static int cam_ife_csid_ver2_stop_csi2_in_err(
|
||||||
struct cam_ife_csid_ver2_hw *csid_hw)
|
struct cam_ife_csid_ver2_hw *csid_hw)
|
||||||
{
|
{
|
||||||
@@ -631,6 +778,8 @@ static int cam_ife_csid_ver2_rx_err_top_half(
|
|||||||
csid_hw->core_info->csid_reg;
|
csid_hw->core_info->csid_reg;
|
||||||
csi2_reg = csid_reg->csi2_reg;
|
csi2_reg = csid_reg->csi2_reg;
|
||||||
|
|
||||||
|
if (atomic_read(&csid_hw->discard_frame_per_path))
|
||||||
|
return -ENODEV;
|
||||||
|
|
||||||
if (csid_hw->flags.fatal_err_detected) {
|
if (csid_hw->flags.fatal_err_detected) {
|
||||||
CAM_INFO_RATE_LIMIT(CAM_ISP,
|
CAM_INFO_RATE_LIMIT(CAM_ISP,
|
||||||
@@ -1177,6 +1326,9 @@ static int cam_ife_csid_ver2_ipp_bottom_half(
|
|||||||
path_cfg = (struct cam_ife_csid_ver2_path_cfg *)res->res_priv;
|
path_cfg = (struct cam_ife_csid_ver2_path_cfg *)res->res_priv;
|
||||||
irq_status_ipp = payload->irq_reg_val[path_cfg->irq_reg_idx];
|
irq_status_ipp = payload->irq_reg_val[path_cfg->irq_reg_idx];
|
||||||
|
|
||||||
|
CAM_DBG(CAM_ISP, "CSID[%u] IPP status:0x%x", csid_hw->hw_intf->hw_idx,
|
||||||
|
irq_status_ipp);
|
||||||
|
|
||||||
evt_info.hw_idx = csid_hw->hw_intf->hw_idx;
|
evt_info.hw_idx = csid_hw->hw_intf->hw_idx;
|
||||||
evt_info.res_id = CAM_IFE_PIX_PATH_RES_IPP;
|
evt_info.res_id = CAM_IFE_PIX_PATH_RES_IPP;
|
||||||
evt_info.res_type = CAM_ISP_RESOURCE_PIX_PATH;
|
evt_info.res_type = CAM_ISP_RESOURCE_PIX_PATH;
|
||||||
@@ -1292,8 +1444,6 @@ static int cam_ife_csid_ver2_ppp_bottom_half(
|
|||||||
csid_reg = (struct cam_ife_csid_ver2_reg_info *)
|
csid_reg = (struct cam_ife_csid_ver2_reg_info *)
|
||||||
csid_hw->core_info->csid_reg;
|
csid_hw->core_info->csid_reg;
|
||||||
|
|
||||||
res = &csid_hw->path_res[CAM_IFE_CSID_IRQ_REG_PPP];
|
|
||||||
|
|
||||||
err_mask = csid_reg->ppp_reg->fatal_err_mask |
|
err_mask = csid_reg->ppp_reg->fatal_err_mask |
|
||||||
csid_reg->ppp_reg->non_fatal_err_mask;
|
csid_reg->ppp_reg->non_fatal_err_mask;
|
||||||
|
|
||||||
@@ -1724,6 +1874,17 @@ static int cam_ife_csid_ver2_disable_path(
|
|||||||
path_cfg->err_irq_handle = 0;
|
path_cfg->err_irq_handle = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (path_cfg->discard_irq_handle) {
|
||||||
|
rc = cam_irq_controller_unsubscribe_irq(
|
||||||
|
csid_hw->csid_irq_controller,
|
||||||
|
path_cfg->discard_irq_handle);
|
||||||
|
path_cfg->discard_irq_handle = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Reset frame drop fields at stream off */
|
||||||
|
path_cfg->discard_init_frames = false;
|
||||||
|
path_cfg->num_frames_discard = 0;
|
||||||
|
path_cfg->sof_cnt = 0;
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2539,6 +2700,41 @@ static int cam_ife_csid_ver2_init_config_pxl_path(
|
|||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline int cam_ife_csid_ver2_subscribe_sof_for_discard(
|
||||||
|
struct cam_ife_csid_ver2_path_cfg *path_cfg,
|
||||||
|
struct cam_ife_csid_ver2_hw *csid_hw,
|
||||||
|
struct cam_isp_resource_node *res,
|
||||||
|
CAM_IRQ_HANDLER_TOP_HALF top_half_handler)
|
||||||
|
{
|
||||||
|
int rc = 0;
|
||||||
|
uint32_t val;
|
||||||
|
uint32_t irq_mask[CAM_IFE_CSID_IRQ_REG_MAX] = {0};
|
||||||
|
|
||||||
|
val = IFE_CSID_VER2_PATH_INFO_INPUT_SOF;
|
||||||
|
irq_mask[path_cfg->irq_reg_idx] = val;
|
||||||
|
path_cfg->discard_irq_handle = cam_irq_controller_subscribe_irq(
|
||||||
|
csid_hw->csid_irq_controller,
|
||||||
|
CAM_IRQ_PRIORITY_1,
|
||||||
|
irq_mask,
|
||||||
|
res,
|
||||||
|
top_half_handler,
|
||||||
|
NULL,
|
||||||
|
NULL,
|
||||||
|
NULL);
|
||||||
|
|
||||||
|
if (path_cfg->discard_irq_handle < 1) {
|
||||||
|
CAM_ERR(CAM_ISP,
|
||||||
|
"CSID[%d] Subscribing input SOF failed for discarding %d",
|
||||||
|
csid_hw->hw_intf->hw_idx, res->res_id);
|
||||||
|
rc = -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
CAM_DBG(CAM_ISP,
|
||||||
|
"Subscribing input SOF for discard done res: %s rc: %d",
|
||||||
|
res->res_name, rc);
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
static int cam_ife_csid_ver2_start_rdi_path(
|
static int cam_ife_csid_ver2_start_rdi_path(
|
||||||
struct cam_ife_csid_ver2_hw *csid_hw,
|
struct cam_ife_csid_ver2_hw *csid_hw,
|
||||||
struct cam_isp_resource_node *res)
|
struct cam_isp_resource_node *res)
|
||||||
@@ -2588,9 +2784,10 @@ static int cam_ife_csid_ver2_start_rdi_path(
|
|||||||
mem_base = soc_info->reg_map[CAM_IFE_CSID_CLC_MEM_BASE_ID].mem_base;
|
mem_base = soc_info->reg_map[CAM_IFE_CSID_CLC_MEM_BASE_ID].mem_base;
|
||||||
path_cfg = (struct cam_ife_csid_ver2_path_cfg *)res->res_priv;
|
path_cfg = (struct cam_ife_csid_ver2_path_cfg *)res->res_priv;
|
||||||
if (!csid_hw->flags.offline_mode) {
|
if (!csid_hw->flags.offline_mode) {
|
||||||
/* Resume at frame boundary */
|
/* Resume at frame boundary if skip not requested */
|
||||||
cam_io_w_mb(path_reg->resume_frame_boundary,
|
if (!path_cfg->discard_init_frames)
|
||||||
mem_base + path_reg->ctrl_addr);
|
cam_io_w_mb(path_reg->resume_frame_boundary,
|
||||||
|
mem_base + path_reg->ctrl_addr);
|
||||||
|
|
||||||
CAM_DBG(CAM_ISP, "CSID:%d Rdi res: %d",
|
CAM_DBG(CAM_ISP, "CSID:%d Rdi res: %d",
|
||||||
csid_hw->hw_intf->hw_idx, res->res_id);
|
csid_hw->hw_intf->hw_idx, res->res_id);
|
||||||
@@ -2662,6 +2859,14 @@ static int cam_ife_csid_ver2_start_rdi_path(
|
|||||||
goto end;
|
goto end;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (path_cfg->discard_init_frames) {
|
||||||
|
rc = cam_ife_csid_ver2_subscribe_sof_for_discard(
|
||||||
|
path_cfg, csid_hw, res,
|
||||||
|
cam_ife_csid_ver2_discard_sof_rdi_top_half);
|
||||||
|
if (rc)
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
|
|
||||||
val = path_reg->fatal_err_mask | path_reg->non_fatal_err_mask;
|
val = path_reg->fatal_err_mask | path_reg->non_fatal_err_mask;
|
||||||
irq_mask[path_cfg->irq_reg_idx] = val;
|
irq_mask[path_cfg->irq_reg_idx] = val;
|
||||||
path_cfg->err_irq_handle = cam_irq_controller_subscribe_irq(
|
path_cfg->err_irq_handle = cam_irq_controller_subscribe_irq(
|
||||||
@@ -2790,6 +2995,14 @@ static int cam_ife_csid_ver2_start_ipp_path(
|
|||||||
goto end;
|
goto end;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (path_cfg->discard_init_frames) {
|
||||||
|
rc = cam_ife_csid_ver2_subscribe_sof_for_discard(
|
||||||
|
path_cfg, csid_hw, res,
|
||||||
|
cam_ife_csid_ver2_discard_sof_pix_top_half);
|
||||||
|
if (rc)
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
|
|
||||||
val = path_reg->fatal_err_mask | path_reg->non_fatal_err_mask;
|
val = path_reg->fatal_err_mask | path_reg->non_fatal_err_mask;
|
||||||
irq_mask[path_cfg->irq_reg_idx] = val;
|
irq_mask[path_cfg->irq_reg_idx] = val;
|
||||||
path_cfg->err_irq_handle = cam_irq_controller_subscribe_irq(
|
path_cfg->err_irq_handle = cam_irq_controller_subscribe_irq(
|
||||||
@@ -2831,9 +3044,11 @@ static int cam_ife_csid_ver2_start_ipp_path(
|
|||||||
/*
|
/*
|
||||||
* Resume at frame boundary if Master or No Sync.
|
* Resume at frame boundary if Master or No Sync.
|
||||||
* Slave will get resume command from Master.
|
* Slave will get resume command from Master.
|
||||||
|
* If init frame drop requested skip resume
|
||||||
*/
|
*/
|
||||||
if (path_cfg->sync_mode == CAM_ISP_HW_SYNC_MASTER ||
|
if ((!path_cfg->discard_init_frames) &&
|
||||||
path_cfg->sync_mode == CAM_ISP_HW_SYNC_NONE)
|
(path_cfg->sync_mode == CAM_ISP_HW_SYNC_MASTER ||
|
||||||
|
path_cfg->sync_mode == CAM_ISP_HW_SYNC_NONE))
|
||||||
val |= path_reg->resume_frame_boundary;
|
val |= path_reg->resume_frame_boundary;
|
||||||
|
|
||||||
cam_io_w_mb(val, mem_base + path_reg->ctrl_addr);
|
cam_io_w_mb(val, mem_base + path_reg->ctrl_addr);
|
||||||
@@ -2940,9 +3155,11 @@ static int cam_ife_csid_ver2_start_ppp_path(
|
|||||||
/*
|
/*
|
||||||
* Resume at frame boundary if Master or No Sync.
|
* Resume at frame boundary if Master or No Sync.
|
||||||
* Slave will get resume command from Master.
|
* Slave will get resume command from Master.
|
||||||
|
* If init frame drop requested skip resume
|
||||||
*/
|
*/
|
||||||
if (csid_hw->sync_mode == CAM_ISP_HW_SYNC_MASTER ||
|
if ((!path_cfg->discard_init_frames) &&
|
||||||
csid_hw->sync_mode == CAM_ISP_HW_SYNC_NONE)
|
(csid_hw->sync_mode == CAM_ISP_HW_SYNC_MASTER ||
|
||||||
|
csid_hw->sync_mode == CAM_ISP_HW_SYNC_NONE))
|
||||||
val |= path_reg->resume_frame_boundary;
|
val |= path_reg->resume_frame_boundary;
|
||||||
|
|
||||||
cam_io_w_mb(val, mem_base + path_reg->ctrl_addr);
|
cam_io_w_mb(val, mem_base + path_reg->ctrl_addr);
|
||||||
@@ -2980,6 +3197,14 @@ static int cam_ife_csid_ver2_start_ppp_path(
|
|||||||
goto end;
|
goto end;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (path_cfg->discard_init_frames) {
|
||||||
|
rc = cam_ife_csid_ver2_subscribe_sof_for_discard(
|
||||||
|
path_cfg, csid_hw, res,
|
||||||
|
cam_ife_csid_ver2_discard_sof_pix_top_half);
|
||||||
|
if (rc)
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
|
|
||||||
val = path_reg->fatal_err_mask | path_reg->non_fatal_err_mask;
|
val = path_reg->fatal_err_mask | path_reg->non_fatal_err_mask;
|
||||||
irq_mask[path_cfg->irq_reg_idx] = val;
|
irq_mask[path_cfg->irq_reg_idx] = val;
|
||||||
path_cfg->err_irq_handle = cam_irq_controller_subscribe_irq(
|
path_cfg->err_irq_handle = cam_irq_controller_subscribe_irq(
|
||||||
@@ -3661,6 +3886,7 @@ int cam_ife_csid_ver2_stop(void *hw_priv,
|
|||||||
csid_hw->hw_intf->hw_idx,
|
csid_hw->hw_intf->hw_idx,
|
||||||
csid_stop->num_res);
|
csid_stop->num_res);
|
||||||
|
|
||||||
|
atomic_set(&csid_hw->discard_frame_per_path, 0);
|
||||||
mutex_lock(&csid_hw->hw_info->hw_mutex);
|
mutex_lock(&csid_hw->hw_info->hw_mutex);
|
||||||
for (i = 0; i < csid_stop->num_res; i++) {
|
for (i = 0; i < csid_stop->num_res; i++) {
|
||||||
|
|
||||||
@@ -4197,6 +4423,62 @@ static int cam_ife_csid_ver2_dual_sync_cfg(
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int cam_ife_csid_ver2_set_discard_frame_cfg(
|
||||||
|
struct cam_ife_csid_ver2_hw *csid_hw,
|
||||||
|
void *cmd_args)
|
||||||
|
{
|
||||||
|
struct cam_isp_resource_node *res;
|
||||||
|
struct cam_ife_csid_ver2_path_cfg *path_cfg;
|
||||||
|
struct cam_ife_csid_discard_init_frame_args *discard_config = NULL;
|
||||||
|
|
||||||
|
if (!csid_hw)
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
discard_config =
|
||||||
|
(struct cam_ife_csid_discard_init_frame_args *)cmd_args;
|
||||||
|
|
||||||
|
if (discard_config->num_frames == 0xffffffff) {
|
||||||
|
CAM_ERR(CAM_ISP, "Invalid number of frames: 0x%x",
|
||||||
|
discard_config->num_frames);
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!discard_config->num_frames) {
|
||||||
|
CAM_DBG(CAM_ISP, "No discard requested");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
res = discard_config->res;
|
||||||
|
if (res->res_type != CAM_ISP_RESOURCE_PIX_PATH ||
|
||||||
|
res->res_id >= CAM_IFE_PIX_PATH_RES_MAX) {
|
||||||
|
CAM_ERR(CAM_ISP, "CSID[%u] Invalid res_type: %d res id: %d",
|
||||||
|
csid_hw->hw_intf->hw_idx, res->res_type,
|
||||||
|
res->res_id);
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Handle first stream on and consecutive streamons post flush */
|
||||||
|
if ((res->res_state == CAM_ISP_RESOURCE_STATE_RESERVED) ||
|
||||||
|
(res->res_state == CAM_ISP_RESOURCE_STATE_INIT_HW)) {
|
||||||
|
/* Skip if already set */
|
||||||
|
path_cfg = (struct cam_ife_csid_ver2_path_cfg *)res->res_priv;
|
||||||
|
if (path_cfg->discard_init_frames)
|
||||||
|
goto end;
|
||||||
|
|
||||||
|
path_cfg->discard_init_frames = true;
|
||||||
|
path_cfg->sof_cnt = 0;
|
||||||
|
path_cfg->num_frames_discard = discard_config->num_frames;
|
||||||
|
atomic_inc(&csid_hw->discard_frame_per_path);
|
||||||
|
CAM_DBG(CAM_ISP,
|
||||||
|
"CSID[%u] discard num of frames: %u for path: %s discard_ref_cnt: %u",
|
||||||
|
csid_hw->hw_intf->hw_idx, discard_config->num_frames, res->res_name,
|
||||||
|
atomic_read(&csid_hw->discard_frame_per_path));
|
||||||
|
}
|
||||||
|
|
||||||
|
end:
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static int cam_ife_csid_ver2_process_cmd(void *hw_priv,
|
static int cam_ife_csid_ver2_process_cmd(void *hw_priv,
|
||||||
uint32_t cmd_type, void *cmd_args, uint32_t arg_size)
|
uint32_t cmd_type, void *cmd_args, uint32_t arg_size)
|
||||||
{
|
{
|
||||||
@@ -4268,6 +4550,9 @@ static int cam_ife_csid_ver2_process_cmd(void *hw_priv,
|
|||||||
*((struct cam_hw_soc_info **)cmd_args) = soc_info;
|
*((struct cam_hw_soc_info **)cmd_args) = soc_info;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case CAM_ISP_HW_CMD_CSID_DISCARD_INIT_FRAMES:
|
||||||
|
rc = cam_ife_csid_ver2_set_discard_frame_cfg(csid_hw, cmd_args);
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
CAM_ERR(CAM_ISP, "CSID:%d unsupported cmd:%d",
|
CAM_ERR(CAM_ISP, "CSID:%d unsupported cmd:%d",
|
||||||
csid_hw->hw_intf->hw_idx, cmd_type);
|
csid_hw->hw_intf->hw_idx, cmd_type);
|
||||||
@@ -4526,6 +4811,7 @@ int cam_ife_csid_hw_ver2_init(struct cam_hw_intf *hw_intf,
|
|||||||
spin_lock_init(&csid_hw->hw_info->hw_lock);
|
spin_lock_init(&csid_hw->hw_info->hw_lock);
|
||||||
spin_lock_init(&csid_hw->lock_state);
|
spin_lock_init(&csid_hw->lock_state);
|
||||||
init_completion(&csid_hw->hw_info->hw_complete);
|
init_completion(&csid_hw->hw_info->hw_complete);
|
||||||
|
atomic_set(&csid_hw->discard_frame_per_path, 0);
|
||||||
|
|
||||||
for (i = 0; i < CAM_IFE_PIX_PATH_RES_MAX; i++)
|
for (i = 0; i < CAM_IFE_PIX_PATH_RES_MAX; i++)
|
||||||
init_completion(&csid_hw->irq_complete[i]);
|
init_completion(&csid_hw->irq_complete[i]);
|
||||||
|
@@ -144,32 +144,36 @@ struct cam_ife_csid_ver2_camif_data {
|
|||||||
/*
|
/*
|
||||||
* struct cam_ife_csid_ver2_path_cfg: place holder for path parameters
|
* struct cam_ife_csid_ver2_path_cfg: place holder for path parameters
|
||||||
*
|
*
|
||||||
* @camif_data: CAMIF data
|
* @camif_data: CAMIF data
|
||||||
* @error_ts: Error timestamp
|
* @error_ts: Error timestamp
|
||||||
* @cid: cid value for path
|
* @cid: cid value for path
|
||||||
* @in_format: input format
|
* @in_format: input format
|
||||||
* @out_format: output format
|
* @out_format: output format
|
||||||
* @start_pixel: start pixel for horizontal crop
|
* @start_pixel: start pixel for horizontal crop
|
||||||
* @end_pixel: end pixel for horizontal crop
|
* @end_pixel: end pixel for horizontal crop
|
||||||
* @start_line: start line for vertical crop
|
* @start_line: start line for vertical crop
|
||||||
* @end_line: end line for vertical crop
|
* @end_line: end line for vertical crop
|
||||||
* @width: width of incoming data
|
* @width: width of incoming data
|
||||||
* @height: height of incoming data
|
* @height: height of incoming data
|
||||||
* @master_idx: master idx
|
* @master_idx: master idx
|
||||||
* @horizontal_bin: horizontal binning enable/disable on path
|
* @horizontal_bin: horizontal binning enable/disable on path
|
||||||
* @vertical_bin: vertical binning enable/disable on path
|
* @vertical_bin: vertical binning enable/disable on path
|
||||||
* @qcfa_bin : qcfa binning enable/disable on path
|
* @qcfa_bin : qcfa binning enable/disable on path
|
||||||
* @hor_ver_bin : horizontal vertical binning enable/disable on path
|
* @hor_ver_bin : horizontal vertical binning enable/disable on path
|
||||||
* @num_bytes_out: Number of bytes out
|
* @num_bytes_out: Number of bytes out
|
||||||
* @pix_pattern: Pixel Pattern
|
* @pix_pattern: Pixel Pattern
|
||||||
* @irq_handle: IRQ handle
|
* @irq_handle: IRQ handle
|
||||||
* @err_irq_handle: Error IRQ handle
|
* @err_irq_handle: Error IRQ handle
|
||||||
* @irq_reg_idx: IRQ Reg index
|
* @discard_irq_handle: IRQ handle for SOF when discarding initial frames
|
||||||
* @sync_mode : Sync mode--> master/slave/none
|
* @irq_reg_idx: IRQ Reg index
|
||||||
* @vfr_en : flag to indicate if variable frame rate is enabled
|
* @sof_cnt: SOF counter
|
||||||
* @frame_id_dec_en: flag to indicate if frame id decoding is enabled
|
* @num_frames_discard: number of frames to discard
|
||||||
* @crop_enable: flag to indicate crop enable
|
* @sync_mode : Sync mode--> master/slave/none
|
||||||
* @drop_enable: flag to indicate drop enable
|
* @vfr_en : flag to indicate if variable frame rate is enabled
|
||||||
|
* @frame_id_dec_en: flag to indicate if frame id decoding is enabled
|
||||||
|
* @crop_enable: flag to indicate crop enable
|
||||||
|
* @drop_enable: flag to indicate drop enable
|
||||||
|
* @discard_init_frames: discard initial frames
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
struct cam_ife_csid_ver2_path_cfg {
|
struct cam_ife_csid_ver2_path_cfg {
|
||||||
@@ -194,13 +198,17 @@ struct cam_ife_csid_ver2_path_cfg {
|
|||||||
uint32_t pix_pattern;
|
uint32_t pix_pattern;
|
||||||
uint32_t irq_handle;
|
uint32_t irq_handle;
|
||||||
uint32_t err_irq_handle;
|
uint32_t err_irq_handle;
|
||||||
|
uint32_t discard_irq_handle;
|
||||||
uint32_t irq_reg_idx;
|
uint32_t irq_reg_idx;
|
||||||
|
uint32_t sof_cnt;
|
||||||
|
uint32_t num_frames_discard;
|
||||||
enum cam_isp_hw_sync_mode sync_mode;
|
enum cam_isp_hw_sync_mode sync_mode;
|
||||||
bool vfr_en;
|
bool vfr_en;
|
||||||
bool frame_id_dec_en;
|
bool frame_id_dec_en;
|
||||||
bool crop_enable;
|
bool crop_enable;
|
||||||
bool drop_enable;
|
bool drop_enable;
|
||||||
bool handle_camif_irq;
|
bool handle_camif_irq;
|
||||||
|
bool discard_init_frames;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct cam_ife_csid_ver2_top_reg_info {
|
struct cam_ife_csid_ver2_top_reg_info {
|
||||||
@@ -606,6 +614,7 @@ struct cam_ife_csid_ver2_reg_info {
|
|||||||
* @buf_done_irq_handle: Buf done irq handle
|
* @buf_done_irq_handle: Buf done irq handle
|
||||||
* @sync_mode: Master/Slave modes
|
* @sync_mode: Master/Slave modes
|
||||||
* @mup: MUP for incoming VC of next frame
|
* @mup: MUP for incoming VC of next frame
|
||||||
|
* @discard_frame_per_path: Count of paths dropping initial frames
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
struct cam_ife_csid_ver2_hw {
|
struct cam_ife_csid_ver2_hw {
|
||||||
@@ -646,6 +655,7 @@ struct cam_ife_csid_ver2_hw {
|
|||||||
int buf_done_irq_handle;
|
int buf_done_irq_handle;
|
||||||
enum cam_isp_hw_sync_mode sync_mode;
|
enum cam_isp_hw_sync_mode sync_mode;
|
||||||
uint32_t mup;
|
uint32_t mup;
|
||||||
|
atomic_t discard_frame_per_path;
|
||||||
};
|
};
|
||||||
|
|
||||||
int cam_ife_csid_hw_ver2_init(struct cam_hw_intf *csid_hw_intf,
|
int cam_ife_csid_hw_ver2_init(struct cam_hw_intf *csid_hw_intf,
|
||||||
|
@@ -382,4 +382,16 @@ struct cam_ife_csid_offline_cmd_update_args {
|
|||||||
struct cam_ife_csid_mup_update_args {
|
struct cam_ife_csid_mup_update_args {
|
||||||
uint32_t mup;
|
uint32_t mup;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* struct cam_ife_csid_discard_init_frame_args:
|
||||||
|
*
|
||||||
|
* @num_frames: Num frames to discard
|
||||||
|
* @res: Node res for this path
|
||||||
|
*/
|
||||||
|
struct cam_ife_csid_discard_init_frame_args {
|
||||||
|
uint32_t num_frames;
|
||||||
|
struct cam_isp_resource_node *res;
|
||||||
|
};
|
||||||
|
|
||||||
#endif /* _CAM_CSID_HW_INTF_H_ */
|
#endif /* _CAM_CSID_HW_INTF_H_ */
|
||||||
|
@@ -151,6 +151,7 @@ enum cam_isp_hw_cmd_type {
|
|||||||
CAM_IFE_CSID_PROGRAM_OFFLINE_CMD,
|
CAM_IFE_CSID_PROGRAM_OFFLINE_CMD,
|
||||||
CAM_IFE_CSID_SET_DUAL_SYNC_CONFIG,
|
CAM_IFE_CSID_SET_DUAL_SYNC_CONFIG,
|
||||||
CAM_ISP_HW_CMD_CSID_MUP_UPDATE,
|
CAM_ISP_HW_CMD_CSID_MUP_UPDATE,
|
||||||
|
CAM_ISP_HW_CMD_CSID_DISCARD_INIT_FRAMES,
|
||||||
CAM_ISP_HW_CMD_BUF_UPDATE,
|
CAM_ISP_HW_CMD_BUF_UPDATE,
|
||||||
CAM_ISP_HW_CMD_BUF_UPDATE_RM,
|
CAM_ISP_HW_CMD_BUF_UPDATE_RM,
|
||||||
CAM_ISP_HW_NOTIFY_OVERFLOW,
|
CAM_ISP_HW_NOTIFY_OVERFLOW,
|
||||||
|
مرجع در شماره جدید
Block a user