diff --git a/Kbuild b/Kbuild index 78d1a0a3a0..afb554907b 100644 --- a/Kbuild +++ b/Kbuild @@ -264,7 +264,7 @@ camera-$(CONFIG_SPECTRA_TFE) += \ drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_csid_hw/cam_tfe_csid_dev.o \ drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_csid_hw/cam_tfe_csid_soc.o \ drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_csid_hw/cam_tfe_csid_core.o \ - drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_csid_hw/cam_tfe_csid530.o \ + drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_csid_hw/cam_tfe_csid.o \ drivers/cam_isp/isp_hw_mgr/cam_tfe_hw_mgr.o camera-y += drivers/camera_main.o 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 626bbbd9f4..e05f872f26 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 @@ -835,13 +835,13 @@ static int cam_tfe_mgr_process_base_info( } static int cam_tfe_hw_mgr_acquire_res_tfe_out_rdi( - struct cam_tfe_hw_mgr_ctx *tfe_ctx, - struct cam_isp_hw_mgr_res *tfe_in_res, - struct cam_isp_tfe_in_port_info *in_port) + struct cam_tfe_hw_mgr_ctx *tfe_ctx, + struct cam_isp_hw_mgr_res *tfe_in_res, + struct cam_isp_tfe_in_port_generic_info *in_port) { int rc = -EINVAL; - struct cam_tfe_acquire_args tfe_acquire; - struct cam_isp_tfe_out_port_info *out_port = NULL; + struct cam_tfe_acquire_args tfe_acquire; + struct cam_isp_tfe_out_port_generic_info *out_port = NULL; struct cam_isp_hw_mgr_res *tfe_out_res; struct cam_hw_intf *hw_intf; uint32_t i, tfe_out_res_id, tfe_in_res_id; @@ -917,14 +917,14 @@ err: } static int cam_tfe_hw_mgr_acquire_res_tfe_out_pixel( - struct cam_tfe_hw_mgr_ctx *tfe_ctx, - struct cam_isp_hw_mgr_res *tfe_in_res, - struct cam_isp_tfe_in_port_info *in_port) + struct cam_tfe_hw_mgr_ctx *tfe_ctx, + struct cam_isp_hw_mgr_res *tfe_in_res, + struct cam_isp_tfe_in_port_generic_info *in_port) { int rc = -EINVAL; uint32_t i, j, k; struct cam_tfe_acquire_args tfe_acquire; - struct cam_isp_tfe_out_port_info *out_port; + struct cam_isp_tfe_out_port_generic_info *out_port; struct cam_isp_hw_mgr_res *tfe_out_res; struct cam_hw_intf *hw_intf; @@ -1002,8 +1002,8 @@ err: } static int cam_tfe_hw_mgr_acquire_res_tfe_out( - struct cam_tfe_hw_mgr_ctx *tfe_ctx, - struct cam_isp_tfe_in_port_info *in_port) + struct cam_tfe_hw_mgr_ctx *tfe_ctx, + struct cam_isp_tfe_in_port_generic_info *in_port) { int rc = -EINVAL; struct cam_isp_hw_mgr_res *tfe_in_res; @@ -1039,8 +1039,8 @@ err: } static int cam_tfe_hw_mgr_acquire_res_tfe_in( - struct cam_tfe_hw_mgr_ctx *tfe_ctx, - struct cam_isp_tfe_in_port_info *in_port, + struct cam_tfe_hw_mgr_ctx *tfe_ctx, + struct cam_isp_tfe_in_port_generic_info *in_port, uint32_t *pdaf_enable) { int rc = -EINVAL; @@ -1156,8 +1156,8 @@ err: } static int cam_tfe_hw_mgr_acquire_res_tfe_csid_pxl( - struct cam_tfe_hw_mgr_ctx *tfe_ctx, - struct cam_isp_tfe_in_port_info *in_port) + struct cam_tfe_hw_mgr_ctx *tfe_ctx, + struct cam_isp_tfe_in_port_generic_info *in_port) { int rc = -EINVAL; int i, j; @@ -1168,7 +1168,7 @@ static int cam_tfe_hw_mgr_acquire_res_tfe_csid_pxl( struct cam_tfe_csid_hw_reserve_resource_args csid_acquire; enum cam_tfe_csid_path_res_id path_res_id; struct cam_isp_hw_mgr_res *csid_res_temp, *csid_res_iterator; - struct cam_isp_tfe_out_port_info *out_port = NULL; + struct cam_isp_tfe_out_port_generic_info *out_port = NULL; tfe_hw_mgr = tfe_ctx->hw_mgr; /* get csid resource */ @@ -1398,9 +1398,9 @@ end: } static int cam_tfe_hw_mgr_acquire_tpg( - struct cam_tfe_hw_mgr_ctx *tfe_ctx, - struct cam_isp_tfe_in_port_info **in_port, - uint32_t num_inport) + struct cam_tfe_hw_mgr_ctx *tfe_ctx, + struct cam_isp_tfe_in_port_generic_info *in_port, + uint32_t num_inport) { int rc = -EINVAL; uint32_t i, j = 0; @@ -1418,7 +1418,7 @@ static int cam_tfe_hw_mgr_acquire_tpg( tpg_reserve.num_inport = num_inport; tpg_reserve.node_res = NULL; for (j = 0; j < num_inport; j++) - tpg_reserve.in_port[j] = in_port[j]; + tpg_reserve.in_port[j] = &in_port[j]; rc = hw_intf->hw_ops.reserve(hw_intf->hw_priv, &tpg_reserve, sizeof(tpg_reserve)); @@ -1469,19 +1469,19 @@ static enum cam_tfe_csid_path_res_id } static int cam_tfe_hw_mgr_acquire_res_tfe_csid_rdi( - struct cam_tfe_hw_mgr_ctx *tfe_ctx, - struct cam_isp_tfe_in_port_info *in_port) + struct cam_tfe_hw_mgr_ctx *tfe_ctx, + struct cam_isp_tfe_in_port_generic_info *in_port) { int rc = -EINVAL; int i, j; - struct cam_tfe_hw_mgr *tfe_hw_mgr; - struct cam_isp_hw_mgr_res *csid_res; - struct cam_hw_intf *hw_intf; - struct cam_isp_tfe_out_port_info *out_port; - struct cam_tfe_csid_hw_reserve_resource_args csid_acquire; - struct cam_isp_hw_mgr_res *csid_res_iterator; - enum cam_tfe_csid_path_res_id path_res_id; + struct cam_tfe_hw_mgr *tfe_hw_mgr; + struct cam_isp_hw_mgr_res *csid_res; + struct cam_hw_intf *hw_intf; + struct cam_isp_tfe_out_port_generic_info *out_port; + struct cam_tfe_csid_hw_reserve_resource_args csid_acquire; + struct cam_isp_hw_mgr_res *csid_res_iterator; + enum cam_tfe_csid_path_res_id path_res_id; tfe_hw_mgr = tfe_ctx->hw_mgr; @@ -1639,8 +1639,8 @@ end: } static int cam_tfe_hw_mgr_preprocess_port( - struct cam_tfe_hw_mgr_ctx *tfe_ctx, - struct cam_isp_tfe_in_port_info *in_port, + struct cam_tfe_hw_mgr_ctx *tfe_ctx, + struct cam_isp_tfe_in_port_generic_info *in_port, int *ipp_count, int *rdi_count, int *pdaf_enable) @@ -1649,9 +1649,9 @@ static int cam_tfe_hw_mgr_preprocess_port( int rdi_num = 0; bool rdi2_enable = false; uint32_t i; - struct cam_isp_tfe_out_port_info *out_port; - struct cam_tfe_hw_mgr *tfe_hw_mgr; - struct cam_hw_intf *tfe_device; + struct cam_isp_tfe_out_port_generic_info *out_port; + struct cam_tfe_hw_mgr *tfe_hw_mgr; + struct cam_hw_intf *tfe_device; bool pdaf_rdi2_mux_en = false; tfe_hw_mgr = tfe_ctx->hw_mgr; @@ -1693,8 +1693,8 @@ static int cam_tfe_hw_mgr_preprocess_port( } static int cam_tfe_mgr_acquire_hw_for_ctx( - struct cam_tfe_hw_mgr_ctx *tfe_ctx, - struct cam_isp_tfe_in_port_info *in_port, + struct cam_tfe_hw_mgr_ctx *tfe_ctx, + struct cam_isp_tfe_in_port_generic_info *in_port, uint32_t *num_pix_port, uint32_t *num_rdi_port, uint32_t *pdaf_enable) { @@ -1834,6 +1834,226 @@ void cam_tfe_cam_cdm_callback(uint32_t handle, void *userdata, } } +static int cam_tfe_mgr_acquire_get_unified_structure_v1( + struct cam_isp_tfe_acquire_hw_info *acquire_hw_info, + uint32_t offset, uint32_t *input_size, + struct cam_isp_tfe_in_port_generic_info *in_port) +{ + struct cam_isp_tfe_in_port_info *in = NULL; + uint32_t in_port_length = 0; + int32_t rc = 0, i; + + in = (struct cam_isp_tfe_in_port_info *) + ((uint8_t *)&acquire_hw_info->data + + acquire_hw_info->input_info_offset + *input_size); + + in_port_length = sizeof(struct cam_isp_tfe_in_port_info) + + (in->num_out_res - 1) * + sizeof(struct cam_isp_tfe_out_port_info); + + *input_size += in_port_length; + + if (!in_port || ((*input_size) > acquire_hw_info->input_info_size)) { + CAM_ERR(CAM_ISP, "Input is not proper"); + rc = -EINVAL; + goto err; + } + + in_port->major_ver = + (acquire_hw_info->input_info_version >> 16) & 0xFFFF; + in_port->minor_ver = + acquire_hw_info->input_info_version & 0xFFFF; + in_port->res_id = in->res_id; + in_port->lane_type = in->lane_type; + in_port->lane_num = in->lane_num; + in_port->lane_cfg = in->lane_cfg; + in_port->vc[0] = in->vc; + in_port->dt[0] = in->dt; + in_port->num_valid_vc_dt = 1; + in_port->format = in->format; + in_port->pix_pattern = in->pix_pattern; + in_port->usage_type = in->usage_type; + in_port->left_start = in->left_start; + in_port->left_end = in->left_end; + in_port->left_width = in->left_width; + in_port->right_start = in->right_start; + in_port->right_end = in->right_end; + in_port->right_width = in->right_width; + in_port->line_start = in->line_start; + in_port->line_end = in->line_end; + in_port->height = in->height; + in_port->batch_size = in->batch_size; + in_port->dsp_mode = in->dsp_mode; + in_port->sensor_width = in->sensor_width; + in_port->sensor_height = in->sensor_height; + in_port->sensor_hbi = in->sensor_hbi; + in_port->sensor_vbi = in->sensor_vbi; + in_port->sensor_fps = in->sensor_fps; + in_port->init_frame_drop = in->init_frame_drop; + in_port->num_out_res = in->num_out_res; + + in_port->data = kcalloc(in->num_out_res, + sizeof(struct cam_isp_tfe_out_port_generic_info), + GFP_KERNEL); + + if (in_port->data == NULL) { + rc = -ENOMEM; + goto err; + } + + for (i = 0; i < in->num_out_res; i++) { + in_port->data[i].res_id = in->data[i].res_id; + in_port->data[i].format = in->data[i].format; + in_port->data[i].width = in->data[i].width; + in_port->data[i].height = in->data[i].height; + in_port->data[i].stride = in->data[i].stride; + in_port->data[i].comp_grp_id = in->data[i].comp_grp_id; + in_port->data[i].secure_mode = in->data[i].secure_mode; + in_port->data[i].wm_mode = in->data[i].wm_mode; + in_port->data[i].reserved = in->data[i].reserved; + } + + return 0; +err: + return rc; +} + +static int cam_tfe_mgr_acquire_get_unified_structure_v2( + struct cam_isp_tfe_acquire_hw_info *acquire_hw_info, + uint32_t offset, uint32_t *input_size, + struct cam_isp_tfe_in_port_generic_info *in_port) +{ + struct cam_isp_tfe_in_port_info_v2 *in = NULL; + uint32_t in_port_length = 0; + int32_t rc = 0, i; + + in = (struct cam_isp_tfe_in_port_info_v2 *) + ((uint8_t *)&acquire_hw_info->data + + acquire_hw_info->input_info_offset + *input_size); + + in_port_length = sizeof(struct cam_isp_tfe_in_port_info_v2) + + (in->num_out_res - 1) * + sizeof(struct cam_isp_tfe_out_port_info); + + *input_size += in_port_length; + + if (!in_port || ((*input_size) > acquire_hw_info->input_info_size)) { + CAM_ERR(CAM_ISP, "Input is not proper"); + rc = -EINVAL; + goto err; + } + + in_port->major_ver = + (acquire_hw_info->input_info_version >> 16) & 0xFFFF; + in_port->minor_ver = + acquire_hw_info->input_info_version & 0xFFFF; + in_port->res_id = in->res_id; + in_port->lane_type = in->lane_type; + in_port->lane_num = in->lane_num; + in_port->lane_cfg = in->lane_cfg; + in_port->num_valid_vc_dt = in->num_valid_vc_dt; + + if (in_port->num_valid_vc_dt == 0 || + in_port->num_valid_vc_dt >= CAM_ISP_TFE_VC_DT_CFG) { + CAM_ERR(CAM_ISP, "Invalid i/p arg invalid vc-dt: %d", + in->num_valid_vc_dt); + rc = -EINVAL; + goto err; + } + + for (i = 0; i < in_port->num_valid_vc_dt; i++) { + in_port->vc[i] = in->vc[i]; + in_port->dt[i] = in->dt[i]; + } + + in_port->format = in->format; + in_port->pix_pattern = in->pix_pattern; + in_port->usage_type = in->usage_type; + in_port->left_start = in->left_start; + in_port->left_end = in->left_end; + in_port->left_width = in->left_width; + in_port->right_start = in->right_start; + in_port->right_end = in->right_end; + in_port->right_width = in->right_width; + in_port->line_start = in->line_start; + in_port->line_end = in->line_end; + in_port->height = in->height; + in_port->batch_size = in->batch_size; + in_port->dsp_mode = in->dsp_mode; + in_port->sensor_width = in->sensor_width; + in_port->sensor_height = in->sensor_height; + in_port->sensor_hbi = in->sensor_hbi; + in_port->sensor_vbi = in->sensor_vbi; + in_port->sensor_fps = in->sensor_fps; + in_port->init_frame_drop = in->init_frame_drop; + in_port->bayer_bin = in->feature_flag & + CAM_ISP_TFE_FLAG_BAYER_BIN; + in_port->qcfa_bin = in->feature_flag & + CAM_ISP_TFE_FLAG_QCFA_BIN; + + if (in_port->bayer_bin && in_port->qcfa_bin) { + CAM_ERR(CAM_ISP, + "Bayer and QCFA binning not supported together!"); + rc = -EINVAL; + goto err; + } + + in_port->core_cfg = in->core_cfg; + in_port->num_out_res = in->num_out_res; + + in_port->data = kcalloc(in->num_out_res, + sizeof(struct cam_isp_tfe_out_port_generic_info), + GFP_KERNEL); + + if (in_port->data == NULL) { + rc = -ENOMEM; + goto err; + } + + for (i = 0; i < in->num_out_res; i++) { + in_port->data[i].res_id = in->data[i].res_id; + in_port->data[i].format = in->data[i].format; + in_port->data[i].width = in->data[i].width; + in_port->data[i].height = in->data[i].height; + in_port->data[i].stride = in->data[i].stride; + in_port->data[i].comp_grp_id = in->data[i].comp_grp_id; + in_port->data[i].secure_mode = in->data[i].secure_mode; + in_port->data[i].wm_mode = in->data[i].wm_mode; + in_port->data[i].reserved = in->data[i].reserved; + } + + return 0; +err: + return rc; +} +static int cam_tfe_mgr_acquire_get_unified_structure( + struct cam_isp_tfe_acquire_hw_info *acquire_hw_info, + uint32_t offset, uint32_t *input_size, + struct cam_isp_tfe_in_port_generic_info *in_port) +{ + uint32_t major_ver = 0, minor_ver = 0; + + if (acquire_hw_info == NULL || input_size == NULL) + return -EINVAL; + + major_ver = (acquire_hw_info->common_info_version >> 12) & 0xF; + minor_ver = (acquire_hw_info->common_info_version) & 0xFFF; + + switch (major_ver) { + case 1: + return cam_tfe_mgr_acquire_get_unified_structure_v1( + acquire_hw_info, offset, input_size, in_port); + case 2: + return cam_tfe_mgr_acquire_get_unified_structure_v2( + acquire_hw_info, offset, input_size, in_port); + default: + CAM_ERR(CAM_ISP, "Invalid ver of i/p port info from user"); + return -EINVAL; + } + + return 0; +} + /* entry function: acquire_hw */ static int cam_tfe_mgr_acquire_hw(void *hw_mgr_priv, void *acquire_hw_args) { @@ -1842,18 +2062,15 @@ static int cam_tfe_mgr_acquire_hw(void *hw_mgr_priv, void *acquire_hw_args) int rc = -EINVAL; int i, j; struct cam_tfe_hw_mgr_ctx *tfe_ctx; - struct cam_isp_tfe_in_port_info *in_port = NULL; + struct cam_isp_tfe_in_port_generic_info *in_port = NULL; struct cam_cdm_acquire_data cdm_acquire; uint32_t num_pix_port_per_in = 0; uint32_t num_rdi_port_per_in = 0; uint32_t pdaf_enable = 0; uint32_t total_pix_port = 0; uint32_t total_rdi_port = 0; - uint32_t in_port_length = 0; - uint32_t total_in_port_length = 0; struct cam_isp_tfe_acquire_hw_info *acquire_hw_info = NULL; - struct cam_isp_tfe_in_port_info - *tpg_inport[CAM_TOP_TPG_MAX_SUPPORTED_DT] = {0, 0, 0, 0}; + uint32_t input_size = 0; CAM_DBG(CAM_ISP, "Enter..."); @@ -1905,42 +2122,34 @@ static int cam_tfe_mgr_acquire_hw(void *hw_mgr_priv, void *acquire_hw_args) acquire_hw_info = (struct cam_isp_tfe_acquire_hw_info *) acquire_args->acquire_info; - in_port = (struct cam_isp_tfe_in_port_info *) - ((uint8_t *)&acquire_hw_info->data + - acquire_hw_info->input_info_offset); + in_port = kcalloc(acquire_hw_info->num_inputs, + sizeof(struct cam_isp_tfe_in_port_generic_info), + GFP_KERNEL); + + if (!in_port) { + CAM_ERR(CAM_ISP, "No memory available"); + rc = -ENOMEM; + goto free_cdm; + } + + /* Update in_port structure */ + for (i = 0; i < acquire_hw_info->num_inputs; i++) { + rc = cam_tfe_mgr_acquire_get_unified_structure(acquire_hw_info, + i, &input_size, &in_port[i]); + + if (rc < 0) { + CAM_ERR(CAM_ISP, "Failed in parsing: %d", rc); + goto free_cdm; + } + } /* Check any inport has dual tfe usage */ tfe_ctx->is_dual = false; - for (i = 0; i < acquire_hw_info->num_inputs; i++) { - if (in_port->usage_type) + for (i = 0; i < acquire_hw_info->num_inputs; i++) + if (in_port[i].usage_type) tfe_ctx->is_dual = true; - in_port_length = - sizeof(struct cam_isp_tfe_in_port_info) + - (in_port->num_out_res - 1) * - sizeof(struct cam_isp_tfe_out_port_info); - total_in_port_length += in_port_length; - if (total_in_port_length > - acquire_hw_info->input_info_size) { - CAM_ERR(CAM_ISP, - "buffer size is not enough %d %d", - total_in_port_length, - acquire_hw_info->input_info_size); - rc = -EINVAL; - goto free_cdm; - } - - in_port = (struct cam_isp_tfe_in_port_info *) - ((uint8_t *)in_port + in_port_length); - } - - in_port_length = 0; - total_in_port_length = 0; - in_port = (struct cam_isp_tfe_in_port_info *) - ((uint8_t *)&acquire_hw_info->data + - acquire_hw_info->input_info_offset); - - if (in_port->res_id == CAM_ISP_TFE_IN_RES_TPG) { + if (in_port[0].res_id == CAM_ISP_TFE_IN_RES_TPG) { if (acquire_hw_info->num_inputs > CAM_TOP_TPG_MAX_SUPPORTED_DT) { CAM_ERR(CAM_ISP, "too many number inport:%d for TPG ", @@ -1949,35 +2158,17 @@ static int cam_tfe_mgr_acquire_hw(void *hw_mgr_priv, void *acquire_hw_args) goto free_cdm; } - for (i = 0; i < acquire_hw_info->num_inputs; i++) { - if (in_port->res_id != CAM_ISP_TFE_IN_RES_TPG) { + for (i = 1; i < acquire_hw_info->num_inputs; i++) { + if (in_port[i].res_id != CAM_ISP_TFE_IN_RES_TPG) { CAM_ERR(CAM_ISP, "Inval :%d inport res id:0x%x", - i, in_port->res_id); + i, in_port[i].res_id); rc = -EINVAL; goto free_cdm; } - tpg_inport[i] = in_port; - in_port_length = - sizeof(struct cam_isp_tfe_in_port_info) + - (in_port->num_out_res - 1) * - sizeof(struct cam_isp_tfe_out_port_info); - total_in_port_length += in_port_length; - if (total_in_port_length > - acquire_hw_info->input_info_size) { - CAM_ERR(CAM_ISP, - "buffer size is not enough %d %d", - total_in_port_length, - acquire_hw_info->input_info_size); - rc = -EINVAL; - goto free_cdm; - } - - in_port = (struct cam_isp_tfe_in_port_info *) - ((uint8_t *)in_port + in_port_length); } - rc = cam_tfe_hw_mgr_acquire_tpg(tfe_ctx, tpg_inport, + rc = cam_tfe_hw_mgr_acquire_tpg(tfe_ctx, in_port, acquire_hw_info->num_inputs); if (rc) goto free_cdm; @@ -1985,34 +2176,18 @@ static int cam_tfe_mgr_acquire_hw(void *hw_mgr_priv, void *acquire_hw_args) tfe_ctx->is_tpg = true; } - in_port = (struct cam_isp_tfe_in_port_info *) - ((uint8_t *)&acquire_hw_info->data + - acquire_hw_info->input_info_offset); - in_port_length = 0; - total_in_port_length = 0; - /* acquire HW resources */ for (i = 0; i < acquire_hw_info->num_inputs; i++) { - if (in_port->num_out_res > CAM_TFE_HW_OUT_RES_MAX) { + if (in_port[i].num_out_res > CAM_TFE_HW_OUT_RES_MAX) { CAM_ERR(CAM_ISP, "too many output res %d", - in_port->num_out_res); + in_port[i].num_out_res); rc = -EINVAL; - goto free_res; + goto free_cdm; } - in_port_length = sizeof(struct cam_isp_tfe_in_port_info) + - (in_port->num_out_res - 1) * - sizeof(struct cam_isp_tfe_out_port_info); - total_in_port_length += in_port_length; - - if (total_in_port_length > acquire_hw_info->input_info_size) { - CAM_ERR(CAM_ISP, "buffer size is not enough"); - rc = -EINVAL; - goto free_res; - } - CAM_DBG(CAM_ISP, "in_res_id %x", in_port->res_id); - rc = cam_tfe_mgr_acquire_hw_for_ctx(tfe_ctx, in_port, + CAM_DBG(CAM_ISP, "in_res_id %x", in_port[i].res_id); + rc = cam_tfe_mgr_acquire_hw_for_ctx(tfe_ctx, &in_port[i], &num_pix_port_per_in, &num_rdi_port_per_in, &pdaf_enable); total_pix_port += num_pix_port_per_in; @@ -2022,8 +2197,6 @@ static int cam_tfe_mgr_acquire_hw(void *hw_mgr_priv, void *acquire_hw_args) CAM_ERR(CAM_ISP, "can not acquire resource"); goto free_res; } - in_port = (struct cam_isp_tfe_in_port_info *) - ((uint8_t *)in_port + in_port_length); } /* Check whether context has only RDI resource */ @@ -2044,6 +2217,16 @@ static int cam_tfe_mgr_acquire_hw(void *hw_mgr_priv, void *acquire_hw_args) tfe_ctx->ctx_in_use = 1; tfe_ctx->num_reg_dump_buf = 0; + if (in_port) { + for (i = 0; i < acquire_hw_info->num_inputs; i++) { + kfree(in_port[i].data); + in_port[i].data = NULL; + } + + kfree(in_port); + in_port = NULL; + } + if (g_tfe_hw_mgr.support_consumed_addr) acquire_args->op_flags |= CAM_IFE_CTX_CONSUME_ADDR_EN; @@ -2067,6 +2250,15 @@ free_cdm: cam_cdm_release(tfe_ctx->cdm_handle); free_ctx: cam_tfe_hw_mgr_put_ctx(&tfe_hw_mgr->free_ctx_list, &tfe_ctx); + if (in_port) { + for (i = 0; i < acquire_hw_info->num_inputs; i++) { + kfree(in_port[i].data); + in_port[i].data = NULL; + } + + kfree(in_port); + in_port = NULL; + } err: /* Dump all the current acquired HW */ cam_tfe_hw_mgr_dump_all_ctx(); @@ -2075,6 +2267,67 @@ err: return rc; } +int cam_tfe_mgr_acquire_get_unified_dev_str( + struct cam_isp_tfe_in_port_info *in, + struct cam_isp_tfe_in_port_generic_info *in_port) +{ + int i, rc = 0; + + in_port->res_id = in->res_id; + in_port->lane_type = in->lane_type; + in_port->lane_num = in->lane_num; + in_port->lane_cfg = in->lane_cfg; + in_port->vc[0] = in->vc; + in_port->dt[0] = in->dt; + in_port->num_valid_vc_dt = 1; + in_port->format = in->format; + in_port->pix_pattern = in->pix_pattern; + in_port->usage_type = in->usage_type; + in_port->left_start = in->left_start; + in_port->left_end = in->left_end; + in_port->left_width = in->left_width; + in_port->right_start = in->right_start; + in_port->right_end = in->right_end; + in_port->right_width = in->right_width; + in_port->line_start = in->line_start; + in_port->line_end = in->line_end; + in_port->height = in->height; + in_port->batch_size = in->batch_size; + in_port->dsp_mode = in->dsp_mode; + in_port->sensor_width = in->sensor_width; + in_port->sensor_height = in->sensor_height; + in_port->sensor_hbi = in->sensor_hbi; + in_port->sensor_vbi = in->sensor_vbi; + in_port->sensor_fps = in->sensor_fps; + in_port->init_frame_drop = in->init_frame_drop; + in_port->num_out_res = in->num_out_res; + + in_port->data = kcalloc(in->num_out_res, + sizeof(struct cam_isp_tfe_out_port_generic_info), + GFP_KERNEL); + + if (in_port->data == NULL) { + rc = -ENOMEM; + goto err; + } + + for (i = 0; i < in->num_out_res; i++) { + in_port->data[i].res_id = in->data[i].res_id; + in_port->data[i].format = in->data[i].format; + in_port->data[i].width = in->data[i].width; + in_port->data[i].height = in->data[i].height; + in_port->data[i].stride = in->data[i].stride; + in_port->data[i].comp_grp_id = in->data[i].comp_grp_id; + in_port->data[i].secure_mode = in->data[i].secure_mode; + in_port->data[i].wm_mode = in->data[i].wm_mode; + in_port->data[i].reserved = in->data[i].reserved; + } + + return 0; +err: + return rc; +} + /* entry function: acquire_hw */ static int cam_tfe_mgr_acquire_dev(void *hw_mgr_priv, void *acquire_hw_args) { @@ -2084,6 +2337,7 @@ static int cam_tfe_mgr_acquire_dev(void *hw_mgr_priv, void *acquire_hw_args) int i, j; struct cam_tfe_hw_mgr_ctx *tfe_ctx; struct cam_isp_tfe_in_port_info *in_port = NULL; + struct cam_isp_tfe_in_port_generic_info *gen_in_port = NULL; struct cam_isp_resource *isp_resource = NULL; struct cam_cdm_acquire_data cdm_acquire; uint32_t num_pix_port_per_in = 0; @@ -2143,6 +2397,16 @@ static int cam_tfe_mgr_acquire_dev(void *hw_mgr_priv, void *acquire_hw_args) isp_resource = (struct cam_isp_resource *)acquire_args->acquire_info; + gen_in_port = kcalloc(acquire_args->num_acq, + sizeof(struct cam_isp_tfe_in_port_generic_info), + GFP_KERNEL); + + if (!gen_in_port) { + CAM_ERR(CAM_ISP, "No memory available"); + rc = -ENOMEM; + goto free_cdm; + } + /* acquire HW resources */ for (i = 0; i < acquire_args->num_acq; i++) { if (isp_resource[i].resource_id != CAM_ISP_RES_ID_PORT) @@ -2186,13 +2450,25 @@ static int cam_tfe_mgr_acquire_dev(void *hw_mgr_priv, void *acquire_hw_args) goto free_res; } - rc = cam_tfe_mgr_acquire_hw_for_ctx(tfe_ctx, in_port, + rc = cam_tfe_mgr_acquire_get_unified_dev_str(in_port, + &gen_in_port[i]); + + if (rc) { + CAM_ERR(CAM_ISP, + "Cannot get in_port structure, rc: %d", + rc); + goto free_res; + } + + rc = cam_tfe_mgr_acquire_hw_for_ctx(tfe_ctx, + &gen_in_port[i], &num_pix_port_per_in, &num_rdi_port_per_in, &pdad_enable); total_pix_port += num_pix_port_per_in; total_rdi_port += num_rdi_port_per_in; kfree(in_port); + in_port = NULL; if (rc) { CAM_ERR(CAM_ISP, "can not acquire resource"); goto free_res; @@ -2220,6 +2496,15 @@ static int cam_tfe_mgr_acquire_dev(void *hw_mgr_priv, void *acquire_hw_args) goto free_res; } + if (gen_in_port) { + for (i = 0; i < acquire_args->num_acq; i++) { + kfree(gen_in_port[i].data); + gen_in_port[i].data = NULL; + } + kfree(gen_in_port); + gen_in_port = NULL; + } + acquire_args->ctxt_to_hw_map = tfe_ctx; tfe_ctx->ctx_in_use = 1; @@ -2230,7 +2515,13 @@ static int cam_tfe_mgr_acquire_dev(void *hw_mgr_priv, void *acquire_hw_args) return 0; free_res: cam_tfe_hw_mgr_release_hw_for_ctx(tfe_ctx); +free_cdm: cam_cdm_release(tfe_ctx->cdm_handle); + if (gen_in_port) { + for (i = 0; i < acquire_args->num_acq; i++) + kfree(gen_in_port[i].data); + kfree(gen_in_port); + } free_ctx: cam_tfe_hw_mgr_put_ctx(&tfe_hw_mgr->free_ctx_list, &tfe_ctx); err: 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 1f274be9eb..8b100d3db4 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 @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* - * Copyright (c) 2019-2020, The Linux Foundation. All rights reserved. + * Copyright (c) 2019-2021, The Linux Foundation. All rights reserved. */ #ifndef _CAM_TFE_CSID_HW_INTF_H_ @@ -8,6 +8,7 @@ #include "cam_isp_hw.h" #include "cam_hw_intf.h" +#include "cam_tfe.h" /* MAX TFE CSID instance */ #define CAM_TFE_CSID_HW_NUM_MAX 3 @@ -37,6 +38,58 @@ enum cam_tfe_csid_irq_reg { TFE_CSID_IRQ_REG_MAX, }; +struct cam_isp_tfe_out_port_generic_info { + uint32_t res_id; + uint32_t format; + uint32_t width; + uint32_t height; + uint32_t stride; + uint32_t comp_grp_id; + uint32_t secure_mode; + uint32_t wm_mode; + uint32_t reserved; +}; + +struct cam_isp_tfe_in_port_generic_info { + uint32_t major_ver; + uint32_t minor_ver; + uint32_t res_id; + uint32_t lane_type; + uint32_t lane_num; + uint32_t lane_cfg; + uint32_t vc[CAM_ISP_TFE_VC_DT_CFG]; + uint32_t dt[CAM_ISP_TFE_VC_DT_CFG]; + uint32_t num_valid_vc_dt; + uint32_t format; + uint32_t pix_pattern; + uint32_t usage_type; + uint32_t left_start; + uint32_t left_end; + uint32_t left_width; + uint32_t right_start; + uint32_t right_end; + uint32_t right_width; + uint32_t line_start; + uint32_t line_end; + uint32_t height; + uint32_t batch_size; + uint32_t dsp_mode; + uint32_t sensor_width; + uint32_t sensor_height; + uint32_t sensor_hbi; + uint32_t sensor_vbi; + uint32_t sensor_fps; + uint32_t init_frame_drop; + uint32_t num_out_res; + uint32_t bayer_bin; + uint32_t qcfa_bin; + uint32_t core_cfg; + uint32_t num_bytes_out; + uint32_t ipp_count; + uint32_t rdi_count; + uint32_t secure_mode; + struct cam_isp_tfe_out_port_generic_info *data; +}; /** * struct cam_tfe_csid_hw_caps- get the CSID hw capability @@ -75,8 +128,8 @@ struct cam_tfe_csid_hw_caps { struct cam_tfe_csid_hw_reserve_resource_args { enum cam_isp_resource_type res_type; uint32_t res_id; - struct cam_isp_tfe_in_port_info *in_port; - struct cam_isp_tfe_out_port_info *out_port; + struct cam_isp_tfe_in_port_generic_info *in_port; + struct cam_isp_tfe_out_port_generic_info *out_port; enum cam_isp_hw_sync_mode sync_mode; uint32_t master_idx; uint32_t phy_sel; diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/include/cam_tfe_hw_intf.h b/drivers/cam_isp/isp_hw_mgr/isp_hw/include/cam_tfe_hw_intf.h index 4b9dce38ca..ebb69e64f2 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/include/cam_tfe_hw_intf.h +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/include/cam_tfe_hw_intf.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* - * Copyright (c) 2019-2020, The Linux Foundation. All rights reserved. + * Copyright (c) 2019-2021, The Linux Foundation. All rights reserved. */ #ifndef _CAM_TFE_HW_INTF_H_ @@ -94,14 +94,14 @@ struct cam_tfe_hw_get_hw_cap { * @ctx: Context data */ struct cam_tfe_hw_tfe_out_acquire_args { - struct cam_isp_resource_node *rsrc_node; - struct cam_isp_tfe_out_port_info *out_port_info; - uint32_t unique_id; - uint32_t is_dual; - enum cam_isp_hw_split_id split_id; - uint32_t is_master; - struct cam_cdm_utils_ops *cdm_ops; - void *ctx; + struct cam_isp_resource_node *rsrc_node; + struct cam_isp_tfe_out_port_generic_info *out_port_info; + uint32_t unique_id; + uint32_t is_dual; + enum cam_isp_hw_split_id split_id; + uint32_t is_master; + struct cam_cdm_utils_ops *cdm_ops; + void *ctx; }; /* @@ -119,13 +119,13 @@ struct cam_tfe_hw_tfe_out_acquire_args { * @dual_tfe_sync_sel_idx Dual tfe master hardware index */ struct cam_tfe_hw_tfe_in_acquire_args { - struct cam_isp_resource_node *rsrc_node; - struct cam_isp_tfe_in_port_info *in_port; - uint32_t res_id; - void *cdm_ops; - enum cam_isp_hw_sync_mode sync_mode; - bool camif_pd_enable; - uint32_t dual_tfe_sync_sel_idx; + struct cam_isp_resource_node *rsrc_node; + struct cam_isp_tfe_in_port_generic_info *in_port; + uint32_t res_id; + void *cdm_ops; + enum cam_isp_hw_sync_mode sync_mode; + bool camif_pd_enable; + uint32_t dual_tfe_sync_sel_idx; }; /* diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/include/cam_top_tpg_hw_intf.h b/drivers/cam_isp/isp_hw_mgr/isp_hw/include/cam_top_tpg_hw_intf.h index 0b26e470fa..6085a86399 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/include/cam_top_tpg_hw_intf.h +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/include/cam_top_tpg_hw_intf.h @@ -9,6 +9,7 @@ #include "cam_isp_hw.h" #include "cam_hw_intf.h" #include "cam_ife_csid_hw_intf.h" +#include "cam_tfe_csid_hw_intf.h" /* Max top tpg instance */ #define CAM_TOP_TPG_HW_NUM_MAX 3 @@ -52,9 +53,9 @@ struct cam_top_tpg_hw_caps { * */ struct cam_top_tpg_ver1_reserve_args { - uint32_t num_inport; - struct cam_isp_tfe_in_port_info *in_port[CAM_TOP_TPG_MAX_SUPPORTED_DT]; - struct cam_isp_resource_node *node_res; + uint32_t num_inport; + struct cam_isp_tfe_in_port_generic_info *in_port[CAM_TOP_TPG_MAX_SUPPORTED_DT]; + struct cam_isp_resource_node *node_res; }; /** diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_csid_hw/cam_tfe_csid.c b/drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_csid_hw/cam_tfe_csid.c new file mode 100644 index 0000000000..61c9e60acd --- /dev/null +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_csid_hw/cam_tfe_csid.c @@ -0,0 +1,51 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (c) 2021, The Linux Foundation. All rights reserved. + */ + + +#include +#include "cam_tfe_csid_core.h" +#include "cam_tfe_csid530.h" +#include "cam_tfe_csid640.h" +#include "cam_tfe_csid_dev.h" +#include "camera_main.h" + +#define CAM_TFE_CSID_DRV_NAME "tfe_csid" + +static const struct of_device_id cam_tfe_csid_dt_match[] = { + { + .compatible = "qcom,csid530", + .data = &cam_tfe_csid530_hw_info, + }, + { + .compatible = "qcom,csid640", + .data = &cam_tfe_csid640_hw_info, + }, + {} +}; + +MODULE_DEVICE_TABLE(of, cam_tfe_csid_dt_match); + +struct platform_driver cam_tfe_csid_driver = { + .probe = cam_tfe_csid_probe, + .remove = cam_tfe_csid_remove, + .driver = { + .name = CAM_TFE_CSID_DRV_NAME, + .of_match_table = cam_tfe_csid_dt_match, + .suppress_bind_attrs = true, + }, +}; + +int cam_tfe_csid_init_module(void) +{ + return platform_driver_register(&cam_tfe_csid_driver); +} + +void cam_tfe_csid_exit_module(void) +{ + platform_driver_unregister(&cam_tfe_csid_driver); +} + +MODULE_DESCRIPTION("CAM TFE_CSID driver"); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_csid_hw/cam_tfe_csid.h b/drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_csid_hw/cam_tfe_csid.h new file mode 100644 index 0000000000..3edc187662 --- /dev/null +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_csid_hw/cam_tfe_csid.h @@ -0,0 +1,13 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (c) 2021, The Linux Foundation. All rights reserved. + */ + +#ifndef _CAM_TFE_CSID_H_ +#define _CAM_TFE_CSID_H_ + +int cam_tfe_csid_init_module(void); +void cam_tfe_csid_exit_module(void); + +#endif /*_CAM_TFE_CSID_H_ */ + diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_csid_hw/cam_tfe_csid530.c b/drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_csid_hw/cam_tfe_csid530.c deleted file mode 100644 index 420ac8ff93..0000000000 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_csid_hw/cam_tfe_csid530.c +++ /dev/null @@ -1,52 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-only -/* - * Copyright (c) 2019-2020, The Linux Foundation. All rights reserved. - */ - - -#include -#include "cam_tfe_csid_core.h" -#include "cam_tfe_csid530.h" -#include "cam_tfe_csid_dev.h" -#include "camera_main.h" - -#define CAM_TFE_CSID_DRV_NAME "csid_530" -#define CAM_TFE_CSID_VERSION_V530 0x50030000 - -static struct cam_tfe_csid_hw_info cam_tfe_csid530_hw_info = { - .csid_reg = &cam_tfe_csid_530_reg_offset, - .hw_dts_version = CAM_TFE_CSID_VERSION_V530, -}; - -static const struct of_device_id cam_tfe_csid530_dt_match[] = { - { - .compatible = "qcom,csid530", - .data = &cam_tfe_csid530_hw_info, - }, - {} -}; - -MODULE_DEVICE_TABLE(of, cam_tfe_csid530_dt_match); - -struct platform_driver cam_tfe_csid530_driver = { - .probe = cam_tfe_csid_probe, - .remove = cam_tfe_csid_remove, - .driver = { - .name = CAM_TFE_CSID_DRV_NAME, - .of_match_table = cam_tfe_csid530_dt_match, - .suppress_bind_attrs = true, - }, -}; - -int cam_tfe_csid530_init_module(void) -{ - return platform_driver_register(&cam_tfe_csid530_driver); -} - -void cam_tfe_csid530_exit_module(void) -{ - platform_driver_unregister(&cam_tfe_csid530_driver); -} - -MODULE_DESCRIPTION("CAM TFE_CSID530 driver"); -MODULE_LICENSE("GPL v2"); diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_csid_hw/cam_tfe_csid530.h b/drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_csid_hw/cam_tfe_csid530.h index b0e9dc862c..9f4ccc28ab 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_csid_hw/cam_tfe_csid530.h +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_csid_hw/cam_tfe_csid530.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* - * Copyright (c) 2019-2020, The Linux Foundation. All rights reserved. + * Copyright (c) 2019-2021, The Linux Foundation. All rights reserved. */ #ifndef _CAM_TFE_CSID_530_H_ @@ -8,6 +8,8 @@ #include "cam_tfe_csid_core.h" +#define CAM_TFE_CSID_VERSION_V530 0x50030000 + static struct cam_tfe_csid_pxl_reg_offset cam_tfe_csid_530_ipp_reg_offset = { .csid_pxl_irq_status_addr = 0x30, .csid_pxl_irq_mask_addr = 0x34, @@ -40,6 +42,8 @@ static struct cam_tfe_csid_pxl_reg_offset cam_tfe_csid_530_ipp_reg_offset = { .halt_mode_shift = 2, .halt_master_sel_master_val = 3, .halt_master_sel_slave_val = 0, + .binning_supported = 0, + .is_multi_vc_dt_supported = false, }; static struct cam_tfe_csid_rdi_reg_offset cam_tfe_csid_530_rdi_0_reg_offset = { @@ -68,6 +72,8 @@ static struct cam_tfe_csid_rdi_reg_offset cam_tfe_csid_530_rdi_0_reg_offset = { .csid_rdi_err_recovery_cfg2_addr = 0x3b8, .csid_rdi_byte_cntr_ping_addr = 0x3e0, .csid_rdi_byte_cntr_pong_addr = 0x3e4, + /* configurations */ + .is_multi_vc_dt_supported = false, }; static struct cam_tfe_csid_rdi_reg_offset cam_tfe_csid_530_rdi_1_reg_offset = { @@ -96,6 +102,8 @@ static struct cam_tfe_csid_rdi_reg_offset cam_tfe_csid_530_rdi_1_reg_offset = { .csid_rdi_err_recovery_cfg2_addr = 0x4b8, .csid_rdi_byte_cntr_ping_addr = 0x4e0, .csid_rdi_byte_cntr_pong_addr = 0x4e4, + /* configurations */ + .is_multi_vc_dt_supported = false, }; static struct cam_tfe_csid_rdi_reg_offset cam_tfe_csid_530_rdi_2_reg_offset = { @@ -124,6 +132,8 @@ static struct cam_tfe_csid_rdi_reg_offset cam_tfe_csid_530_rdi_2_reg_offset = { .csid_rdi_err_recovery_cfg2_addr = 0x5b8, .csid_rdi_byte_cntr_ping_addr = 0x5e0, .csid_rdi_byte_cntr_pong_addr = 0x5e4, + /* configurations */ + .is_multi_vc_dt_supported = false, }; static struct cam_tfe_csid_csi2_rx_reg_offset @@ -207,6 +217,7 @@ static struct cam_tfe_csid_common_reg_offset .rdi_irq_mask_all = 0x3FFFF, .top_tfe2_pix_pipe_fuse_reg = 0xFE4, .top_tfe2_fuse_reg = 0xFE8, + .format_measure_support = false, }; static struct cam_tfe_csid_reg_offset cam_tfe_csid_530_reg_offset = { @@ -220,7 +231,9 @@ static struct cam_tfe_csid_reg_offset cam_tfe_csid_530_reg_offset = { }, }; -int cam_tfe_csid530_init_module(void); -void cam_tfe_csid530_exit_module(void); +static struct cam_tfe_csid_hw_info cam_tfe_csid530_hw_info = { + .csid_reg = &cam_tfe_csid_530_reg_offset, + .hw_dts_version = CAM_TFE_CSID_VERSION_V530, +}; #endif /*_CAM_TFE_CSID_530_H_ */ diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_csid_hw/cam_tfe_csid640.h b/drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_csid_hw/cam_tfe_csid640.h new file mode 100644 index 0000000000..b8b87bd7f0 --- /dev/null +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_csid_hw/cam_tfe_csid640.h @@ -0,0 +1,283 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (c) 2019-2021, The Linux Foundation. All rights reserved. + */ + +#ifndef _CAM_TFE_CSID_640_H_ +#define _CAM_TFE_CSID_640_H_ + +#include "cam_tfe_csid_core.h" + +#define CAM_TFE_CSID_VERSION_V640 0x60040000 + +static struct cam_tfe_csid_pxl_reg_offset cam_tfe_csid_640_ipp_reg_offset = { + .csid_pxl_irq_status_addr = 0x30, + .csid_pxl_irq_mask_addr = 0x34, + .csid_pxl_irq_clear_addr = 0x38, + .csid_pxl_irq_set_addr = 0x3c, + + .csid_pxl_cfg0_addr = 0x200, + .csid_pxl_cfg1_addr = 0x204, + .csid_pxl_ctrl_addr = 0x208, + .csid_pxl_hcrop_addr = 0x21c, + .csid_pxl_vcrop_addr = 0x220, + .csid_pxl_rst_strobes_addr = 0x240, + .csid_pxl_status_addr = 0x254, + .csid_pxl_misr_val_addr = 0x258, + .csid_pxl_timestamp_curr0_sof_addr = 0x290, + .csid_pxl_timestamp_curr1_sof_addr = 0x294, + .csid_pxl_timestamp_perv0_sof_addr = 0x298, + .csid_pxl_timestamp_perv1_sof_addr = 0x29c, + .csid_pxl_timestamp_curr0_eof_addr = 0x2a0, + .csid_pxl_timestamp_curr1_eof_addr = 0x2a4, + .csid_pxl_timestamp_perv0_eof_addr = 0x2a8, + .csid_pxl_timestamp_perv1_eof_addr = 0x2ac, + .csid_pxl_err_recovery_cfg0_addr = 0x2d0, + .csid_pxl_err_recovery_cfg1_addr = 0x2d4, + .csid_pxl_err_recovery_cfg2_addr = 0x2d8, + .csid_pxl_multi_vcdt_cfg0_addr = 0x2dc, + .csid_pxl_format_measure_cfg0_addr = 0x270, + .csid_pxl_format_measure_cfg1_addr = 0x274, + .csid_pxl_format_measure0_addr = 0x278, + .csid_pxl_format_measure1_addr = 0x27c, + .csid_pxl_format_measure2_addr = 0x280, + + /* configurations */ + .pix_store_en_shift_val = 7, + .early_eof_en_shift_val = 29, + .halt_master_sel_shift = 4, + .halt_mode_shift = 2, + .halt_master_sel_master_val = 3, + .halt_master_sel_slave_val = 0, + .binning_supported = 3, + .bin_qcfa_en_shift_val = 30, + .bin_en_shift_val = 2, + .is_multi_vc_dt_supported = true, + .format_measure_en_shift_val = 0, + .measure_en_hbi_vbi_cnt_val = 0xc, +}; + +static struct cam_tfe_csid_rdi_reg_offset cam_tfe_csid_640_rdi_0_reg_offset = { + .csid_rdi_irq_status_addr = 0x40, + .csid_rdi_irq_mask_addr = 0x44, + .csid_rdi_irq_clear_addr = 0x48, + .csid_rdi_irq_set_addr = 0x4c, + + .csid_rdi_cfg0_addr = 0x300, + .csid_rdi_cfg1_addr = 0x304, + .csid_rdi_ctrl_addr = 0x308, + .csid_rdi_rst_strobes_addr = 0x340, + .csid_rdi_status_addr = 0x350, + .csid_rdi_misr_val0_addr = 0x354, + .csid_rdi_misr_val1_addr = 0x358, + .csid_rdi_timestamp_curr0_sof_addr = 0x390, + .csid_rdi_timestamp_curr1_sof_addr = 0x394, + .csid_rdi_timestamp_prev0_sof_addr = 0x398, + .csid_rdi_timestamp_prev1_sof_addr = 0x39c, + .csid_rdi_timestamp_curr0_eof_addr = 0x3a0, + .csid_rdi_timestamp_curr1_eof_addr = 0x3a4, + .csid_rdi_timestamp_prev0_eof_addr = 0x3a8, + .csid_rdi_timestamp_prev1_eof_addr = 0x3ac, + .csid_rdi_err_recovery_cfg0_addr = 0x3b0, + .csid_rdi_err_recovery_cfg1_addr = 0x3b4, + .csid_rdi_err_recovery_cfg2_addr = 0x3b8, + .csid_rdi_byte_cntr_ping_addr = 0x3e0, + .csid_rdi_byte_cntr_pong_addr = 0x3e4, + .csid_rdi_multi_vcdt_cfg0_addr = 0x3bc, + .csid_rdi_format_measure_cfg0_addr = 0x370, + .csid_rdi_format_measure_cfg1_addr = 0x374, + .csid_rdi_format_measure0_addr = 0x378, + .csid_rdi_format_measure1_addr = 0x37c, + .csid_rdi_format_measure2_addr = 0x380, + + /* configurations */ + .is_multi_vc_dt_supported = true, + .format_measure_en_shift_val = 0, + .measure_en_hbi_vbi_cnt_val = 0xc, +}; + +static struct cam_tfe_csid_rdi_reg_offset cam_tfe_csid_640_rdi_1_reg_offset = { + .csid_rdi_irq_status_addr = 0x50, + .csid_rdi_irq_mask_addr = 0x54, + .csid_rdi_irq_clear_addr = 0x58, + .csid_rdi_irq_set_addr = 0x5c, + + .csid_rdi_cfg0_addr = 0x400, + .csid_rdi_cfg1_addr = 0x404, + .csid_rdi_ctrl_addr = 0x408, + .csid_rdi_rst_strobes_addr = 0x440, + .csid_rdi_status_addr = 0x450, + .csid_rdi_misr_val0_addr = 0x454, + .csid_rdi_misr_val1_addr = 0x458, + .csid_rdi_timestamp_curr0_sof_addr = 0x490, + .csid_rdi_timestamp_curr1_sof_addr = 0x494, + .csid_rdi_timestamp_prev0_sof_addr = 0x498, + .csid_rdi_timestamp_prev1_sof_addr = 0x49c, + .csid_rdi_timestamp_curr0_eof_addr = 0x4a0, + .csid_rdi_timestamp_curr1_eof_addr = 0x4a4, + .csid_rdi_timestamp_prev0_eof_addr = 0x4a8, + .csid_rdi_timestamp_prev1_eof_addr = 0x4ac, + .csid_rdi_err_recovery_cfg0_addr = 0x4b0, + .csid_rdi_err_recovery_cfg1_addr = 0x4b4, + .csid_rdi_err_recovery_cfg2_addr = 0x4b8, + .csid_rdi_byte_cntr_ping_addr = 0x4e0, + .csid_rdi_byte_cntr_pong_addr = 0x4e4, + .csid_rdi_multi_vcdt_cfg0_addr = 0x4bc, + .csid_rdi_format_measure_cfg0_addr = 0x470, + .csid_rdi_format_measure_cfg1_addr = 0x474, + .csid_rdi_format_measure0_addr = 0x478, + .csid_rdi_format_measure1_addr = 0x47c, + .csid_rdi_format_measure2_addr = 0x480, + + /* configurations */ + .is_multi_vc_dt_supported = true, + .format_measure_en_shift_val = 0, + .measure_en_hbi_vbi_cnt_val = 0xc, +}; + +static struct cam_tfe_csid_rdi_reg_offset cam_tfe_csid_640_rdi_2_reg_offset = { + .csid_rdi_irq_status_addr = 0x60, + .csid_rdi_irq_mask_addr = 0x64, + .csid_rdi_irq_clear_addr = 0x68, + .csid_rdi_irq_set_addr = 0x6c, + + .csid_rdi_cfg0_addr = 0x500, + .csid_rdi_cfg1_addr = 0x504, + .csid_rdi_ctrl_addr = 0x508, + .csid_rdi_rst_strobes_addr = 0x540, + .csid_rdi_status_addr = 0x550, + .csid_rdi_misr_val0_addr = 0x554, + .csid_rdi_misr_val1_addr = 0x558, + .csid_rdi_timestamp_curr0_sof_addr = 0x590, + .csid_rdi_timestamp_curr1_sof_addr = 0x594, + .csid_rdi_timestamp_prev0_sof_addr = 0x598, + .csid_rdi_timestamp_prev1_sof_addr = 0x59c, + .csid_rdi_timestamp_curr0_eof_addr = 0x5a0, + .csid_rdi_timestamp_curr1_eof_addr = 0x5a4, + .csid_rdi_timestamp_prev0_eof_addr = 0x5a8, + .csid_rdi_timestamp_prev1_eof_addr = 0x5ac, + .csid_rdi_err_recovery_cfg0_addr = 0x5b0, + .csid_rdi_err_recovery_cfg1_addr = 0x5b4, + .csid_rdi_err_recovery_cfg2_addr = 0x5b8, + .csid_rdi_byte_cntr_ping_addr = 0x5e0, + .csid_rdi_byte_cntr_pong_addr = 0x5e4, + .csid_rdi_multi_vcdt_cfg0_addr = 0x5bc, + .csid_rdi_format_measure_cfg0_addr = 0x570, + .csid_rdi_format_measure_cfg1_addr = 0x574, + .csid_rdi_format_measure0_addr = 0x578, + .csid_rdi_format_measure1_addr = 0x57c, + .csid_rdi_format_measure2_addr = 0x580, + + /* configurations */ + .is_multi_vc_dt_supported = true, + .format_measure_en_shift_val = 0, + .measure_en_hbi_vbi_cnt_val = 0xc, +}; + +static struct cam_tfe_csid_csi2_rx_reg_offset + cam_tfe_csid_640_csi2_reg_offset = { + .csid_csi2_rx_irq_status_addr = 0x20, + .csid_csi2_rx_irq_mask_addr = 0x24, + .csid_csi2_rx_irq_clear_addr = 0x28, + .csid_csi2_rx_irq_set_addr = 0x2c, + + /*CSI2 rx control */ + .csid_csi2_rx_cfg0_addr = 0x100, + .csid_csi2_rx_cfg1_addr = 0x104, + .csid_csi2_rx_capture_ctrl_addr = 0x108, + .csid_csi2_rx_rst_strobes_addr = 0x110, + .csid_csi2_rx_cap_unmap_long_pkt_hdr_0_addr = 0x120, + .csid_csi2_rx_cap_unmap_long_pkt_hdr_1_addr = 0x124, + .csid_csi2_rx_captured_short_pkt_0_addr = 0x128, + .csid_csi2_rx_captured_short_pkt_1_addr = 0x12c, + .csid_csi2_rx_captured_long_pkt_0_addr = 0x130, + .csid_csi2_rx_captured_long_pkt_1_addr = 0x134, + .csid_csi2_rx_captured_long_pkt_ftr_addr = 0x138, + .csid_csi2_rx_captured_cphy_pkt_hdr_addr = 0x13c, + .csid_csi2_rx_total_pkts_rcvd_addr = 0x160, + .csid_csi2_rx_stats_ecc_addr = 0x164, + .csid_csi2_rx_total_crc_err_addr = 0x168, + + .csi2_rst_srb_all = 0x3FFF, + .csi2_rst_done_shift_val = 27, + .csi2_irq_mask_all = 0xFFFFFFF, + .csi2_misr_enable_shift_val = 6, + .csi2_capture_long_pkt_en_shift = 0, + .csi2_capture_short_pkt_en_shift = 1, + .csi2_capture_cphy_pkt_en_shift = 2, + .csi2_capture_long_pkt_dt_shift = 4, + .csi2_capture_long_pkt_vc_shift = 10, + .csi2_capture_short_pkt_vc_shift = 12, + .csi2_capture_cphy_pkt_dt_shift = 14, + .csi2_capture_cphy_pkt_vc_shift = 20, + .csi2_rx_phy_num_mask = 0x7, + .csi2_rx_long_pkt_hdr_rst_stb_shift = 0x1, + .csi2_rx_short_pkt_hdr_rst_stb_shift = 0x2, + .csi2_rx_cphy_pkt_hdr_rst_stb_shift = 0x3, +}; + +static struct cam_tfe_csid_common_reg_offset + cam_tfe_csid_640_cmn_reg_offset = { + .csid_hw_version_addr = 0x0, + .csid_cfg0_addr = 0x4, + .csid_ctrl_addr = 0x8, + .csid_rst_strobes_addr = 0x10, + + .csid_test_bus_ctrl_addr = 0x14, + .csid_top_irq_status_addr = 0x70, + .csid_top_irq_mask_addr = 0x74, + .csid_top_irq_clear_addr = 0x78, + .csid_top_irq_set_addr = 0x7c, + .csid_irq_cmd_addr = 0x80, + + /*configurations */ + .major_version = 5, + .minor_version = 3, + .version_incr = 0, + .num_rdis = 3, + .num_pix = 1, + .csid_reg_rst_stb = 1, + .csid_rst_stb = 0x1e, + .csid_rst_stb_sw_all = 0x1f, + .ipp_path_rst_stb_all = 0x17, + .rdi_path_rst_stb_all = 0x97, + .path_rst_done_shift_val = 1, + .path_en_shift_val = 31, + .dt_id_shift_val = 27, + .vc_shift_val = 22, + .dt_shift_val = 16, + .vc1_shift_val = 2, + .dt1_shift_val = 7, + .multi_vc_dt_en_shift_val = 0, + .fmt_shift_val = 12, + .plain_fmt_shit_val = 10, + .crop_v_en_shift_val = 6, + .crop_h_en_shift_val = 5, + .crop_shift = 16, + .ipp_irq_mask_all = 0x3FFFF, + .rdi_irq_mask_all = 0x3FFFF, + .top_tfe2_pix_pipe_fuse_reg = 0xFE4, + .top_tfe2_fuse_reg = 0xFE8, + .format_measure_support = true, + .format_measure_height_shift_val = 16, + .format_measure_height_mask_val = 0xe, + .format_measure_width_mask_val = 0x10, +}; + +static struct cam_tfe_csid_reg_offset cam_tfe_csid_640_reg_offset = { + .cmn_reg = &cam_tfe_csid_640_cmn_reg_offset, + .csi2_reg = &cam_tfe_csid_640_csi2_reg_offset, + .ipp_reg = &cam_tfe_csid_640_ipp_reg_offset, + .rdi_reg = { + &cam_tfe_csid_640_rdi_0_reg_offset, + &cam_tfe_csid_640_rdi_1_reg_offset, + &cam_tfe_csid_640_rdi_2_reg_offset, + }, +}; + +static struct cam_tfe_csid_hw_info cam_tfe_csid640_hw_info = { + .csid_reg = &cam_tfe_csid_640_reg_offset, + .hw_dts_version = CAM_TFE_CSID_VERSION_V640, +}; + +#endif /*_CAM_TFE_CSID_640_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 6e643d4539..822a981705 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 @@ -20,6 +20,7 @@ #include "cam_subdev.h" #include "cam_tasklet_util.h" #include "cam_common_util.h" +#include "cam_tfe_csid_hw_intf.h" /* Timeout value in msec */ #define TFE_CSID_TIMEOUT 1000 @@ -204,16 +205,36 @@ static int cam_tfe_csid_get_format_ipp( return rc; } -static int cam_tfe_csid_cid_get(struct cam_tfe_csid_hw *csid_hw, - int32_t vc, uint32_t dt, uint32_t *cid) +static int cam_tfe_match_vc_dt_pair(int32_t *vc, uint32_t *dt, + uint32_t num_valid_vc_dt, struct cam_tfe_csid_cid_data *cid_data) { - uint32_t i = 0; + int i; + + if (num_valid_vc_dt == 0 || num_valid_vc_dt > CAM_ISP_TFE_VC_DT_CFG) { + CAM_ERR(CAM_ISP, "invalid num_valid_vc_dt: %d", + num_valid_vc_dt); + return -EINVAL; + } + + for (i = 0; i < num_valid_vc_dt; i++) { + if (vc[i] != cid_data->vc_dt[i].vc || + dt[i] != cid_data->vc_dt[i].dt) + return -EINVAL; + } + + return 0; +} + +static int cam_tfe_csid_cid_get(struct cam_tfe_csid_hw *csid_hw, + int32_t *vc, uint32_t *dt, uint32_t num_valid_vc_dt, uint32_t *cid) +{ + uint32_t i = 0, j = 0; /* Return already reserved CID if the VC/DT matches */ for (i = 0; i < CAM_TFE_CSID_CID_MAX; i++) { if (csid_hw->cid_res[i].cnt >= 1) { - if (csid_hw->cid_res[i].vc == vc && - csid_hw->cid_res[i].dt == dt) { + if (!cam_tfe_match_vc_dt_pair(vc, dt, num_valid_vc_dt, + &csid_hw->cid_res[i])) { csid_hw->cid_res[i].cnt++; *cid = i; CAM_DBG(CAM_ISP, "CSID:%d CID %d allocated", @@ -225,9 +246,12 @@ static int cam_tfe_csid_cid_get(struct cam_tfe_csid_hw *csid_hw, for (i = 0; i < CAM_TFE_CSID_CID_MAX; i++) { if (!csid_hw->cid_res[i].cnt) { - csid_hw->cid_res[i].vc = vc; - csid_hw->cid_res[i].dt = dt; - csid_hw->cid_res[i].cnt = 1; + for (j = 0; j < num_valid_vc_dt; j++) { + csid_hw->cid_res[i].vc_dt[j].vc = vc[j]; + csid_hw->cid_res[i].vc_dt[j].dt = dt[j]; + csid_hw->cid_res[i].num_valid_vc_dt++; + csid_hw->cid_res[i].cnt++; + } *cid = i; CAM_DBG(CAM_ISP, "CSID:%d CID %d allocated", csid_hw->hw_intf->hw_idx, i); @@ -240,8 +264,10 @@ static int cam_tfe_csid_cid_get(struct cam_tfe_csid_hw *csid_hw, /* Dump CID values */ for (i = 0; i < CAM_TFE_CSID_CID_MAX; i++) { CAM_ERR_RATE_LIMIT(CAM_ISP, "CSID:%d CID:%d vc:%d dt:%d cnt:%d", - csid_hw->hw_intf->hw_idx, i, csid_hw->cid_res[i].vc, - csid_hw->cid_res[i].dt, csid_hw->cid_res[i].cnt); + csid_hw->hw_intf->hw_idx, i, + csid_hw->cid_res[i].vc_dt[0].vc, + csid_hw->cid_res[i].vc_dt[0].dt, + csid_hw->cid_res[i].cnt); } return -EINVAL; } @@ -450,7 +476,7 @@ static int cam_tfe_csid_cid_reserve(struct cam_tfe_csid_hw *csid_hw, struct cam_tfe_csid_hw_reserve_resource_args *cid_reserv, uint32_t *cid_value) { - int rc = 0; + int i, rc = 0; CAM_DBG(CAM_ISP, "CSID:%d res_id:0x%x Lane type:%d lane_num:%d dt:%d vc:%d", @@ -458,8 +484,8 @@ static int cam_tfe_csid_cid_reserve(struct cam_tfe_csid_hw *csid_hw, cid_reserv->in_port->res_id, cid_reserv->in_port->lane_type, cid_reserv->in_port->lane_num, - cid_reserv->in_port->dt, - cid_reserv->in_port->vc); + cid_reserv->in_port->dt[0], + cid_reserv->in_port->vc[0]); if (cid_reserv->in_port->res_id >= CAM_ISP_TFE_IN_RES_MAX) { CAM_ERR(CAM_ISP, "CSID:%d Invalid phy sel %d", @@ -497,13 +523,16 @@ static int cam_tfe_csid_cid_reserve(struct cam_tfe_csid_hw *csid_hw, } /* CSID CSI2 v1.1 supports 4 vc */ - if (cid_reserv->in_port->dt > 0x3f || - cid_reserv->in_port->vc > 0x3) { - CAM_ERR(CAM_ISP, "CSID:%d Invalid vc:%d dt %d", - csid_hw->hw_intf->hw_idx, - cid_reserv->in_port->vc, cid_reserv->in_port->dt); - rc = -EINVAL; - goto end; + for (i = 0; i < cid_reserv->in_port->num_valid_vc_dt; i++) { + if (cid_reserv->in_port->dt[i] > 0x3f || + cid_reserv->in_port->vc[i] > 0x3) { + CAM_ERR(CAM_ISP, "CSID:%d Invalid vc:%d dt %d", + csid_hw->hw_intf->hw_idx, + cid_reserv->in_port->vc[i], + cid_reserv->in_port->dt[i]); + rc = -EINVAL; + goto end; + } } if (csid_hw->csi2_reserve_cnt == UINT_MAX) { @@ -537,6 +566,7 @@ static int cam_tfe_csid_cid_reserve(struct cam_tfe_csid_hw *csid_hw, rc = cam_tfe_csid_cid_get(csid_hw, cid_reserv->in_port->vc, cid_reserv->in_port->dt, + cid_reserv->in_port->num_valid_vc_dt, cid_value); if (rc) { CAM_ERR(CAM_ISP, "CSID:%d CID Reserve failed res_id %d", @@ -575,20 +605,24 @@ end: static int cam_tfe_csid_path_reserve(struct cam_tfe_csid_hw *csid_hw, struct cam_tfe_csid_hw_reserve_resource_args *reserve) { - int rc = 0; + int i, rc = 0; struct cam_tfe_csid_path_cfg *path_data; struct cam_isp_resource_node *res; uint32_t cid_value; /* CSID CSI2 v2.0 supports 4 vc */ - if (reserve->in_port->dt > 0x3f || reserve->in_port->vc > 0x3 || - (reserve->sync_mode >= CAM_ISP_HW_SYNC_MAX)) { - CAM_ERR(CAM_ISP, "CSID:%d Invalid vc:%d dt %d mode:%d", - csid_hw->hw_intf->hw_idx, - reserve->in_port->vc, reserve->in_port->dt, - reserve->sync_mode); - rc = -EINVAL; - goto end; + for (i = 0; i < reserve->in_port->num_valid_vc_dt; i++) { + if (reserve->in_port->dt[i] > 0x3f || + reserve->in_port->vc[i] > 0x3 || + (reserve->sync_mode >= CAM_ISP_HW_SYNC_MAX)) { + CAM_ERR(CAM_ISP, "CSID:%d Invalid vc:%d dt %d mode:%d", + csid_hw->hw_intf->hw_idx, + reserve->in_port->vc[i], + reserve->in_port->dt[i], + reserve->sync_mode); + rc = -EINVAL; + goto end; + } } switch (reserve->res_id) { @@ -679,6 +713,9 @@ static int cam_tfe_csid_path_reserve(struct cam_tfe_csid_hw *csid_hw, path_data->start_line = reserve->in_port->line_start; path_data->end_line = reserve->in_port->line_end; + path_data->bayer_bin = reserve->in_port->bayer_bin; + path_data->qcfa_bin = reserve->in_port->qcfa_bin; + csid_hw->event_cb = reserve->event_cb; csid_hw->event_cb_priv = reserve->event_cb_prv; @@ -692,8 +729,13 @@ static int cam_tfe_csid_path_reserve(struct cam_tfe_csid_hw *csid_hw, reserve->in_port->line_start, reserve->in_port->line_end, path_data->crop_enable); - path_data->dt = reserve->in_port->dt; - path_data->vc = reserve->in_port->vc; + path_data->num_valid_vc_dt = 0; + + for (i = 0; i < reserve->in_port->num_valid_vc_dt; i++) { + path_data->vc_dt[i].vc = reserve->in_port->vc[i]; + path_data->vc_dt[i].dt = reserve->in_port->dt[i]; + path_data->num_valid_vc_dt++; + } if (reserve->sync_mode == CAM_ISP_HW_SYNC_MASTER) { path_data->start_pixel = reserve->in_port->left_start; @@ -1048,8 +1090,8 @@ static int cam_tfe_csid_init_config_pxl_path( * configure Pxl path and enable the time stamp capture. * enable the HW measrurement blocks */ - val = (path_data->vc << csid_reg->cmn_reg->vc_shift_val) | - (path_data->dt << csid_reg->cmn_reg->dt_shift_val) | + val = (path_data->vc_dt[0].vc << csid_reg->cmn_reg->vc_shift_val) | + (path_data->vc_dt[0].dt << csid_reg->cmn_reg->dt_shift_val) | (path_data->cid << csid_reg->cmn_reg->dt_id_shift_val) | (decode_format << csid_reg->cmn_reg->fmt_shift_val) | (path_data->crop_enable << @@ -1058,10 +1100,64 @@ static int cam_tfe_csid_init_config_pxl_path( csid_reg->cmn_reg->crop_v_en_shift_val) | (1 << 1); + if (pxl_reg->binning_supported && (path_data->qcfa_bin || + path_data->bayer_bin)) { + + CAM_DBG(CAM_ISP, + "Set Binning mode, binning_supported: %d, qcfa_bin: %d, bayer_bin: %d", + pxl_reg->binning_supported, path_data->qcfa_bin, + path_data->bayer_bin); + + if (path_data->bayer_bin && !(pxl_reg->binning_supported & + CAM_TFE_CSID_BIN_BAYER)) { + CAM_ERR(CAM_ISP, + "Bayer bin is not supported! binning_supported: %d", + pxl_reg->binning_supported); + return -EINVAL; + } + + if (path_data->qcfa_bin && !(pxl_reg->binning_supported & + CAM_TFE_CSID_BIN_QCFA)) { + CAM_ERR(CAM_ISP, + "QCFA bin is not supported! binning_supported: %d", + pxl_reg->binning_supported); + return -EINVAL; + } + + if (path_data->qcfa_bin && path_data->bayer_bin) { + CAM_ERR(CAM_ISP, + "Bayer bin and QCFA bin could not be enabled together!"); + return -EINVAL; + } + + if (path_data->bayer_bin) + val |= 1 << pxl_reg->bin_en_shift_val; + + if (path_data->qcfa_bin) { + val |= 1 << pxl_reg->bin_qcfa_en_shift_val; + val |= 1 << pxl_reg->bin_en_shift_val; + } + } + + if (csid_reg->cmn_reg->format_measure_support && + (csid_hw->csid_debug & TFE_CSID_DEBUG_ENABLE_HBI_VBI_INFO)) + val |= (1 << pxl_reg->format_measure_en_shift_val); + val |= (1 << pxl_reg->pix_store_en_shift_val); cam_io_w_mb(val, soc_info->reg_map[0].mem_base + pxl_reg->csid_pxl_cfg0_addr); + if (pxl_reg->is_multi_vc_dt_supported && + (path_data->num_valid_vc_dt > 1)) { + val = ((path_data->vc_dt[1].vc << + csid_reg->cmn_reg->vc1_shift_val) | + (path_data->vc_dt[1].dt << + csid_reg->cmn_reg->dt1_shift_val) | + 1 << csid_reg->cmn_reg->multi_vc_dt_en_shift_val); + cam_io_w_mb(val, soc_info->reg_map[0].mem_base + + pxl_reg->csid_pxl_multi_vcdt_cfg0_addr); + } + val = cam_io_r_mb(soc_info->reg_map[0].mem_base + pxl_reg->csid_pxl_cfg1_addr); @@ -1097,6 +1193,15 @@ static int cam_tfe_csid_init_config_pxl_path( } } + if (csid_reg->cmn_reg->format_measure_support && + (csid_hw->csid_debug & TFE_CSID_DEBUG_ENABLE_HBI_VBI_INFO)) { + val = cam_io_r_mb(soc_info->reg_map[0].mem_base + + pxl_reg->csid_pxl_format_measure_cfg0_addr); + val |= pxl_reg->measure_en_hbi_vbi_cnt_val; + cam_io_w_mb(val, soc_info->reg_map[0].mem_base + + pxl_reg->csid_pxl_format_measure_cfg0_addr); + } + /* Enable the Pxl path */ val = cam_io_r_mb(soc_info->reg_map[0].mem_base + pxl_reg->csid_pxl_cfg0_addr); @@ -1115,23 +1220,23 @@ static int cam_tfe_csid_init_config_pxl_path( if (csid_hw->csid_debug & TFE_CSID_DEBUG_ENABLE_SHORT_PKT_CAPTURE) val = ((1 << csid_reg->csi2_reg->csi2_capture_short_pkt_en_shift) | - (path_data->vc << + (path_data->vc_dt[0].vc << csid_reg->csi2_reg->csi2_capture_short_pkt_vc_shift)); if (csid_hw->csid_debug & TFE_CSID_DEBUG_ENABLE_LONG_PKT_CAPTURE) val |= ((1 << csid_reg->csi2_reg->csi2_capture_long_pkt_en_shift) | - (path_data->dt << + (path_data->vc_dt[0].dt << csid_reg->csi2_reg->csi2_capture_long_pkt_dt_shift) | - (path_data->vc << + (path_data->vc_dt[0].vc << csid_reg->csi2_reg->csi2_capture_long_pkt_vc_shift)); if (csid_hw->csid_debug & TFE_CSID_DEBUG_ENABLE_CPHY_PKT_CAPTURE) val |= ((1 << csid_reg->csi2_reg->csi2_capture_cphy_pkt_en_shift) | - (path_data->dt << + (path_data->vc_dt[0].dt << csid_reg->csi2_reg->csi2_capture_cphy_pkt_dt_shift) | - (path_data->vc << + (path_data->vc_dt[0].vc << csid_reg->csi2_reg->csi2_capture_cphy_pkt_vc_shift)); cam_io_w_mb(val, soc_info->reg_map[0].mem_base + @@ -1245,6 +1350,11 @@ static int cam_tfe_csid_enable_pxl_path( TFE_CSID_PATH_IPP_ERROR_CCIF_VIOLATION | TFE_CSID_PATH_IPP_OVERFLOW_IRQ; + 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) val |= TFE_CSID_PATH_INFO_INPUT_SOF; if (csid_hw->csid_debug & TFE_CSID_DEBUG_ENABLE_EOF_IRQ) @@ -1392,9 +1502,10 @@ static int cam_tfe_csid_init_config_rdi_path( struct cam_isp_resource_node *res) { int rc = 0; - struct cam_tfe_csid_path_cfg *path_data; - const struct cam_tfe_csid_reg_offset *csid_reg; - struct cam_hw_soc_info *soc_info; + struct cam_tfe_csid_path_cfg *path_data; + const struct cam_tfe_csid_reg_offset *csid_reg; + const struct cam_tfe_csid_rdi_reg_offset *rdi_reg; + struct cam_hw_soc_info *soc_info; uint32_t path_format = 0, plain_fmt = 0, val = 0, id; path_data = (struct cam_tfe_csid_path_cfg *) res->res_priv; @@ -1408,6 +1519,7 @@ static int cam_tfe_csid_init_config_rdi_path( return -EINVAL; } + rdi_reg = csid_reg->rdi_reg[id]; rc = cam_tfe_csid_get_format_rdi(path_data->in_format, path_data->out_format, &path_format, &plain_fmt); if (rc) @@ -1417,16 +1529,31 @@ static int cam_tfe_csid_init_config_rdi_path( * RDI path config and enable the time stamp capture * Enable the measurement blocks */ - val = (path_data->vc << csid_reg->cmn_reg->vc_shift_val) | - (path_data->dt << csid_reg->cmn_reg->dt_shift_val) | + val = (path_data->vc_dt[0].vc << csid_reg->cmn_reg->vc_shift_val) | + (path_data->vc_dt[0].dt << csid_reg->cmn_reg->dt_shift_val) | (path_data->cid << csid_reg->cmn_reg->dt_id_shift_val) | (path_format << csid_reg->cmn_reg->fmt_shift_val) | (plain_fmt << csid_reg->cmn_reg->plain_fmt_shit_val) | (1 << 2) | 1; + if (csid_reg->cmn_reg->format_measure_support && + (csid_hw->csid_debug & TFE_CSID_DEBUG_ENABLE_HBI_VBI_INFO)) + val |= (1 << rdi_reg->format_measure_en_shift_val); + cam_io_w_mb(val, soc_info->reg_map[0].mem_base + csid_reg->rdi_reg[id]->csid_rdi_cfg0_addr); + if (csid_reg->rdi_reg[id]->is_multi_vc_dt_supported && + (path_data->num_valid_vc_dt > 1)) { + val = ((path_data->vc_dt[1].vc << + csid_reg->cmn_reg->vc1_shift_val) | + (path_data->vc_dt[1].dt << + csid_reg->cmn_reg->dt1_shift_val) | + (1 << csid_reg->cmn_reg->multi_vc_dt_en_shift_val)); + cam_io_w_mb(val, soc_info->reg_map[0].mem_base + + csid_reg->rdi_reg[id]->csid_rdi_multi_vcdt_cfg0_addr); + } + /* select the post irq sub sample strobe for time stamp capture */ cam_io_w_mb(TFE_CSID_TIMESTAMP_STB_POST_IRQ, soc_info->reg_map[0].mem_base + @@ -1441,6 +1568,15 @@ static int cam_tfe_csid_init_config_rdi_path( cam_io_w_mb(0, soc_info->reg_map[0].mem_base + csid_reg->rdi_reg[id]->csid_rdi_ctrl_addr); + if (csid_reg->cmn_reg->format_measure_support && + (csid_hw->csid_debug & TFE_CSID_DEBUG_ENABLE_HBI_VBI_INFO)) { + val = cam_io_r_mb(soc_info->reg_map[0].mem_base + + rdi_reg->csid_rdi_format_measure_cfg0_addr); + val |= rdi_reg->measure_en_hbi_vbi_cnt_val; + cam_io_w_mb(val, soc_info->reg_map[0].mem_base + + rdi_reg->csid_rdi_format_measure_cfg0_addr); + } + /* Enable the RPP path */ val = cam_io_r_mb(soc_info->reg_map[0].mem_base + csid_reg->rdi_reg[id]->csid_rdi_cfg0_addr); @@ -1453,23 +1589,23 @@ static int cam_tfe_csid_init_config_rdi_path( if (csid_hw->csid_debug & TFE_CSID_DEBUG_ENABLE_SHORT_PKT_CAPTURE) val = ((1 << csid_reg->csi2_reg->csi2_capture_short_pkt_en_shift) | - (path_data->vc << + (path_data->vc_dt[0].vc << csid_reg->csi2_reg->csi2_capture_short_pkt_vc_shift)); if (csid_hw->csid_debug & TFE_CSID_DEBUG_ENABLE_LONG_PKT_CAPTURE) val |= ((1 << csid_reg->csi2_reg->csi2_capture_long_pkt_en_shift) | - (path_data->dt << + (path_data->vc_dt[0].dt << csid_reg->csi2_reg->csi2_capture_long_pkt_dt_shift) | - (path_data->vc << + (path_data->vc_dt[0].vc << csid_reg->csi2_reg->csi2_capture_long_pkt_vc_shift)); if (csid_hw->csid_debug & TFE_CSID_DEBUG_ENABLE_CPHY_PKT_CAPTURE) val |= ((1 << csid_reg->csi2_reg->csi2_capture_cphy_pkt_en_shift) | - (path_data->dt << + (path_data->vc_dt[0].dt << csid_reg->csi2_reg->csi2_capture_cphy_pkt_dt_shift) | - (path_data->vc << + (path_data->vc_dt[0].vc << csid_reg->csi2_reg->csi2_capture_cphy_pkt_vc_shift)); cam_io_w_mb(val, soc_info->reg_map[0].mem_base + csid_reg->csi2_reg->csid_csi2_rx_capture_ctrl_addr); @@ -1541,6 +1677,11 @@ static int cam_tfe_csid_enable_rdi_path( TFE_CSID_PATH_RDI_ERROR_CCIF_VIOLATION | TFE_CSID_PATH_RDI_OVERFLOW_IRQ; + 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) val |= TFE_CSID_PATH_INFO_INPUT_SOF; if (csid_hw->csid_debug & TFE_CSID_DEBUG_ENABLE_EOF_IRQ) @@ -2420,7 +2561,7 @@ static int cam_tfe_csid_get_regdump(struct cam_tfe_csid_hw *csid_hw, struct cam_isp_resource_node *res; struct cam_tfe_csid_path_cfg *path_data; uint32_t id; - int val; + int i, val; csid_reg = (struct cam_tfe_csid_reg_offset *) csid_hw->csid_info->csid_reg; @@ -2489,10 +2630,14 @@ static int cam_tfe_csid_get_regdump(struct cam_tfe_csid_hw *csid_hw, path_data->start_line, path_data->end_line, path_data->width, path_data->height); CAM_INFO(CAM_ISP, - "clock:%d crop_enable:%d vc:%d dt:%d informat:%d outformat:%d", + "clock:%d crop_enable:%d num of vc_dt:%d informat:%d outformat:%d", path_data->clk_rate, path_data->crop_enable, - path_data->vc, path_data->dt, + path_data->num_valid_vc_dt, path_data->in_format, path_data->out_format); + for (i = 0; i < path_data->num_valid_vc_dt; i++) { + CAM_INFO(CAM_ISP, "vc[%d]: %d, dt[%d]: %d", + i, path_data->vc_dt[i].vc, i, path_data->vc_dt[i].dt); + } return 0; } @@ -2884,12 +3029,15 @@ irqreturn_t cam_tfe_csid_irq(int irq_num, void *data) struct cam_tfe_csid_hw *csid_hw; struct cam_hw_soc_info *soc_info; const struct cam_tfe_csid_reg_offset *csid_reg; + const struct cam_tfe_csid_pxl_reg_offset *ipp_reg; + const struct cam_tfe_csid_rdi_reg_offset *rdi_reg; + const struct cam_tfe_csid_common_reg_offset *cmn_reg; const struct cam_tfe_csid_csi2_rx_reg_offset *csi2_reg; uint32_t irq_status[TFE_CSID_IRQ_REG_MAX]; bool fatal_err_detected = false, is_error_irq = false; uint32_t sof_irq_debug_en = 0, log_en = 0; unsigned long flags; - uint32_t i, val; + uint32_t i, val, val1; if (!data) { CAM_ERR(CAM_ISP, "CSID: Invalid arguments"); @@ -3213,6 +3361,32 @@ handle_fatal_error: TFE_CSID_PATH_IPP_ERROR_CCIF_VIOLATION) is_error_irq = true; + if ((irq_status[TFE_CSID_IRQ_REG_IPP] & + TFE_CSID_PATH_ERROR_PIX_COUNT) || + (irq_status[TFE_CSID_IRQ_REG_IPP] & + TFE_CSID_PATH_ERROR_LINE_COUNT)) { + ipp_reg = csid_reg->ipp_reg; + cmn_reg = csid_reg->cmn_reg; + val = cam_io_r_mb(soc_info->reg_map[0].mem_base + + ipp_reg->csid_pxl_format_measure0_addr); + val1 = cam_io_r_mb(soc_info->reg_map[0].mem_base + + ipp_reg->csid_pxl_format_measure_cfg1_addr); + + CAM_ERR(CAM_ISP, + "Pix/Line count error for CSID: %d IPP path, Expected:: height: %d, width: %d and Actual:: height: %d width %d", + csid_hw->hw_intf->hw_idx, + ((val1 >> + cmn_reg->format_measure_height_shift_val) & + cmn_reg->format_measure_height_mask_val), + val1 & + cmn_reg->format_measure_width_mask_val, + ((val >> + cmn_reg->format_measure_height_shift_val) & + cmn_reg->format_measure_height_mask_val), + val & + cmn_reg->format_measure_width_mask_val); + } + } for (i = 0; i < csid_reg->cmn_reg->num_rdis; i++) { @@ -3264,6 +3438,30 @@ handle_fatal_error: (irq_status[i] & TFE_CSID_PATH_RDI_ERROR_CCIF_VIOLATION)) is_error_irq = true; + + if ((irq_status[i] & TFE_CSID_PATH_ERROR_PIX_COUNT) || + (irq_status[i] & TFE_CSID_PATH_ERROR_LINE_COUNT)) { + rdi_reg = csid_reg->rdi_reg[i]; + cmn_reg = csid_reg->cmn_reg; + val = cam_io_r_mb(soc_info->reg_map[0].mem_base + + rdi_reg->csid_rdi_format_measure0_addr); + val1 = cam_io_r_mb(soc_info->reg_map[0].mem_base + + rdi_reg->csid_rdi_format_measure_cfg1_addr); + + CAM_ERR(CAM_ISP, + "Pix/Line count error for CSID:%d RDI:%d path, Expected:: height: %d, width: %d and Actual:: height: %d width %d", + csid_hw->hw_intf->hw_idx, i, + ((val1 >> + cmn_reg->format_measure_height_shift_val) & + cmn_reg->format_measure_height_mask_val), + val1 & + cmn_reg->format_measure_width_mask_val, + ((val >> + cmn_reg->format_measure_height_shift_val) & + cmn_reg->format_measure_height_mask_val), + val & + cmn_reg->format_measure_width_mask_val); + } } if (is_error_irq || log_en) @@ -3283,7 +3481,7 @@ int cam_tfe_csid_hw_probe_init(struct cam_hw_intf *csid_hw_intf, uint32_t csid_idx) { int rc = -EINVAL; - uint32_t i, val, clk_lvl; + uint32_t i, j, val, clk_lvl; struct cam_tfe_csid_path_cfg *path_data; struct cam_hw_info *csid_hw_info; struct cam_tfe_csid_hw *tfe_csid_hw = NULL; @@ -3350,8 +3548,11 @@ int cam_tfe_csid_hw_probe_init(struct cam_hw_intf *csid_hw_intf, /* reset the cid values */ for (i = 0; i < CAM_TFE_CSID_CID_MAX; i++) { - tfe_csid_hw->cid_res[i].vc = 0; - tfe_csid_hw->cid_res[i].dt = 0; + for (j = 0; j < CAM_ISP_TFE_VC_DT_CFG ; j++) { + tfe_csid_hw->cid_res[i].vc_dt[j].vc = 0; + tfe_csid_hw->cid_res[i].vc_dt[j].dt = 0; + } + tfe_csid_hw->cid_res[i].num_valid_vc_dt = 0; tfe_csid_hw->cid_res[i].cnt = 0; } diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_csid_hw/cam_tfe_csid_core.h b/drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_csid_hw/cam_tfe_csid_core.h index 55d71df6fa..08a31b2345 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_csid_hw/cam_tfe_csid_core.h +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_csid_hw/cam_tfe_csid_core.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* - * Copyright (c) 2019-2020, The Linux Foundation. All rights reserved. + * Copyright (c) 2019-2021, The Linux Foundation. All rights reserved. */ #ifndef _CAM_TFE_CSID_HW_H_ @@ -52,6 +52,8 @@ #define TFE_CSID_PATH_INFO_INPUT_EOL BIT(10) #define TFE_CSID_PATH_INFO_INPUT_SOL BIT(11) #define TFE_CSID_PATH_INFO_INPUT_SOF BIT(12) +#define TFE_CSID_PATH_ERROR_PIX_COUNT BIT(13) +#define TFE_CSID_PATH_ERROR_LINE_COUNT BIT(14) #define TFE_CSID_PATH_IPP_ERROR_CCIF_VIOLATION BIT(15) #define TFE_CSID_PATH_IPP_OVERFLOW_IRQ BIT(16) #define TFE_CSID_PATH_IPP_FRAME_DROP BIT(17) @@ -76,6 +78,14 @@ #define CAM_CSID_EVT_PAYLOAD_MAX 10 +/* Binning supported masks. Binning support changes for specific paths + * and also for targets. With the mask, we handle the supported features + * in reg files and handle in code accordingly. + */ + +#define CAM_TFE_CSID_BIN_BAYER BIT(0) +#define CAM_TFE_CSID_BIN_QCFA BIT(1) + /* enum cam_csid_path_halt_mode select the path halt mode control */ enum cam_tfe_csid_path_halt_mode { TFE_CSID_HALT_MODE_INTERNAL, @@ -121,6 +131,12 @@ struct cam_tfe_csid_pxl_reg_offset { uint32_t csid_pxl_err_recovery_cfg0_addr; uint32_t csid_pxl_err_recovery_cfg1_addr; uint32_t csid_pxl_err_recovery_cfg2_addr; + uint32_t csid_pxl_multi_vcdt_cfg0_addr; + uint32_t csid_pxl_format_measure_cfg0_addr; + uint32_t csid_pxl_format_measure_cfg1_addr; + uint32_t csid_pxl_format_measure0_addr; + uint32_t csid_pxl_format_measure1_addr; + uint32_t csid_pxl_format_measure2_addr; /* configuration */ uint32_t pix_store_en_shift_val; @@ -129,6 +145,12 @@ struct cam_tfe_csid_pxl_reg_offset { uint32_t halt_mode_shift; uint32_t halt_master_sel_master_val; uint32_t halt_master_sel_slave_val; + uint32_t binning_supported; + uint32_t bin_qcfa_en_shift_val; + uint32_t bin_en_shift_val; + uint32_t format_measure_en_shift_val; + uint32_t measure_en_hbi_vbi_cnt_val; + bool is_multi_vc_dt_supported; }; struct cam_tfe_csid_rdi_reg_offset { @@ -158,9 +180,18 @@ struct cam_tfe_csid_rdi_reg_offset { uint32_t csid_rdi_err_recovery_cfg2_addr; uint32_t csid_rdi_byte_cntr_ping_addr; uint32_t csid_rdi_byte_cntr_pong_addr; + uint32_t csid_rdi_multi_vcdt_cfg0_addr; + uint32_t csid_rdi_format_measure_cfg0_addr; + uint32_t csid_rdi_format_measure_cfg1_addr; + uint32_t csid_rdi_format_measure0_addr; + uint32_t csid_rdi_format_measure1_addr; + uint32_t csid_rdi_format_measure2_addr; /* configuration */ uint32_t packing_format; + uint32_t format_measure_en_shift_val; + uint32_t measure_en_hbi_vbi_cnt_val; + bool is_multi_vc_dt_supported; }; struct cam_tfe_csid_csi2_rx_reg_offset { @@ -234,6 +265,9 @@ struct cam_tfe_csid_common_reg_offset { uint32_t dt_id_shift_val; uint32_t vc_shift_val; uint32_t dt_shift_val; + uint32_t vc1_shift_val; + uint32_t dt1_shift_val; + uint32_t multi_vc_dt_en_shift_val; uint32_t fmt_shift_val; uint32_t plain_fmt_shit_val; uint32_t crop_v_en_shift_val; @@ -243,6 +277,10 @@ struct cam_tfe_csid_common_reg_offset { uint32_t rdi_irq_mask_all; uint32_t top_tfe2_pix_pipe_fuse_reg; uint32_t top_tfe2_fuse_reg; + uint32_t format_measure_height_shift_val; + uint32_t format_measure_height_mask_val; + uint32_t format_measure_width_mask_val; + bool format_measure_support; }; /** @@ -290,53 +328,68 @@ struct cam_tfe_csid_csi2_rx_cfg { uint32_t lane_cfg; }; +/** + * struct vc_dt_data- VC DT data + * + * @vc: VC data + * @dt: DT data + * + */ +struct vc_dt_data { + uint32_t vc; + uint32_t dt; +}; + /** * struct cam_tfe_csid_cid_data- cid configuration private data * - * @vc: Virtual channel - * @dt: Data type - * @cnt: Cid resource reference count. + * @vc_dt: VC DT data + * @num_valid_vc_dt: Number of VC-DTs + * @cnt: Cid resource reference count. * */ struct cam_tfe_csid_cid_data { - uint32_t vc; - uint32_t dt; + struct vc_dt_data vc_dt[CAM_ISP_TFE_VC_DT_CFG]; + uint32_t num_valid_vc_dt; uint32_t cnt; }; /** * struct cam_tfe_csid_path_cfg- csid path configuration details. It is stored * as private data for IPP/ RDI paths - * @vc : Virtual channel number - * @dt : Data type number - * @cid cid number, it is same as DT_ID number in HW - * @in_format: input decode format - * @out_format: output format - * @crop_enable: crop is enable or disabled, if enabled - * then remaining parameters are valid. - * @start_pixel: start pixel - * @end_pixel: end_pixel - * @width: width - * @start_line: start line - * @end_line: end_line - * @height: heigth - * @sync_mode: Applicable for IPP/RDI path reservation - * Reserving the path for master IPP or slave IPP - * master (set value 1), Slave ( set value 2) - * for RDI, set mode to none - * @master_idx: For Slave reservation, Give master TFE instance Index. - * Slave will synchronize with master Start and stop operations - * @clk_rate Clock rate - * @sensor_width Sensor width in pixel - * @sensor_height Sensor height in pixel - * @sensor_fps Sensor fps - * @sensor_hbi Sensor horizontal blanking interval - * @sensor_vbi Sensor vertical blanking interval + * @vc_dt : VC DT data + * @num_valid_vc_dt: Number of valid VC-DTs + * @cid cid number, it is same as DT_ID number in HW + * @in_format: input decode format + * @out_format: output format + * @crop_enable: crop is enable or disabled, if enabled + * then remaining parameters are valid. + * @start_pixel: start pixel + * @end_pixel: end_pixel + * @width: width + * @start_line: start line + * @end_line: end_line + * @height: heigth + * @sync_mode: Applicable for IPP/RDI path reservation + * Reserving the path for master IPP or slave IPP + * master (set value 1), Slave ( set value 2) + * for RDI, set mode to none + * @master_idx: For Slave reservation, Give master TFE instance Index. + * Slave will synchronize with master Start and stop + * operations + * @clk_rate: Clock rate + * @sensor_width: Sensor width in pixel + * @sensor_height: Sensor height in pixel + * @sensor_fps: Sensor fps + * @sensor_hbi: Sensor horizontal blanking interval + * @sensor_vbi: Sensor vertical blanking interval + * @bayer_bin: Bayer binning + * @qcfa_bin: Quad-CFA binning * */ struct cam_tfe_csid_path_cfg { - uint32_t vc; - uint32_t dt; + struct vc_dt_data vc_dt[CAM_ISP_TFE_VC_DT_CFG]; + uint32_t num_valid_vc_dt; uint32_t cid; uint32_t in_format; uint32_t out_format; @@ -355,6 +408,8 @@ struct cam_tfe_csid_path_cfg { uint32_t sensor_fps; uint32_t sensor_hbi; uint32_t sensor_vbi; + uint32_t bayer_bin; + uint32_t qcfa_bin; }; /** diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_hw/cam_tfe530.h b/drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_hw/cam_tfe530.h index dec5cdc086..7d5d4ce91d 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_hw/cam_tfe530.h +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_hw/cam_tfe530.h @@ -51,6 +51,7 @@ static struct cam_tfe_top_reg_offset_common tfe530_top_commong_reg = { .diag_min_hbi_error_shift = 15, .diag_neq_hbi_shift = 14, .diag_sensor_hbi_mask = 0x3FFF, + .serializer_supported = false, }; static struct cam_tfe_camif_reg tfe530_camif_reg = { diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_hw/cam_tfe640.h b/drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_hw/cam_tfe640.h index dd319d67d0..6d350dfbe3 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_hw/cam_tfe640.h +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_hw/cam_tfe640.h @@ -64,6 +64,7 @@ static struct cam_tfe_top_reg_offset_common tfe640_top_commong_reg = { .diag_min_hbi_error_shift = 15, .diag_neq_hbi_shift = 14, .diag_sensor_hbi_mask = 0x3FFF, + .serializer_supported = true, }; static struct cam_tfe_camif_reg tfe640_camif_reg = { @@ -119,6 +120,9 @@ static struct cam_tfe_camif_reg_data tfe640_camif_reg_data = { .perf_client_sel_shift = 8, .perf_window_start_shift = 16, .perf_window_end_shift = 20, + .ai_c_srl_en_shift = 11, + .ds16_c_srl_en_shift = 10, + .ds4_c_srl_en_shift = 9, }; static struct cam_tfe_rdi_reg tfe640_rdi0_reg = { diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_hw/cam_tfe_bus.c b/drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_hw/cam_tfe_bus.c index 20fda8ec29..10cd4ac09e 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_hw/cam_tfe_bus.c +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_hw/cam_tfe_bus.c @@ -20,6 +20,7 @@ #include "cam_tfe_soc.h" #include "cam_debug_util.h" #include "cam_cpas_api.h" +#include "cam_tfe_csid_hw_intf.h" static const char drv_name[] = "tfe_bus"; @@ -680,15 +681,15 @@ static int cam_tfe_bus_acquire_rdi_wm( } static int cam_tfe_bus_acquire_wm( - struct cam_tfe_bus_priv *bus_priv, - struct cam_isp_tfe_out_port_info *out_port_info, - struct cam_isp_resource_node **wm_res, - void *tasklet, - enum cam_tfe_bus_tfe_out_id tfe_out_res_id, - enum cam_tfe_bus_plane_type plane, - uint32_t *client_done_mask, - uint32_t is_dual, - enum cam_tfe_bus_comp_grp_id *comp_grp_id) + struct cam_tfe_bus_priv *bus_priv, + struct cam_isp_tfe_out_port_generic_info *out_port_info, + struct cam_isp_resource_node **wm_res, + void *tasklet, + enum cam_tfe_bus_tfe_out_id tfe_out_res_id, + enum cam_tfe_bus_plane_type plane, + uint32_t *client_done_mask, + uint32_t is_dual, + enum cam_tfe_bus_comp_grp_id *comp_grp_id) { struct cam_isp_resource_node *wm_res_local = NULL; struct cam_tfe_bus_wm_resource_data *rsrc_data = NULL; @@ -985,15 +986,15 @@ static bool cam_tfe_bus_match_comp_grp( } static int cam_tfe_bus_acquire_comp_grp( - struct cam_tfe_bus_priv *bus_priv, - struct cam_isp_tfe_out_port_info *out_port_info, - void *tasklet, - uint32_t is_dual, - uint32_t is_master, - struct cam_isp_resource_node **comp_grp, - enum cam_tfe_bus_comp_grp_id comp_grp_id, - struct cam_isp_resource_node *out_rsrc, - uint32_t source_group) + struct cam_tfe_bus_priv *bus_priv, + struct cam_isp_tfe_out_port_generic_info *out_port_info, + void *tasklet, + uint32_t is_dual, + uint32_t is_master, + struct cam_isp_resource_node **comp_grp, + enum cam_tfe_bus_comp_grp_id comp_grp_id, + struct cam_isp_resource_node *out_rsrc, + uint32_t source_group) { int rc = 0; struct cam_isp_resource_node *comp_grp_local = NULL; diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_hw/cam_tfe_core.c b/drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_hw/cam_tfe_core.c index a00bdb16ce..3b3522f002 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_hw/cam_tfe_core.c +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_hw/cam_tfe_core.c @@ -20,6 +20,7 @@ #include "cam_cpas_api.h" #include "cam_compat.h" #include "cam_common_util.h" +#include "cam_tfe_csid_hw_intf.h" static const char drv_name[] = "tfe"; @@ -85,6 +86,9 @@ struct cam_tfe_camif_data { uint32_t dual_tfe_sync_sel; uint32_t hbi_value; uint32_t vbi_value; + uint32_t qcfa_bin; + uint32_t bayer_bin; + uint32_t core_cfg; }; struct cam_tfe_rdi_data { @@ -1887,6 +1891,12 @@ int cam_tfe_top_reserve(void *device_priv, camif_data->sync_mode = acquire_args->sync_mode; camif_data->event_cb = args->event_cb; camif_data->priv = args->priv; + camif_data->qcfa_bin = + acquire_args->in_port->qcfa_bin; + camif_data->bayer_bin = + acquire_args->in_port->bayer_bin; + camif_data->core_cfg = + acquire_args->in_port->core_cfg; CAM_DBG(CAM_ISP, "TFE:%d pix_pattern:%d dsp_mode=%d", @@ -2017,6 +2027,18 @@ static int cam_tfe_camif_resource_start( /* enables the Delay Line CLC in the pixel pipeline */ val |= BIT(rsrc_data->reg_data->delay_line_en_shift); + if (rsrc_data->common_reg->serializer_supported) { + val |= rsrc_data->core_cfg & + (1 << rsrc_data->reg_data->ai_c_srl_en_shift); + + val |= rsrc_data->core_cfg & + (1 << rsrc_data->reg_data->ds16_c_srl_en_shift); + + val |= rsrc_data->core_cfg & + (1 << rsrc_data->reg_data->ds4_c_srl_en_shift); + } + + cam_io_w_mb(val, rsrc_data->mem_base + rsrc_data->common_reg->core_cfg_0); @@ -2043,6 +2065,9 @@ static int cam_tfe_camif_resource_start( epoch0_irq_mask = (rsrc_data->last_line - rsrc_data->first_line); + if (rsrc_data->bayer_bin || rsrc_data->qcfa_bin) + epoch0_irq_mask >>= 1; + epoch1_irq_mask = rsrc_data->reg_data->epoch_line_cfg & 0xFFFF; computed_epoch_line_cfg = (epoch0_irq_mask << 16) | diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_hw/cam_tfe_core.h b/drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_hw/cam_tfe_core.h index f855160d18..1728e4d55e 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_hw/cam_tfe_core.h +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_hw/cam_tfe_core.h @@ -107,6 +107,9 @@ struct cam_tfe_top_reg_offset_common { uint32_t diag_min_hbi_error_shift; uint32_t diag_neq_hbi_shift; uint32_t diag_sensor_hbi_mask; + + /* configuration */ + bool serializer_supported; }; struct cam_tfe_camif_reg { @@ -163,6 +166,10 @@ struct cam_tfe_camif_reg_data { uint32_t perf_client_sel_shift; uint32_t perf_window_start_shift; uint32_t perf_window_end_shift; + + uint32_t ai_c_srl_en_shift; + uint32_t ds16_c_srl_en_shift; + uint32_t ds4_c_srl_en_shift; }; struct cam_tfe_camif_hw_info { diff --git a/drivers/cam_isp/isp_hw_mgr/isp_hw/top_tpg/cam_top_tpg_ver1.c b/drivers/cam_isp/isp_hw_mgr/isp_hw/top_tpg/cam_top_tpg_ver1.c index 6c0fb3092c..cf6d5885db 100644 --- a/drivers/cam_isp/isp_hw_mgr/isp_hw/top_tpg/cam_top_tpg_ver1.c +++ b/drivers/cam_isp/isp_hw_mgr/isp_hw/top_tpg/cam_top_tpg_ver1.c @@ -124,13 +124,13 @@ static int cam_top_tpg_ver1_reserve( return -EINVAL; } - if ((reserv->in_port[0]->vc > 0xF) || + if ((reserv->in_port[0]->vc[0] > 0xF) || (reserv->in_port[0]->lane_num <= 0 || reserv->in_port[0]->lane_num > 4) || (reserv->in_port[0]->pix_pattern > 4) || (reserv->in_port[0]->lane_type >= 2)) { CAM_ERR_RATE_LIMIT(CAM_ISP, "TPG:%u invalid input %d %d %d %d", - tpg_hw->hw_intf->hw_idx, reserv->in_port[0]->vc, + tpg_hw->hw_intf->hw_idx, reserv->in_port[0]->vc[0], reserv->in_port[0]->lane_num, reserv->in_port[0]->pix_pattern, reserv->in_port[0]->lane_type); @@ -145,13 +145,13 @@ static int cam_top_tpg_ver1_reserve( CAM_DBG(CAM_ISP, "TPG: %u enter", tpg_hw->hw_intf->hw_idx); tpg_data = (struct cam_top_tpg_cfg *)tpg_hw->tpg_res.res_priv; - tpg_data->vc_num[0] = reserv->in_port[0]->vc; + tpg_data->vc_num[0] = reserv->in_port[0]->vc[0]; tpg_data->phy_sel = reserv->in_port[0]->lane_type; tpg_data->num_active_lanes = reserv->in_port[0]->lane_num; tpg_data->h_blank_count = reserv->in_port[0]->sensor_hbi; tpg_data->v_blank_count = reserv->in_port[0]->sensor_vbi; tpg_data->pix_pattern = reserv->in_port[0]->pix_pattern; - tpg_data->dt_cfg[0].data_type = reserv->in_port[0]->dt; + tpg_data->dt_cfg[0].data_type = reserv->in_port[0]->dt[0]; tpg_data->dt_cfg[0].frame_height = reserv->in_port[0]->height; if (reserv->in_port[0]->usage_type) tpg_data->dt_cfg[0].frame_width = @@ -182,7 +182,7 @@ static int cam_top_tpg_ver1_reserve( goto end; for (i = 1; i < reserv->num_inport; i++) { - if ((tpg_data->vc_num[0] != reserv->in_port[i]->vc) || + if ((tpg_data->vc_num[0] != reserv->in_port[i]->vc[0]) || (tpg_data->phy_sel != reserv->in_port[i]->lane_type) || (tpg_data->num_active_lanes != reserv->in_port[i]->lane_num) || @@ -199,7 +199,7 @@ static int cam_top_tpg_ver1_reserve( if (rc) return rc; - tpg_data->dt_cfg[i].data_type = reserv->in_port[i]->dt; + tpg_data->dt_cfg[i].data_type = reserv->in_port[i]->dt[0]; tpg_data->dt_cfg[i].frame_height = reserv->in_port[i]->height; tpg_data->dt_cfg[i].frame_width = diff --git a/drivers/camera_main.c b/drivers/camera_main.c index 9a5ddbec4a..62d009c4e8 100644 --- a/drivers/camera_main.c +++ b/drivers/camera_main.c @@ -58,7 +58,7 @@ #include "cam_top_tpg.h" #include "cam_tfe_dev.h" -#include "cam_tfe_csid530.h" +#include "cam_tfe_csid.h" #include "cam_csid_ppi100.h" #include "camera_main.h" @@ -86,7 +86,7 @@ static const struct camera_submodule_component camera_tfe[] = { #ifdef CONFIG_SPECTRA_TFE {&cam_csid_ppi100_init_module, &cam_csid_ppi100_exit_module}, {&cam_tfe_init_module, &cam_tfe_exit_module}, - {&cam_tfe_csid530_init_module, &cam_tfe_csid530_exit_module}, + {&cam_tfe_csid_init_module, &cam_tfe_csid_exit_module}, #endif }; diff --git a/drivers/camera_main.h b/drivers/camera_main.h index 19baa4126f..f0a0767e56 100644 --- a/drivers/camera_main.h +++ b/drivers/camera_main.h @@ -25,7 +25,7 @@ extern struct platform_driver isp_driver; #ifdef CONFIG_SPECTRA_TFE extern struct platform_driver cam_csid_ppi100_driver; extern struct platform_driver cam_tfe_driver; -extern struct platform_driver cam_tfe_csid530_driver; +extern struct platform_driver cam_tfe_csid_driver; #endif #ifdef CONFIG_SPECTRA_SENSOR extern struct platform_driver cam_res_mgr_driver; @@ -87,7 +87,7 @@ static struct platform_driver *const cam_component_drivers[] = { #ifdef CONFIG_SPECTRA_TFE &cam_csid_ppi100_driver, &cam_tfe_driver, - &cam_tfe_csid530_driver, + &cam_tfe_csid_driver, #endif #ifdef CONFIG_SPECTRA_ISP &cam_top_tpg_driver, diff --git a/include/uapi/camera/media/cam_tfe.h b/include/uapi/camera/media/cam_tfe.h index 523cff3395..e384407881 100644 --- a/include/uapi/camera/media/cam_tfe.h +++ b/include/uapi/camera/media/cam_tfe.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0-only WITH Linux-syscall-note */ /* - * Copyright (c) 2019-2020, The Linux Foundation. All rights reserved. + * Copyright (c) 2019-2021, The Linux Foundation. All rights reserved. */ #ifndef __UAPI_CAM_TFE_H__ @@ -88,6 +88,12 @@ #define CAM_ISP_TFE_WM_LINE_BASED_MODE 1 #define CAM_ISP_TFE_WM_INDEX_BASED_MODE 2 +#define CAM_ISP_TFE_VC_DT_CFG 2 + +/* Feature Flag indicators */ +#define CAM_ISP_TFE_FLAG_QCFA_BIN BIT(0) +#define CAM_ISP_TFE_FLAG_BAYER_BIN BIT(1) + /* Query devices */ /** * struct cam_isp_tfe_dev_cap_info - A cap info for particular hw type @@ -220,6 +226,92 @@ struct cam_isp_tfe_in_port_info { struct cam_isp_tfe_out_port_info data[1]; }; +/** + * struct cam_isp_tfe_in_port_info_v2 - An input port resource info + * + * @res_id: input resource id CAM_ISP_TFE_IN_RES_XXX + * @lane_type: lane type: c-phy or d-phy. + * @lane_num: active lane number + * @lane_cfg: lane configurations: 4 bits per lane + * @vc: input virtual channel number + * @dt: input data type number + * @format: input format + * @pix_pattern: pixel pattern + * @usage_type: whether dual tfe is required + * @left_start: left input start offset in pixels + * @left_end: left input stop offset in pixels + * @left_width: left input width in pixels + * @right_start: right input start offset in pixels. + * Only for Dual TFE + * @right_end: right input stop offset in + * pixels. Only for Dual TFE + * @right_width: right input width in pixels. + * Only for dual TFE + * @line_start: top of the line number + * @line_stop: bottome of the line number + * @height: input height in lines + * @batch_size: batch size for HFR mode + * @dsp_mode: DSP stream mode(Defines as + * CAM_ISP_TFE_DSP_MODE_*) + * @sensor_width: sensor width + * @sensor_height: sensor height + * @sensor_hbi: sensor HBI value + * @sensor_vbi: sensor VBI value + * @sensor_fps: sensor fps + * @init_frame_drop init frame drop value. + * @num_out_res: number of the output resource associated + * @feature_flag: Feature flags for indicating QCFA, Bayer bin + * @core_cfg: Core configuration + * @reserve_field_1: Reserve field 1 + * @reserve_field_2: Reserve field 2 + * @reserve_field_3: Reserve field 3 + * @reserve_field_4: Reserve field 4 + * @reserve_field_5: Reserve field 5 + * @reserve_field_6: Reserve filed 6 + * @data: payload that contains the output resources, + * array of cam_isp_tfe_out_port_info data + * + */ +struct cam_isp_tfe_in_port_info_v2 { + __u32 res_id; + __u32 lane_type; + __u32 lane_num; + __u32 lane_cfg; + __u32 vc[CAM_ISP_TFE_VC_DT_CFG]; + __u32 dt[CAM_ISP_TFE_VC_DT_CFG]; + __u32 num_valid_vc_dt; + __u32 format; + __u32 pix_pattern; + __u32 usage_type; + __u32 left_start; + __u32 left_end; + __u32 left_width; + __u32 right_start; + __u32 right_end; + __u32 right_width; + __u32 line_start; + __u32 line_end; + __u32 height; + __u32 batch_size; + __u32 dsp_mode; + __u32 sensor_width; + __u32 sensor_height; + __u32 sensor_hbi; + __u32 sensor_vbi; + __u32 sensor_fps; + __u32 init_frame_drop; + __u32 num_out_res; + __u32 feature_flag; + __u32 core_cfg; + __u32 reserve_field_1; + __u32 reserve_field_2; + __u32 reserve_field_3; + __u32 reserve_field_4; + __u32 reserve_field_5; + __u32 reserve_field_6; + struct cam_isp_tfe_out_port_info data[1]; +}; + /** * struct cam_isp_tfe_resource - A resource bundle *