Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 37746f3d authored by Jeyaprakash Soundrapandian's avatar Jeyaprakash Soundrapandian Committed by Gerrit - the friendly Code Review server
Browse files

Merge "msm: camera: isp: Add changes for dynamic clock/BW update" into dev/msm-4.9-camx

parents 902b826c 29102391
Loading
Loading
Loading
Loading
+186 −2
Original line number Diff line number Diff line
@@ -41,10 +41,12 @@
	(CAM_ISP_PACKET_META_GENERIC_BLOB_COMMON + 1)

#define CAM_ISP_GENERIC_BLOB_TYPE_MAX               \
	(CAM_ISP_GENERIC_BLOB_TYPE_HFR_CONFIG + 1)
	(CAM_ISP_GENERIC_BLOB_TYPE_BW_CONFIG + 1)

static uint32_t blob_type_hw_cmd_map[CAM_ISP_GENERIC_BLOB_TYPE_MAX] = {
	CAM_ISP_HW_CMD_GET_HFR_UPDATE,
	CAM_ISP_HW_CMD_CLOCK_UPDATE,
	CAM_ISP_HW_CMD_BW_UPDATE,
};

static struct cam_ife_hw_mgr g_ife_hw_mgr;
@@ -2109,6 +2111,168 @@ static int cam_isp_blob_hfr_update(
	return rc;
}

static int cam_isp_blob_clock_update(
	uint32_t                               blob_type,
	struct cam_isp_generic_blob_info      *blob_info,
	struct cam_isp_clock_config           *clock_config,
	struct cam_hw_prepare_update_args     *prepare)
{
	struct cam_ife_hw_mgr_ctx             *ctx = NULL;
	struct cam_ife_hw_mgr_res             *hw_mgr_res;
	struct cam_hw_intf                    *hw_intf;
	struct cam_vfe_clock_update_args       clock_upd_args;
	uint64_t                               clk_rate = 0;
	int                                    rc = -EINVAL;
	uint32_t                               i;
	uint32_t                               j;

	ctx = prepare->ctxt_to_hw_map;

	CAM_DBG(CAM_ISP,
		"usage=%u left_clk= %lu right_clk=%lu",
		clock_config->usage_type,
		clock_config->left_pix_hz,
		clock_config->right_pix_hz);

	list_for_each_entry(hw_mgr_res, &ctx->res_list_ife_src, list) {
		for (i = 0; i < CAM_ISP_HW_SPLIT_MAX; i++) {
			clk_rate = 0;
			if (!hw_mgr_res->hw_res[i])
				continue;

			if (hw_mgr_res->res_id == CAM_ISP_HW_VFE_IN_CAMIF)
				if (i == CAM_ISP_HW_SPLIT_LEFT)
					clk_rate =
						clock_config->left_pix_hz;
				else
					clk_rate =
						clock_config->right_pix_hz;
			else if ((hw_mgr_res->res_id >= CAM_ISP_HW_VFE_IN_RDI0)
					&& (hw_mgr_res->res_id <=
					CAM_ISP_HW_VFE_IN_RDI3))
				for (j = 0; j < clock_config->num_rdi; j++)
					clk_rate = max(clock_config->rdi_hz[j],
						clk_rate);
			else
				if (hw_mgr_res->hw_res[i]) {
					CAM_ERR(CAM_ISP, "Invalid res_id %u",
						hw_mgr_res->res_id);
					rc = -EINVAL;
					return rc;
				}

			hw_intf = hw_mgr_res->hw_res[i]->hw_intf;
			if (hw_intf && hw_intf->hw_ops.process_cmd) {
				clock_upd_args.node_res =
					hw_mgr_res->hw_res[i];
				CAM_DBG(CAM_ISP,
				"res_id=%u i= %d clk=%llu\n",
				hw_mgr_res->res_id, i, clk_rate);

				clock_upd_args.clk_rate = clk_rate;

				rc = hw_intf->hw_ops.process_cmd(
					hw_intf->hw_priv,
					CAM_ISP_HW_CMD_CLOCK_UPDATE,
					&clock_upd_args,
					sizeof(
					struct cam_vfe_clock_update_args));
				if (rc)
					CAM_ERR(CAM_ISP, "Clock Update failed");
			} else
				CAM_WARN(CAM_ISP, "NULL hw_intf!");
		}
	}

	return rc;
}

static int cam_isp_blob_bw_update(
	uint32_t                               blob_type,
	struct cam_isp_generic_blob_info      *blob_info,
	struct cam_isp_bw_config              *bw_config,
	struct cam_hw_prepare_update_args     *prepare)
{
	struct cam_ife_hw_mgr_ctx             *ctx = NULL;
	struct cam_ife_hw_mgr_res             *hw_mgr_res;
	struct cam_hw_intf                    *hw_intf;
	struct cam_vfe_bw_update_args          bw_upd_args;
	uint64_t                               cam_bw_bps = 0;
	uint64_t                               ext_bw_bps = 0;
	int                                    rc = -EINVAL;
	uint32_t                               i;

	ctx = prepare->ctxt_to_hw_map;

	CAM_DBG(CAM_ISP,
		"usage=%u left cam_bw_bps=%llu ext_bw_bps=%llu\n"
		"right cam_bw_bps=%llu ext_bw_bps=%llu",
		bw_config->usage_type,
		bw_config->left_pix_vote.cam_bw_bps,
		bw_config->left_pix_vote.ext_bw_bps,
		bw_config->right_pix_vote.cam_bw_bps,
		bw_config->right_pix_vote.ext_bw_bps);

	list_for_each_entry(hw_mgr_res, &ctx->res_list_ife_src, list) {
		for (i = 0; i < CAM_ISP_HW_SPLIT_MAX; i++) {
			if (!hw_mgr_res->hw_res[i])
				continue;

			if (hw_mgr_res->res_id == CAM_ISP_HW_VFE_IN_CAMIF)
				if (i == CAM_ISP_HW_SPLIT_LEFT) {
					cam_bw_bps =
					bw_config->left_pix_vote.cam_bw_bps;
					ext_bw_bps =
					bw_config->left_pix_vote.ext_bw_bps;
				} else {
					cam_bw_bps =
					bw_config->right_pix_vote.cam_bw_bps;
					ext_bw_bps =
					bw_config->right_pix_vote.ext_bw_bps;
				}
			else if ((hw_mgr_res->res_id >= CAM_ISP_HW_VFE_IN_RDI0)
						&& (hw_mgr_res->res_id <=
						CAM_ISP_HW_VFE_IN_RDI3)) {
				uint32_t idx = hw_mgr_res->res_id -
						CAM_ISP_HW_VFE_IN_RDI0;
				if (idx >= bw_config->num_rdi)
					continue;

				cam_bw_bps =
					bw_config->rdi_vote[idx].cam_bw_bps;
				ext_bw_bps =
					bw_config->rdi_vote[idx].ext_bw_bps;
			} else
				if (hw_mgr_res->hw_res[i]) {
					CAM_ERR(CAM_ISP, "Invalid res_id %u",
						hw_mgr_res->res_id);
					rc = -EINVAL;
					return rc;
				}

			hw_intf = hw_mgr_res->hw_res[i]->hw_intf;
			if (hw_intf && hw_intf->hw_ops.process_cmd) {
				bw_upd_args.node_res =
					hw_mgr_res->hw_res[i];

				bw_upd_args.camnoc_bw_bytes = cam_bw_bps;
				bw_upd_args.external_bw_bytes = ext_bw_bps;

				rc = hw_intf->hw_ops.process_cmd(
					hw_intf->hw_priv,
					CAM_ISP_HW_CMD_BW_UPDATE,
					&bw_upd_args,
					sizeof(struct cam_vfe_bw_update_args));
				if (rc)
					CAM_ERR(CAM_ISP, "BW Update failed");
			} else
				CAM_WARN(CAM_ISP, "NULL hw_intf!");
		}
	}

	return rc;
}

static int cam_isp_packet_generic_blob_handler(void *user_data,
	uint32_t blob_type, uint32_t blob_size, uint8_t *blob_data)
{
@@ -2146,6 +2310,26 @@ static int cam_isp_packet_generic_blob_handler(void *user_data,
			CAM_ERR(CAM_ISP, "HFR Update Failed");
	}
		break;
	case CAM_ISP_GENERIC_BLOB_TYPE_CLOCK_CONFIG: {
		struct cam_isp_clock_config    *clock_config =
			(struct cam_isp_clock_config *)blob_data;

		rc = cam_isp_blob_clock_update(blob_type, blob_info,
			clock_config, prepare);
		if (rc)
			CAM_ERR(CAM_ISP, "Clock Update Failed");
	}
		break;
	case CAM_ISP_GENERIC_BLOB_TYPE_BW_CONFIG: {
		struct cam_isp_bw_config    *bw_config =
			(struct cam_isp_bw_config *)blob_data;

		rc = cam_isp_blob_bw_update(blob_type, blob_info,
			bw_config, prepare);
		if (rc)
			CAM_ERR(CAM_ISP, "Bandwidth Update Failed");
	}
		break;
	default:
		CAM_WARN(CAM_ISP, "Invalid blob type %d", blob_type);
		break;
+4 −0
Original line number Diff line number Diff line
@@ -392,6 +392,7 @@ struct cam_ife_csid_cid_data {
 *                  for RDI, set  mode to none
 * @master_idx:     For Slave reservation, Give master IFE instance Index.
 *                  Slave will synchronize with master Start and stop operations
 * @clk_rate        Clock rate
 *
 */
struct cam_ife_csid_path_cfg {
@@ -409,6 +410,7 @@ struct cam_ife_csid_path_cfg {
	uint32_t                        height;
	enum cam_isp_hw_sync_mode       sync_mode;
	uint32_t                        master_idx;
	uint64_t                        clk_rate;
};

/**
@@ -432,6 +434,7 @@ struct cam_ife_csid_path_cfg {
 * @csid_rdin_reset_complete: rdi n completion
 * @csid_debug:               csid debug information to enable the SOT, EOT,
 *                            SOF, EOF, measure etc in the csid hw
 * @clk_rate                  Clock rate
 *
 */
struct cam_ife_csid_hw {
@@ -452,6 +455,7 @@ struct cam_ife_csid_hw {
	struct completion                csid_ipp_complete;
	struct completion    csid_rdin_complete[CAM_IFE_CSID_RDI_MAX];
	uint64_t                         csid_debug;
	uint64_t                         clk_rate;
};

int cam_ife_csid_hw_probe_init(struct cam_hw_intf  *csid_hw_intf,
+4 −0
Original line number Diff line number Diff line
@@ -90,6 +90,8 @@ enum cam_isp_hw_cmd_type {
	CAM_ISP_HW_CMD_GET_HFR_UPDATE,
	CAM_ISP_HW_CMD_GET_SECURE_MODE,
	CAM_ISP_HW_CMD_STRIPE_UPDATE,
	CAM_ISP_HW_CMD_CLOCK_UPDATE,
	CAM_ISP_HW_CMD_BW_UPDATE,
	CAM_ISP_HW_CMD_MAX,
};

@@ -192,6 +194,8 @@ struct cam_isp_hw_get_cmd_update {
		void                                 *data;
		struct cam_isp_hw_get_wm_update      *wm_update;
		struct cam_isp_port_hfr_config       *hfr_update;
		struct cam_isp_clock_config          *clock_update;
		struct cam_isp_bw_config             *bw_update;
	};
};

+25 −0
Original line number Diff line number Diff line
@@ -160,6 +160,31 @@ struct cam_vfe_acquire_args {
	};
};

/*
 * struct cam_vfe_clock_update_args:
 *
 * @node_res:                Resource to get the time stamp
 * @clk_rate:                Clock rate requested
 */
struct cam_vfe_clock_update_args {
	struct cam_isp_resource_node      *node_res;
	uint64_t                           clk_rate;
};

/*
 * struct cam_vfe_bw_update_args:
 *
 * @node_res:             Resource to get the time stamp
 * @camnoc_bw_bytes:      Bandwidth vote request for CAMNOC
 * @external_bw_bytes:    Bandwidth vote request from CAMNOC
 *                        out to the rest of the path-to-DDR
 */
struct cam_vfe_bw_update_args {
	struct cam_isp_resource_node      *node_res;
	uint64_t                           camnoc_bw_bytes;
	uint64_t                           external_bw_bytes;
};

/*
 * struct cam_vfe_top_irq_evt_payload:
 *
+5 −2
Original line number Diff line number Diff line
@@ -264,7 +264,9 @@ int cam_vfe_init_hw(void *hw_priv, void *init_hw_args, uint32_t arg_size)
		goto deinint_vfe_res;
	}

	return 0;
	vfe_hw->hw_state = CAM_HW_STATE_POWER_UP;
	return rc;

deinint_vfe_res:
	if (isp_res && isp_res->deinit)
		isp_res->deinit(isp_res, NULL, 0);
@@ -650,10 +652,11 @@ int cam_vfe_process_cmd(void *hw_priv, uint32_t cmd_type,
	switch (cmd_type) {
	case CAM_ISP_HW_CMD_GET_CHANGE_BASE:
	case CAM_ISP_HW_CMD_GET_REG_UPDATE:
	case CAM_ISP_HW_CMD_CLOCK_UPDATE:
	case CAM_ISP_HW_CMD_BW_UPDATE:
		rc = core_info->vfe_top->hw_ops.process_cmd(
			core_info->vfe_top->top_priv, cmd_type, cmd_args,
			arg_size);

		break;
	case CAM_ISP_HW_CMD_GET_BUF_UPDATE:
	case CAM_ISP_HW_CMD_GET_HFR_UPDATE:
Loading