diff --git a/drivers/cam_isp/isp_hw_mgr/cam_tfe_hw_mgr.c b/drivers/cam_isp/isp_hw_mgr/cam_tfe_hw_mgr.c index 8d241b89d6..6d83e7f7ce 100644 --- a/drivers/cam_isp/isp_hw_mgr/cam_tfe_hw_mgr.c +++ b/drivers/cam_isp/isp_hw_mgr/cam_tfe_hw_mgr.c @@ -4645,6 +4645,59 @@ static inline int cam_isp_tfe_validate_bw_limiter_blob( return 0; } +static int cam_isp_tfe_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_tfe_hw_mgr_ctx *ctx = NULL; + struct cam_hw_intf *hw_intf; + struct cam_isp_hw_mgr_res *hw_mgr_res; + struct cam_isp_resource_node *res; + struct cam_tfe_csid_discard_init_frame_args discard_args; + int rc = 0, i; + + ctx = prepare->ctxt_to_hw_map; + discard_args.num_frames = discard_config->num_frames; + + if (discard_args.num_frames <= 0) { + CAM_DBG(CAM_ISP, "Invalid num of frames %d CSID[%u]", + discard_args.num_frames, blob_info->base_info->idx); + return rc; + } + + CAM_DBG(CAM_ISP, "Num of frame to be drop %d on CSID[%u]", discard_args.num_frames, + blob_info->base_info->idx); + + list_for_each_entry(hw_mgr_res, &ctx->res_list_tfe_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)) + continue; + + 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_tfe_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); + } + } + } + + return rc; +} + static int cam_isp_tfe_packet_generic_blob_handler(void *user_data, uint32_t blob_type, uint32_t blob_size, uint8_t *blob_data) { @@ -5014,6 +5067,25 @@ static int cam_isp_tfe_packet_generic_blob_handler(void *user_data, prepare->packet->header.request_id, rc, tfe_mgr_ctx->ctx_index); } break; + case CAM_ISP_TFE_GENERIC_BLOB_TYPE_DISCARD_INITIAL_FRAMES: { + struct cam_isp_discard_initial_frames *discard_config; + + if (blob_size < sizeof(struct cam_isp_tfe_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_tfe_blob_csid_discard_init_frame_update( + blob_info, discard_config, prepare); + if (rc) + CAM_ERR(CAM_ISP, "Discard init frames update failed rc %d req %lld", + rc, prepare->packet->header.request_id); + } + break; default: CAM_WARN(CAM_ISP, "Invalid blob type %d ctx %d", blob_type, tfe_mgr_ctx->ctx_index); diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/include/cam_tfe_csid_hw_intf.h b/drivers/cam_isp/isp_hw_mgr/isp_hw/include/cam_tfe_csid_hw_intf.h index 8d163c82fe..9cf4661a77 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/include/cam_tfe_csid_hw_intf.h +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/include/cam_tfe_csid_hw_intf.h @@ -273,5 +273,15 @@ struct cam_tfe_csid_clock_update_args { uint64_t clk_rate; }; +/* + * struct cam_tfe_csid_discard_init_frame_args: + * + * @num_frames: Num frames to discard + * @res: Node res for this path + */ +struct cam_tfe_csid_discard_init_frame_args { + uint32_t num_frames; + struct cam_isp_resource_node *res; +}; #endif /* _CAM_TFE_CSID_HW_INTF_H_ */ diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_csid_hw/cam_tfe_csid_core.c b/drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_csid_hw/cam_tfe_csid_core.c index 17850d0846..c32abb4976 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_csid_hw/cam_tfe_csid_core.c +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_csid_hw/cam_tfe_csid_core.c @@ -251,6 +251,9 @@ static void cam_tfe_csid_enable_path_for_init_frame_drop( if (res_id == CAM_TFE_CSID_PATH_RES_IPP) { res = &csid_hw->ipp_res; pxl_reg = csid_reg->ipp_reg; + } else if (res_id == CAM_TFE_CSID_PATH_RES_PPP) { + res = &csid_hw->ppp_res; + pxl_reg = csid_reg->ppp_reg; } else if (res_id >= CAM_TFE_CSID_PATH_RES_RDI_0 && res_id <= CAM_TFE_CSID_PATH_RES_RDI_2) { res = &csid_hw->rdi_res[res_id]; @@ -282,8 +285,9 @@ static void cam_tfe_csid_enable_path_for_init_frame_drop( if ((path_data->res_sof_cnt == path_data->init_frame_drop) && pxl_reg) { - CAM_DBG(CAM_ISP, "CSID:%d Enabling pixel IPP Path", - csid_hw->hw_intf->hw_idx); + CAM_DBG(CAM_ISP, "CSID:%d Enabling pixel %s Path", + csid_hw->hw_intf->hw_idx, + (res_id == CAM_TFE_CSID_PATH_RES_IPP) ? "IPP" : "PPP"); if (path_data->sync_mode != CAM_ISP_HW_SYNC_SLAVE) { val = cam_io_r_mb(soc_info->reg_map[0].mem_base + @@ -1670,8 +1674,8 @@ static int cam_tfe_csid_enable_pxl_path( * Resume at frame boundary if Master or No Sync. * Slave will get resume command from Master. */ - if (path_data->sync_mode == CAM_ISP_HW_SYNC_MASTER || - path_data->sync_mode == CAM_ISP_HW_SYNC_NONE) + if ((path_data->sync_mode == CAM_ISP_HW_SYNC_MASTER || + path_data->sync_mode == CAM_ISP_HW_SYNC_NONE) && !path_data->init_frame_drop) val |= CAM_TFE_CSID_RESUME_AT_FRAME_BOUNDARY; cam_io_w_mb(val, soc_info->reg_map[0].mem_base + @@ -1691,7 +1695,7 @@ static int cam_tfe_csid_enable_pxl_path( TFE_CSID_PATH_ERROR_LINE_COUNT; } - if (csid_hw->csid_debug & TFE_CSID_DEBUG_ENABLE_SOF_IRQ) + if (csid_hw->csid_debug & TFE_CSID_DEBUG_ENABLE_SOF_IRQ || path_data->init_frame_drop) val |= TFE_CSID_PATH_INFO_INPUT_SOF; if (csid_hw->csid_debug & TFE_CSID_DEBUG_ENABLE_EOF_IRQ) val |= TFE_CSID_PATH_INFO_INPUT_EOF; @@ -1831,6 +1835,9 @@ static int cam_tfe_csid_disable_pxl_path( pxl_reg->csid_pxl_ctrl_addr); } + path_data->init_frame_drop = 0; + path_data->res_sof_cnt = 0; + return rc; } @@ -1886,8 +1893,8 @@ static int cam_tfe_csid_enable_ppp_path( * Resume at frame boundary if Master or No Sync. * Slave will get resume command from Master. */ - if (path_data->sync_mode == CAM_ISP_HW_SYNC_MASTER || - path_data->sync_mode == CAM_ISP_HW_SYNC_NONE) + if ((path_data->sync_mode == CAM_ISP_HW_SYNC_MASTER || + path_data->sync_mode == CAM_ISP_HW_SYNC_NONE) && !path_data->init_frame_drop) val |= CAM_TFE_CSID_RESUME_AT_FRAME_BOUNDARY; cam_io_w_mb(val, soc_info->reg_map[0].mem_base + ppp_reg->csid_pxl_ctrl_addr); @@ -1901,7 +1908,7 @@ static int cam_tfe_csid_enable_ppp_path( if (csid_reg->cmn_reg->format_measure_support) val |= TFE_CSID_PATH_ERROR_PIX_COUNT | TFE_CSID_PATH_ERROR_LINE_COUNT; - if (csid_hw->csid_debug & TFE_CSID_DEBUG_ENABLE_SOF_IRQ) + if (csid_hw->csid_debug & TFE_CSID_DEBUG_ENABLE_SOF_IRQ || path_data->init_frame_drop) val |= TFE_CSID_PATH_INFO_INPUT_SOF; if (csid_hw->csid_debug & TFE_CSID_DEBUG_ENABLE_EOF_IRQ) val |= TFE_CSID_PATH_INFO_INPUT_EOF; @@ -1999,6 +2006,9 @@ static int cam_tfe_csid_disable_ppp_path( ppp_reg->csid_pxl_ctrl_addr); } + path_data->init_frame_drop = 0; + path_data->res_sof_cnt = 0; + return rc; } @@ -3261,6 +3271,38 @@ end: return rc; } +static int cam_tfe_csid_set_discard_frame_cfg( + struct cam_tfe_csid_hw *csid_hw, void *cmd_args) +{ + struct cam_isp_resource_node *res; + struct cam_tfe_csid_path_cfg *path_cfg; + struct cam_tfe_csid_discard_init_frame_args *discard_config = NULL; + + if (!csid_hw) + return -EINVAL; + + discard_config = (struct cam_tfe_csid_discard_init_frame_args *)cmd_args; + + res = discard_config->res; + if (res->res_type != CAM_ISP_RESOURCE_PIX_PATH || + res->res_id >= CAM_TFE_CSID_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; + } + + if ((res->res_state == CAM_ISP_RESOURCE_STATE_RESERVED) || + (res->res_state == CAM_ISP_RESOURCE_STATE_INIT_HW)) { + + path_cfg = (struct cam_tfe_csid_path_cfg *)res->res_priv; + + path_cfg->init_frame_drop = discard_config->num_frames; + path_cfg->res_sof_cnt = 0; + } + + return 0; +} + static int cam_tfe_csid_get_regdump(struct cam_tfe_csid_hw *csid_hw, void *cmd_args) { @@ -3572,6 +3614,9 @@ static int cam_tfe_csid_process_cmd(void *hw_priv, case CAM_ISP_HW_CMD_DYNAMIC_CLOCK_UPDATE: rc = cam_tfe_csid_set_csid_clock_dynamically(csid_hw, cmd_args); break; + case CAM_ISP_HW_CMD_CSID_DISCARD_INIT_FRAMES: + rc = cam_tfe_csid_set_discard_frame_cfg(csid_hw, cmd_args); + break; default: CAM_ERR(CAM_ISP, "CSID:%d unsupported cmd:%d", csid_hw->hw_intf->hw_idx, cmd_type); @@ -4101,6 +4146,12 @@ handle_fatal_error: complete(&csid_hw->csid_ipp_complete); } + if (irq_status[TFE_CSID_IRQ_REG_IPP] & TFE_CSID_PATH_INFO_INPUT_SOF) { + CAM_DBG(CAM_ISP, "CSID:%d IPP SOF received", csid_hw->hw_intf->hw_idx); + cam_tfe_csid_enable_path_for_init_frame_drop(csid_hw, + CAM_TFE_CSID_PATH_RES_IPP); + } + if ((irq_status[TFE_CSID_IRQ_REG_IPP] & TFE_CSID_PATH_INFO_INPUT_SOF) && (csid_hw->csid_debug & TFE_CSID_DEBUG_ENABLE_SOF_IRQ)) { @@ -4179,6 +4230,12 @@ handle_fatal_error: complete(&csid_hw->csid_ppp_complete); } + if (irq_status[TFE_CSID_IRQ_REG_PPP] & TFE_CSID_PATH_INFO_INPUT_SOF) { + CAM_DBG(CAM_ISP, "CSID:%d PPP SOF received", csid_hw->hw_intf->hw_idx); + cam_tfe_csid_enable_path_for_init_frame_drop(csid_hw, + CAM_TFE_CSID_PATH_RES_PPP); + } + if ((irq_status[TFE_CSID_IRQ_REG_PPP] & TFE_CSID_PATH_INFO_INPUT_SOF) && (csid_hw->csid_debug & TFE_CSID_DEBUG_ENABLE_SOF_IRQ)) { @@ -4265,8 +4322,11 @@ handle_fatal_error: complete(&csid_hw->csid_rdin_complete[i]); } - if (irq_status[i] & TFE_CSID_PATH_INFO_INPUT_SOF) + if (irq_status[i] & TFE_CSID_PATH_INFO_INPUT_SOF) { + CAM_DBG(CAM_ISP, "CSID:%d RDI:%d SOF received", + csid_hw->hw_intf->hw_idx); cam_tfe_csid_enable_path_for_init_frame_drop(csid_hw, i); + } if ((irq_status[i] & TFE_CSID_PATH_INFO_INPUT_SOF) && (csid_hw->csid_debug & TFE_CSID_DEBUG_ENABLE_SOF_IRQ)) { diff --git a/include/uapi/camera/media/cam_tfe.h b/include/uapi/camera/media/cam_tfe.h index 71b62db40f..0809aee467 100644 --- a/include/uapi/camera/media/cam_tfe.h +++ b/include/uapi/camera/media/cam_tfe.h @@ -70,15 +70,16 @@ #define CAM_ISP_TFE_PACKET_META_GENERIC_BLOB_RIGHT 10 /* ISP TFE Generic Cmd Buffer Blob types */ -#define CAM_ISP_TFE_GENERIC_BLOB_TYPE_HFR_CONFIG 0 -#define CAM_ISP_TFE_GENERIC_BLOB_TYPE_CLOCK_CONFIG 1 -#define CAM_ISP_TFE_GENERIC_BLOB_TYPE_BW_CONFIG_V2 2 -#define CAM_ISP_TFE_GENERIC_BLOB_TYPE_CSID_CLOCK_CONFIG 3 -#define CAM_ISP_TFE_GENERIC_BLOB_TYPE_INIT_CONFIG 4 -#define CAM_ISP_TFE_GENERIC_BLOB_TYPE_DYNAMIC_MODE_SWITCH 15 -#define CAM_ISP_TFE_GENERIC_BLOB_TYPE_BW_LIMITER_CFG 16 -#define CAM_ISP_TFE_GENERIC_BLOB_TYPE_ALIGNMENT_OFFSET_INFO 17 -#define CAM_ISP_TFE_GENERIC_BLOB_TYPE_UPDATE_OUT_RES 18 +#define CAM_ISP_TFE_GENERIC_BLOB_TYPE_HFR_CONFIG 0 +#define CAM_ISP_TFE_GENERIC_BLOB_TYPE_CLOCK_CONFIG 1 +#define CAM_ISP_TFE_GENERIC_BLOB_TYPE_BW_CONFIG_V2 2 +#define CAM_ISP_TFE_GENERIC_BLOB_TYPE_CSID_CLOCK_CONFIG 3 +#define CAM_ISP_TFE_GENERIC_BLOB_TYPE_INIT_CONFIG 4 +#define CAM_ISP_TFE_GENERIC_BLOB_TYPE_DYNAMIC_MODE_SWITCH 15 +#define CAM_ISP_TFE_GENERIC_BLOB_TYPE_BW_LIMITER_CFG 16 +#define CAM_ISP_TFE_GENERIC_BLOB_TYPE_ALIGNMENT_OFFSET_INFO 17 +#define CAM_ISP_TFE_GENERIC_BLOB_TYPE_UPDATE_OUT_RES 18 +#define CAM_ISP_TFE_GENERIC_BLOB_TYPE_DISCARD_INITIAL_FRAMES 19 /* DSP mode */ #define CAM_ISP_TFE_DSP_MODE_NONE 0 @@ -594,6 +595,22 @@ struct cam_isp_tfe_out_resource_config { struct cam_isp_tfe_wm_dimension_config dimension_config[1]; }; +/** + * struct cam_isp_tfe_discard_initial_frames - Discard init frames + * + * Some sensors require discarding the initial frames + * after the sensor is streamed on. The discard would be + * applied on all paths [IPP/PPP/RDIx] for the given + * pipeline. + * + * @version : Version field + * @num_frames : Number of frames to be discarded + */ +struct cam_isp_tfe_discard_initial_frames { + __u32 version; + __u32 num_frames; +} __attribute__((packed)); + #define CAM_TFE_ACQUIRE_COMMON_VER0 0x1000 #define CAM_TFE_ACQUIRE_COMMON_SIZE_VER0 0x0