Explorar o código

Merge "msm: camera: isp: Add support for TPG cfg blob" into camera-kernel.lnx.4.0

Camera Software Integration %!s(int64=4) %!d(string=hai) anos
pai
achega
f82cd27be1

+ 50 - 0
drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c

@@ -5370,6 +5370,37 @@ static int cam_isp_blob_clock_update(
 	return rc;
 }
 
+static int cam_isp_blob_tpg_config(
+	struct cam_isp_tpg_core_config        *tpg_config,
+	struct cam_hw_prepare_update_args     *prepare)
+{
+	int                                 i, rc = -EINVAL;
+	struct cam_ife_hw_mgr_ctx          *ctx = NULL;
+	struct cam_isp_hw_mgr_res          *hw_mgr_res;
+	struct cam_hw_intf                 *hw_intf;
+
+	ctx = prepare->ctxt_to_hw_map;
+	hw_mgr_res = &ctx->res_list_tpg;
+
+	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;
+		CAM_DBG(CAM_ISP, "TPG ctrl config for hw %u",
+			hw_intf->hw_idx);
+		if (hw_intf->hw_ops.process_cmd) {
+			rc = hw_intf->hw_ops.process_cmd(hw_intf->hw_priv,
+				CAM_ISP_HW_CMD_TPG_CORE_CFG_CMD, tpg_config,
+				sizeof(struct cam_isp_tpg_core_config));
+			if (rc)
+				goto end;
+		}
+	}
+
+end:
+	return rc;
+}
+
 static int cam_isp_blob_sensor_config(
 	uint32_t                               blob_type,
 	struct cam_isp_generic_blob_info      *blob_info,
@@ -6144,6 +6175,25 @@ static int cam_isp_packet_generic_blob_handler(void *user_data,
 				"Sensor Dimension Update Failed rc: %d", rc);
 	}
 		break;
+	case CAM_ISP_GENERIC_BLOB_TYPE_TPG_CORE_CONFIG: {
+		struct cam_isp_tpg_core_config *tpg_config;
+
+		if (blob_size < sizeof(struct cam_isp_tpg_core_config)) {
+			CAM_ERR(CAM_ISP, "Invalid blob size %zu expected %zu",
+				blob_size,
+				sizeof(struct cam_isp_tpg_core_config));
+			return -EINVAL;
+		}
+
+		tpg_config =
+			(struct cam_isp_tpg_core_config *)blob_data;
+
+		rc = cam_isp_blob_tpg_config(tpg_config, prepare);
+		if (rc)
+			CAM_ERR(CAM_ISP,
+				"TPG config failed rc: %d", rc);
+	}
+		break;
 	default:
 		CAM_WARN(CAM_ISP, "Invalid blob type %d", blob_type);
 		break;

+ 1 - 0
drivers/cam_isp/isp_hw_mgr/isp_hw/include/cam_isp_hw.h

@@ -127,6 +127,7 @@ enum cam_isp_hw_cmd_type {
 	CAM_ISP_HW_CMD_GET_RES_FOR_MID,
 	CAM_ISP_HW_CMD_BLANKING_UPDATE,
 	CAM_ISP_HW_CMD_CSID_CLOCK_DUMP,
+	CAM_ISP_HW_CMD_TPG_CORE_CFG_CMD,
 	CAM_ISP_HW_CMD_MAX,
 };
 

+ 1 - 0
drivers/cam_isp/isp_hw_mgr/isp_hw/top_tpg/cam_top_tpg103.h

@@ -112,6 +112,7 @@ static struct cam_top_tpg_ver3_reg_offset cam_top_tpg103_reg = {
 	.top_mux_reg_offset = 0x1C,
 	.tpg_vc_dt_pattern_id_shift = 6,
 	.tpg_num_active_vcs_shift = 30,
+	.tpg_color_bar_qcfa_en_shift = 3,
 };
 
 struct cam_top_tpg_hw_info cam_top_tpg103_hw_info = {

+ 2 - 0
drivers/cam_isp/isp_hw_mgr/isp_hw/top_tpg/cam_top_tpg_core.h

@@ -80,6 +80,7 @@ struct cam_top_tpg_dt_cfg {
  * @vbi_cnt:         vbi count
  * @num_active_dts:  number of active dts need to configure
  * @num_frames:      number of output frames
+ * @qcfa_en:         enable qcfa in color bar cfg
  * @dt_cfg:          dt configuration values
  *
  */
@@ -94,6 +95,7 @@ struct cam_top_tpg_cfg {
 	uint32_t                        num_active_dts;
 	uint32_t                        num_frames;
 	uint32_t                        vc_dt_pattern_id;
+	uint32_t                        qcfa_en;
 	struct cam_top_tpg_dt_cfg       dt_cfg[4];
 };
 

+ 51 - 3
drivers/cam_isp/isp_hw_mgr/isp_hw/top_tpg/cam_top_tpg_ver3.c

@@ -47,6 +47,52 @@ static int cam_top_tpg_ver3_get_hw_caps(
 	return rc;
 }
 
+static int cam_top_tpg_ver3_process_cmd(void *hw_priv,
+	uint32_t cmd_type, void *cmd_args, uint32_t arg_size)
+{
+	int                                     rc = 0;
+	struct cam_top_tpg_hw                  *tpg_hw;
+	struct cam_hw_info                     *tpg_hw_info;
+	struct cam_isp_tpg_core_config         *core_cfg;
+	struct cam_top_tpg_cfg                 *tpg_data;
+
+	if (!hw_priv || !cmd_args) {
+		CAM_ERR(CAM_ISP, "TPG: Invalid args");
+		return -EINVAL;
+	}
+
+	tpg_hw_info = (struct cam_hw_info *)hw_priv;
+	tpg_hw = (struct cam_top_tpg_hw *)tpg_hw_info->core_info;
+	tpg_data = (struct cam_top_tpg_cfg *)tpg_hw->tpg_res.res_priv;
+
+	switch (cmd_type) {
+	case CAM_ISP_HW_CMD_TPG_CORE_CFG_CMD:
+		if (arg_size != sizeof(struct cam_isp_tpg_core_config)) {
+			CAM_ERR(CAM_ISP, "Invalid size %u expected %u",
+				arg_size,
+				sizeof(struct cam_isp_tpg_core_config));
+			rc = -EINVAL;
+			break;
+		}
+
+		core_cfg = (struct cam_isp_tpg_core_config *)cmd_args;
+		tpg_data->pix_pattern = core_cfg->pix_pattern;
+		tpg_data->vc_dt_pattern_id = core_cfg->vc_dt_pattern_id;
+		tpg_data->qcfa_en = core_cfg->qcfa_en;
+		CAM_DBG(CAM_ISP,
+			"pattern_id: 0x%x pix_pattern: 0x%x qcfa_en: 0x%x",
+			tpg_data->vc_dt_pattern_id, tpg_data->pix_pattern,
+			tpg_data->qcfa_en);
+		break;
+	default:
+		CAM_ERR(CAM_ISP, "Invalid TPG cmd type %u", cmd_type);
+		rc = -EINVAL;
+		break;
+	}
+
+	return rc;
+}
+
 static int cam_top_tpg_ver3_reserve(
 	void                                         *hw_priv,
 	void                                         *reserve_args,
@@ -95,7 +141,7 @@ static int cam_top_tpg_ver3_reserve(
 	}
 
 	tpg_data = (struct cam_top_tpg_cfg *)tpg_hw->tpg_res.res_priv;
-
+	memset(tpg_data, 0, sizeof(*tpg_data));
 	for (i = 0; i < reserv->in_port->num_valid_vc_dt; i++) {
 		if (reserv->in_port->dt[i] > 0x3f ||
 			reserv->in_port->vc[i] > 0x1f) {
@@ -218,6 +264,8 @@ static int cam_top_tpg_ver3_start(
 
 		val = (1 << tpg_reg->tpg_split_en_shift);
 		val |= tpg_data->pix_pattern;
+		if (tpg_data->qcfa_en)
+			val |= (1 << tpg_reg->tpg_color_bar_qcfa_en_shift);
 		cam_io_w_mb(val, soc_info->reg_map[0].mem_base +
 			tpg_reg->tpg_vc0_color_bar_cfg + 0x60 * i);
 
@@ -236,7 +284,7 @@ static int cam_top_tpg_ver3_start(
 				tpg_reg->tpg_vc0_hbi_cfg + 0x60 * i);
 
 		if (tpg_data->v_blank_count)
-			cam_io_w_mb(tpg_data->h_blank_count,
+			cam_io_w_mb(tpg_data->v_blank_count,
 				soc_info->reg_map[0].mem_base +
 				tpg_reg->tpg_vc0_vbi_cfg + 0x60 * i);
 		else
@@ -340,6 +388,6 @@ int cam_top_tpg_ver3_init(
 	tpg_hw->hw_intf->hw_ops.reserve     = cam_top_tpg_ver3_reserve;
 	tpg_hw->hw_intf->hw_ops.start       = cam_top_tpg_ver3_start;
 	tpg_hw->hw_intf->hw_ops.stop        = cam_top_tpg_ver3_stop;
-
+	tpg_hw->hw_intf->hw_ops.process_cmd = cam_top_tpg_ver3_process_cmd;
 	return 0;
 }

+ 1 - 0
drivers/cam_isp/isp_hw_mgr/isp_hw/top_tpg/cam_top_tpg_ver3.h

@@ -111,6 +111,7 @@ struct cam_top_tpg_ver3_reg_offset {
 	uint32_t top_mux_reg_offset;
 	uint32_t tpg_vc_dt_pattern_id_shift;
 	uint32_t tpg_num_active_vcs_shift;
+	uint32_t tpg_color_bar_qcfa_en_shift;
 };
 
 int cam_top_tpg_ver3_init(struct cam_top_tpg_hw *tpg_hw);