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

Commit 1aef7b50 authored by Alok Pandey's avatar Alok Pandey Committed by Karthik Anantha Ram
Browse files

msm: camera: icp: Featurize ICP, IPE, BPS power collapse



Add provision to dynamically enable/disable ipe & bps power
collapse. By default, interframe power collapse is enabled.
To disable power collapse use the following cmds

ICP PC:
adb shell "echo 0 > /sys/kernel/debug/camera_icp/icp_pc"

InterFrame PC:
adb shell "echo 0 > /sys/kernel/debug/camera_icp/ipe_bps_pc"

Change-Id: I7658efad8a6d2ce601ea2297bdc086c9386cd28c
Signed-off-by: default avatarKarthik Anantha Ram <kartanan@codeaurora.org>
Signed-off-by: default avatarAlok Pandey <akumarpa@codeaurora.org>
parent 6479e0e4
Loading
Loading
Loading
Loading
+15 −8
Original line number Diff line number Diff line
@@ -276,22 +276,29 @@ int cam_bps_process_cmd(void *device_priv, uint32_t cmd_type,
		rc = cam_bps_handle_resume(bps_dev);
		break;
	case CAM_ICP_BPS_CMD_UPDATE_CLK: {
		uint32_t clk_rate = *(uint32_t *)cmd_args;
		struct cam_a5_clk_update_cmd *clk_upd_cmd =
			(struct cam_a5_clk_update_cmd *)cmd_args;
		uint32_t clk_rate = clk_upd_cmd->curr_clk_rate;

		CAM_DBG(CAM_ICP, "bps_src_clk rate = %d", (int)clk_rate);

		if (!core_info->clk_enable) {
			if (clk_upd_cmd->ipe_bps_pc_enable) {
				cam_bps_handle_pc(bps_dev);
				cam_cpas_reg_write(core_info->cpas_handle,
					CAM_CPAS_REG_CPASTOP,
					hw_info->pwr_ctrl, true, 0x0);
			}
			rc = cam_bps_toggle_clk(soc_info, true);
			if (rc)
				CAM_ERR(CAM_ICP, "Enable failed");
			else
				core_info->clk_enable = true;
			if (clk_upd_cmd->ipe_bps_pc_enable) {
				rc = cam_bps_handle_resume(bps_dev);
				if (rc)
				CAM_ERR(CAM_ICP, "handle resume failed");
					CAM_ERR(CAM_ICP, "BPS resume failed");
			}
		}
		CAM_DBG(CAM_ICP, "clock rate %d", clk_rate);
		rc = cam_bps_update_clk_rate(soc_info, clk_rate);
+91 −45
Original line number Diff line number Diff line
@@ -247,12 +247,12 @@ static int32_t cam_icp_deinit_idle_clk(void *priv, void *data)
		(struct cam_icp_clk_info *)task_data->data;
	uint32_t id;
	uint32_t i;
	uint32_t curr_clk_rate;
	struct cam_icp_hw_ctx_data *ctx_data;
	struct cam_hw_intf *ipe0_dev_intf = NULL;
	struct cam_hw_intf *ipe1_dev_intf = NULL;
	struct cam_hw_intf *bps_dev_intf = NULL;
	struct cam_hw_intf *dev_intf = NULL;
	struct cam_a5_clk_update_cmd clk_upd_cmd;

	ipe0_dev_intf = hw_mgr->devices[CAM_ICP_DEV_IPE][0];
	ipe1_dev_intf = hw_mgr->devices[CAM_ICP_DEV_IPE][1];
@@ -290,14 +290,17 @@ static int32_t cam_icp_deinit_idle_clk(void *priv, void *data)

	CAM_DBG(CAM_ICP, "Disable %d", clk_info->hw_type);

	clk_upd_cmd.ipe_bps_pc_enable = icp_hw_mgr.ipe_bps_pc_flag;

	dev_intf->hw_ops.process_cmd(dev_intf->hw_priv, id,
		&curr_clk_rate, sizeof(curr_clk_rate));
		&clk_upd_cmd, sizeof(struct cam_a5_clk_update_cmd));

	if (clk_info->hw_type != ICP_CLK_HW_BPS)
		if (ipe1_dev_intf)
			ipe1_dev_intf->hw_ops.process_cmd(
				ipe1_dev_intf->hw_priv, id,
				&curr_clk_rate, sizeof(curr_clk_rate));
				&clk_upd_cmd,
				sizeof(struct cam_a5_clk_update_cmd));

	return 0;
}
@@ -747,6 +750,7 @@ static int cam_icp_update_clk_rate(struct cam_icp_hw_mgr *hw_mgr,
	struct cam_hw_intf *ipe1_dev_intf = NULL;
	struct cam_hw_intf *bps_dev_intf = NULL;
	struct cam_hw_intf *dev_intf = NULL;
	struct cam_a5_clk_update_cmd clk_upd_cmd;

	ipe0_dev_intf = hw_mgr->ipe0_dev_intf;
	ipe1_dev_intf = hw_mgr->ipe1_dev_intf;
@@ -768,14 +772,18 @@ static int cam_icp_update_clk_rate(struct cam_icp_hw_mgr *hw_mgr,
		id = CAM_ICP_IPE_CMD_UPDATE_CLK;
	}

	clk_upd_cmd.curr_clk_rate = curr_clk_rate;
	clk_upd_cmd.ipe_bps_pc_enable = icp_hw_mgr.ipe_bps_pc_flag;

	dev_intf->hw_ops.process_cmd(dev_intf->hw_priv, id,
		&curr_clk_rate, sizeof(curr_clk_rate));
		&clk_upd_cmd, sizeof(struct cam_a5_clk_update_cmd));

	if (ctx_data->icp_dev_acquire_info->dev_type != CAM_ICP_RES_TYPE_BPS)
		if (ipe1_dev_intf)
			ipe1_dev_intf->hw_ops.process_cmd(
				ipe1_dev_intf->hw_priv, id,
				&curr_clk_rate, sizeof(curr_clk_rate));
				&clk_upd_cmd,
				sizeof(struct cam_a5_clk_update_cmd));

	return 0;
}
@@ -863,7 +871,7 @@ static int cam_icp_mgr_ipe_bps_resume(struct cam_icp_hw_mgr *hw_mgr,
		if (hw_mgr->bps_ctxt_cnt++)
			goto end;
		bps_dev_intf->hw_ops.init(bps_dev_intf->hw_priv, NULL, 0);
		if (icp_hw_mgr.icp_pc_flag) {
		if (icp_hw_mgr.ipe_bps_pc_flag) {
			bps_dev_intf->hw_ops.process_cmd(
				bps_dev_intf->hw_priv,
				CAM_ICP_BPS_CMD_POWER_RESUME, NULL, 0);
@@ -874,7 +882,7 @@ static int cam_icp_mgr_ipe_bps_resume(struct cam_icp_hw_mgr *hw_mgr,
			goto end;

		ipe0_dev_intf->hw_ops.init(ipe0_dev_intf->hw_priv, NULL, 0);
		if (icp_hw_mgr.icp_pc_flag) {
		if (icp_hw_mgr.ipe_bps_pc_flag) {
			ipe0_dev_intf->hw_ops.process_cmd(
				ipe0_dev_intf->hw_priv,
				CAM_ICP_IPE_CMD_POWER_RESUME, NULL, 0);
@@ -884,21 +892,21 @@ static int cam_icp_mgr_ipe_bps_resume(struct cam_icp_hw_mgr *hw_mgr,
			ipe1_dev_intf->hw_ops.init(ipe1_dev_intf->hw_priv,
				NULL, 0);

			if (icp_hw_mgr.icp_pc_flag) {
			if (icp_hw_mgr.ipe_bps_pc_flag) {
				ipe1_dev_intf->hw_ops.process_cmd(
					ipe1_dev_intf->hw_priv,
					CAM_ICP_IPE_CMD_POWER_RESUME,
					NULL, 0);
			}
		}
		if (icp_hw_mgr.icp_pc_flag) {
		if (icp_hw_mgr.ipe_bps_pc_flag) {
			hw_mgr->core_info = hw_mgr->core_info |
				(ICP_PWR_CLP_IPE0 | ICP_PWR_CLP_IPE1);
		}
	}

	CAM_DBG(CAM_ICP, "core_info %X",  hw_mgr->core_info);
	if (icp_hw_mgr.icp_pc_flag)
	if (icp_hw_mgr.ipe_bps_pc_flag)
		rc = hfi_enable_ipe_bps_pc(true, hw_mgr->core_info);
	else
		rc = hfi_enable_ipe_bps_pc(false, hw_mgr->core_info);
@@ -936,7 +944,7 @@ static int cam_icp_mgr_ipe_bps_power_collapse(struct cam_icp_hw_mgr *hw_mgr,
		if (hw_mgr->bps_ctxt_cnt)
			goto end;

		if (icp_hw_mgr.icp_pc_flag) {
		if (icp_hw_mgr.ipe_bps_pc_flag) {
			rc = bps_dev_intf->hw_ops.process_cmd(
				bps_dev_intf->hw_priv,
				CAM_ICP_BPS_CMD_POWER_COLLAPSE,
@@ -954,7 +962,7 @@ static int cam_icp_mgr_ipe_bps_power_collapse(struct cam_icp_hw_mgr *hw_mgr,
		if (hw_mgr->ipe_ctxt_cnt)
			goto end;

		if (icp_hw_mgr.icp_pc_flag) {
		if (icp_hw_mgr.ipe_bps_pc_flag) {
			rc = ipe0_dev_intf->hw_ops.process_cmd(
				ipe0_dev_intf->hw_priv,
				CAM_ICP_IPE_CMD_POWER_COLLAPSE, NULL, 0);
@@ -963,7 +971,7 @@ static int cam_icp_mgr_ipe_bps_power_collapse(struct cam_icp_hw_mgr *hw_mgr,
		ipe0_dev_intf->hw_ops.deinit(ipe0_dev_intf->hw_priv, NULL, 0);

		if (ipe1_dev_intf) {
			if (icp_hw_mgr.icp_pc_flag) {
			if (icp_hw_mgr.ipe_bps_pc_flag) {
				rc = ipe1_dev_intf->hw_ops.process_cmd(
					ipe1_dev_intf->hw_priv,
					CAM_ICP_IPE_CMD_POWER_COLLAPSE,
@@ -973,7 +981,7 @@ static int cam_icp_mgr_ipe_bps_power_collapse(struct cam_icp_hw_mgr *hw_mgr,
			ipe1_dev_intf->hw_ops.deinit(ipe1_dev_intf->hw_priv,
				NULL, 0);
		}
		if (icp_hw_mgr.icp_pc_flag) {
		if (icp_hw_mgr.ipe_bps_pc_flag) {
			hw_mgr->core_info = hw_mgr->core_info &
				(~(ICP_PWR_CLP_IPE0 | ICP_PWR_CLP_IPE1));
		}
@@ -1031,7 +1039,18 @@ static int cam_icp_hw_mgr_create_debugfs_entry(void)
		rc = -ENOMEM;
		goto err;
	}
	icp_hw_mgr.icp_pc_flag = 1;
	icp_hw_mgr.icp_pc_flag = false;

	if (!debugfs_create_bool("ipe_bps_pc",
		0644,
		icp_hw_mgr.dentry,
		&icp_hw_mgr.ipe_bps_pc_flag)) {
		CAM_ERR(CAM_ICP, "failed to create ipe_bps_pc entry");
		rc = -ENOMEM;
		goto err;
	}

	icp_hw_mgr.ipe_bps_pc_flag = false;

	if (!debugfs_create_file("icp_debug_clk",
		0644,
@@ -1814,6 +1833,9 @@ static int cam_icp_mgr_icp_power_collapse(struct cam_icp_hw_mgr *hw_mgr)
	}
	a5_dev = (struct cam_hw_info *)a5_dev_intf->hw_priv;

	if (!hw_mgr->icp_pc_flag)
		rc = cam_icp_mgr_hw_close(hw_mgr, NULL);
	else
		rc = cam_icp_mgr_send_pc_prep(hw_mgr);

	cam_hfi_disable_cpu(a5_dev->soc_info.reg_map[A5_SIERRA_BASE].mem_base);
@@ -1871,33 +1893,6 @@ static int cam_icp_mgr_hfi_resume(struct cam_icp_hw_mgr *hw_mgr)
		hw_mgr->a5_jtag_debug);
}

static int cam_icp_mgr_icp_resume(struct cam_icp_hw_mgr *hw_mgr)
{
	int rc = 0;
	struct cam_hw_intf *a5_dev_intf = NULL;

	CAM_DBG(CAM_ICP, "Enter");
	a5_dev_intf = hw_mgr->a5_dev_intf;

	if (!a5_dev_intf) {
		CAM_ERR(CAM_ICP, "a5 dev intf is wrong");
		return -EINVAL;
	}

	rc = a5_dev_intf->hw_ops.init(a5_dev_intf->hw_priv, NULL, 0);
	if (rc)
		return -EINVAL;

	rc = cam_icp_mgr_hfi_resume(hw_mgr);
	if (rc)
		goto hfi_resume_failed;

	CAM_DBG(CAM_ICP, "Exit");
	return rc;
hfi_resume_failed:
	cam_icp_mgr_icp_power_collapse(hw_mgr);
	return rc;
}
static int cam_icp_mgr_abort_handle(
	struct cam_icp_hw_ctx_data *ctx_data)
{
@@ -2145,6 +2140,7 @@ static int cam_icp_mgr_hw_close(void *hw_priv, void *hw_close_args)
	hw_mgr->secure_mode = CAM_SECURE_MODE_NON_SECURE;
	mutex_unlock(&hw_mgr->hw_mgr_mutex);

	CAM_DBG(CAM_ICP, "Exit");
	return rc;
}

@@ -2321,11 +2317,50 @@ static int cam_icp_mgr_send_fw_init(struct cam_icp_hw_mgr *hw_mgr)
	return rc;
}

static int cam_icp_mgr_icp_resume(struct cam_icp_hw_mgr *hw_mgr)
{
	int rc = 0;
	struct cam_hw_intf *a5_dev_intf = NULL;
	bool downloadFromResume = true;

	CAM_DBG(CAM_ICP, "Enter");
	a5_dev_intf = hw_mgr->devices[CAM_ICP_DEV_A5][0];

	if (!a5_dev_intf) {
		CAM_ERR(CAM_ICP, "a5 dev intf is wrong");
		return -EINVAL;
	}

	if (hw_mgr->fw_download  == false) {
		CAM_DBG(CAM_ICP, "Downloading FW");
		mutex_unlock(&hw_mgr->hw_mgr_mutex);
		cam_icp_mgr_hw_open(hw_mgr, &downloadFromResume);
		mutex_lock(&hw_mgr->hw_mgr_mutex);
		CAM_DBG(CAM_ICP, "FW Download Done Exit");
		return 0;
	}

	rc = a5_dev_intf->hw_ops.init(a5_dev_intf->hw_priv, NULL, 0);
	if (rc)
		return -EINVAL;

	rc = cam_icp_mgr_hfi_resume(hw_mgr);
	if (rc)
		goto hfi_resume_failed;

	CAM_DBG(CAM_ICP, "Exit");
	return rc;
hfi_resume_failed:
	cam_icp_mgr_icp_power_collapse(hw_mgr);
	return rc;
}

static int cam_icp_mgr_hw_open(void *hw_mgr_priv, void *download_fw_args)
{
	struct cam_hw_intf *a5_dev_intf = NULL;
	struct cam_hw_info *a5_dev = NULL;
	struct cam_icp_hw_mgr *hw_mgr = hw_mgr_priv;
	bool icp_pc = false;
	int rc = 0;

	if (!hw_mgr) {
@@ -2378,17 +2413,23 @@ static int cam_icp_mgr_hw_open(void *hw_mgr_priv, void *download_fw_args)
	}

	hw_mgr->ctxt_cnt = 0;
	hw_mgr->fw_download = true;

	if (icp_hw_mgr.a5_debug_q)
		hfi_set_debug_level(icp_hw_mgr.a5_dbg_lvl);

	mutex_unlock(&hw_mgr->hw_mgr_mutex);
	CAM_INFO(CAM_ICP, "FW download done successfully");

	rc = cam_ipe_bps_deint(hw_mgr);
	if (download_fw_args)
		icp_pc = *((bool *)download_fw_args);

	if (download_fw_args && icp_pc == true)
		return rc;

	rc = cam_icp_mgr_icp_power_collapse(hw_mgr);

	hw_mgr->fw_download = true;
	CAM_DBG(CAM_ICP, "FW download done successfully");
	return rc;

fw_init_failed:
@@ -3025,6 +3066,7 @@ static int cam_icp_mgr_release_hw(void *hw_mgr_priv, void *release_hw_args)
		return -EINVAL;
	}

	CAM_DBG(CAM_ICP, "Enter");
	ctx_data = release_hw->ctxt_to_hw_map;
	if (!ctx_data) {
		CAM_ERR(CAM_ICP, "NULL ctx data");
@@ -3054,7 +3096,9 @@ static int cam_icp_mgr_release_hw(void *hw_mgr_priv, void *release_hw_args)
	rc = cam_icp_mgr_release_ctx(hw_mgr, ctx_id);
	if (!hw_mgr->ctxt_cnt) {
		CAM_DBG(CAM_ICP, "Last Release");
		mutex_unlock(&hw_mgr->hw_mgr_mutex);
		cam_icp_mgr_icp_power_collapse(hw_mgr);
		mutex_lock(&hw_mgr->hw_mgr_mutex);
		cam_icp_hw_mgr_reset_clk_info(hw_mgr);
		hw_mgr->secure_mode = CAM_SECURE_MODE_NON_SECURE;
	}
@@ -3063,6 +3107,7 @@ static int cam_icp_mgr_release_hw(void *hw_mgr_priv, void *release_hw_args)
	if (!hw_mgr->bps_ctxt_cnt || !hw_mgr->ipe_ctxt_cnt)
		cam_icp_timer_stop(hw_mgr);

	CAM_DBG(CAM_ICP, "Exit");
	return rc;
}

@@ -3302,6 +3347,7 @@ static int cam_icp_mgr_acquire_hw(void *hw_mgr_priv, void *acquire_hw_args)
		return -EINVAL;
	}

	CAM_DBG(CAM_ICP, "ENTER");
	mutex_lock(&hw_mgr->hw_mgr_mutex);
	ctx_id = cam_icp_mgr_get_free_ctx(hw_mgr);
	if (ctx_id >= CAM_ICP_CTX_MAX) {
+3 −0
Original line number Diff line number Diff line
@@ -258,6 +258,8 @@ struct cam_icp_clk_info {
 * @dentry: Debugfs entry
 * @a5_debug: A5 debug flag
 * @icp_pc_flag: Flag to enable/disable power collapse
 * @ipe_bps_pc_flag: Flag to enable/disable
 *                   power collapse for ipe & bps
 * @icp_debug_clk: Set clock based on debug value
 * @icp_default_clk: Set this clok if user doesn't supply
 * @clk_info: Clock info of hardware
@@ -295,6 +297,7 @@ struct cam_icp_hw_mgr {
	struct dentry *dentry;
	bool a5_debug;
	bool icp_pc_flag;
	bool ipe_bps_pc_flag;
	uint64_t icp_debug_clk;
	uint64_t icp_default_clk;
	struct cam_icp_clk_info clk_info[ICP_CLK_HW_MAX];
+11 −0
Original line number Diff line number Diff line
@@ -22,4 +22,15 @@ enum cam_a5_hw_type {
	CAM_ICP_DEV_BPS,
	CAM_ICP_DEV_MAX,
};

/**
 * struct cam_a5_clk_update_cmd - Payload for hw manager command
 *
 * @curr_clk_rate:        clk rate to HW
 * @ipe_bps_pc_enable     power collpase enable flag
 */
struct cam_a5_clk_update_cmd {
	uint32_t  curr_clk_rate;
	bool  ipe_bps_pc_enable;
};
#endif
+14 −8
Original line number Diff line number Diff line
@@ -267,22 +267,28 @@ int cam_ipe_process_cmd(void *device_priv, uint32_t cmd_type,
		rc = cam_ipe_handle_resume(ipe_dev);
		break;
	case CAM_ICP_IPE_CMD_UPDATE_CLK: {
		uint32_t clk_rate = *(uint32_t *)cmd_args;
		struct cam_a5_clk_update_cmd *clk_upd_cmd =
			(struct cam_a5_clk_update_cmd *)cmd_args;
		uint32_t clk_rate = clk_upd_cmd->curr_clk_rate;

		CAM_DBG(CAM_ICP, "ipe_src_clk rate = %d", (int)clk_rate);
		if (!core_info->clk_enable) {
			if (clk_upd_cmd->ipe_bps_pc_enable) {
				cam_ipe_handle_pc(ipe_dev);
				cam_cpas_reg_write(core_info->cpas_handle,
					CAM_CPAS_REG_CPASTOP,
					hw_info->pwr_ctrl, true, 0x0);
			}
			rc = cam_ipe_toggle_clk(soc_info, true);
			if (rc)
				CAM_ERR(CAM_ICP, "Enable failed");
			else
				core_info->clk_enable = true;
			if (clk_upd_cmd->ipe_bps_pc_enable) {
				rc = cam_ipe_handle_resume(ipe_dev);
				if (rc)
				CAM_ERR(CAM_ICP, "handle resume failed");
					CAM_ERR(CAM_ICP, "bps resume failed");
			}
		}
		CAM_DBG(CAM_ICP, "clock rate %d", clk_rate);