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

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

Merge "msm: camera: icp: shut down icp clk when needed" into dev/msm-4.9-camx

parents b985c434 bc37c56e
Loading
Loading
Loading
Loading
+27 −2
Original line number Diff line number Diff line
@@ -93,6 +93,8 @@ int cam_bps_init_hw(void *device_priv,
			CAM_ERR(CAM_ICP, "cpas stop is failed");
		else
			core_info->cpas_start = false;
	} else {
		core_info->clk_enable = true;
	}

	return rc;
@@ -119,9 +121,10 @@ int cam_bps_deinit_hw(void *device_priv,
		return -EINVAL;
	}

	rc = cam_bps_disable_soc_resources(soc_info);
	rc = cam_bps_disable_soc_resources(soc_info, core_info->clk_enable);
	if (rc)
		CAM_ERR(CAM_ICP, "soc disable is failed: %d", rc);
	core_info->clk_enable = false;

	if (core_info->cpas_start) {
		if (cam_cpas_stop(core_info->cpas_handle))
@@ -276,9 +279,31 @@ int cam_bps_process_cmd(void *device_priv, uint32_t cmd_type,
		uint32_t clk_rate = *(uint32_t *)cmd_args;

		CAM_DBG(CAM_ICP, "bps_src_clk rate = %d", (int)clk_rate);
		if (!core_info->clk_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;
			rc = cam_bps_handle_resume(bps_dev);
			if (rc)
				CAM_ERR(CAM_ICP, "handle resume failed");
		}
		CAM_DBG(CAM_ICP, "clock rate %d", clk_rate);
		rc = cam_bps_update_clk_rate(soc_info, clk_rate);
		if (rc)
			CAM_ERR(CAM_ICP, "Failed to update clk");
		}
		break;
	case CAM_ICP_BPS_CMD_DISABLE_CLK:
		if (core_info->clk_enable == true)
			cam_bps_toggle_clk(soc_info, false);
		core_info->clk_enable = false;
		break;
	default:
		break;
	}
+1 −0
Original line number Diff line number Diff line
@@ -33,6 +33,7 @@ struct cam_bps_device_core_info {
	struct cam_bps_device_hw_info *bps_hw_info;
	uint32_t cpas_handle;
	bool cpas_start;
	bool clk_enable;
};

int cam_bps_init_hw(void *device_priv,
+16 −2
Original line number Diff line number Diff line
@@ -72,11 +72,13 @@ int cam_bps_enable_soc_resources(struct cam_hw_soc_info *soc_info)
	return rc;
}

int cam_bps_disable_soc_resources(struct cam_hw_soc_info *soc_info)
int cam_bps_disable_soc_resources(struct cam_hw_soc_info *soc_info,
	bool disable_clk)
{
	int rc = 0;

	rc = cam_soc_util_disable_platform_resource(soc_info, true, false);
	rc = cam_soc_util_disable_platform_resource(soc_info, disable_clk,
		false);
	if (rc)
		CAM_ERR(CAM_ICP, "disable platform failed");

@@ -142,3 +144,15 @@ int cam_bps_update_clk_rate(struct cam_hw_soc_info *soc_info,
	return cam_soc_util_set_clk_rate(soc_info->clk[soc_info->src_clk_idx],
		soc_info->clk_name[soc_info->src_clk_idx], clk_rate);
}

int cam_bps_toggle_clk(struct cam_hw_soc_info *soc_info, bool clk_enable)
{
	int rc = 0;

	if (clk_enable)
		rc = cam_soc_util_clk_enable_default(soc_info, CAM_SVS_VOTE);
	else
		cam_soc_util_clk_disable_default(soc_info);

	return rc;
}
+3 −1
Original line number Diff line number Diff line
@@ -20,7 +20,8 @@ int cam_bps_init_soc_resources(struct cam_hw_soc_info *soc_info,

int cam_bps_enable_soc_resources(struct cam_hw_soc_info *soc_info);

int cam_bps_disable_soc_resources(struct cam_hw_soc_info *soc_info);
int cam_bps_disable_soc_resources(struct cam_hw_soc_info *soc_info,
	bool disable_clk);

int cam_bps_get_gdsc_control(struct cam_hw_soc_info *soc_info);

@@ -28,4 +29,5 @@ int cam_bps_transfer_gdsc_control(struct cam_hw_soc_info *soc_info);

int cam_bps_update_clk_rate(struct cam_hw_soc_info *soc_info,
	uint32_t clk_rate);
int cam_bps_toggle_clk(struct cam_hw_soc_info *soc_info, bool clk_enable);
#endif /* _CAM_BPS_SOC_H_*/
+143 −10
Original line number Diff line number Diff line
@@ -53,6 +53,9 @@
#define ICP_WORKQ_TASK_CMD_TYPE 1
#define ICP_WORKQ_TASK_MSG_TYPE 2

#define ICP_DEV_TYPE_TO_CLK_TYPE(dev_type) \
	((dev_type == CAM_ICP_RES_TYPE_BPS) ? ICP_CLK_HW_BPS : ICP_CLK_HW_IPE)

static struct cam_icp_hw_mgr icp_hw_mgr;

static int cam_icp_send_ubwc_cfg(struct cam_icp_hw_mgr *hw_mgr)
@@ -225,6 +228,104 @@ static int cam_icp_clk_idx_from_req_id(struct cam_icp_hw_ctx_data *ctx_data,
	return 0;
}

static int cam_icp_ctx_clk_info_init(struct cam_icp_hw_ctx_data *ctx_data)
{
	ctx_data->clk_info.curr_fc = 0;
	ctx_data->clk_info.base_clk = 0;
	ctx_data->clk_info.uncompressed_bw = 0;
	ctx_data->clk_info.compressed_bw = 0;
	cam_icp_supported_clk_rates(&icp_hw_mgr, ctx_data);

	return 0;
}

static int32_t cam_icp_deinit_idle_clk(void *priv, void *data)
{
	struct cam_icp_hw_mgr *hw_mgr = (struct cam_icp_hw_mgr *)priv;
	struct clk_work_data *task_data = (struct clk_work_data *)data;
	struct cam_icp_clk_info *clk_info =
		(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;

	ipe0_dev_intf = hw_mgr->devices[CAM_ICP_DEV_IPE][0];
	ipe1_dev_intf = hw_mgr->devices[CAM_ICP_DEV_IPE][1];
	bps_dev_intf = hw_mgr->devices[CAM_ICP_DEV_BPS][0];

	clk_info->base_clk = 0;
	clk_info->curr_clk = 0;
	clk_info->over_clked = 0;

	for (i = 0; i < CAM_ICP_CTX_MAX; i++) {
		ctx_data = &hw_mgr->ctx_data[i];
		mutex_lock(&ctx_data->ctx_mutex);
		if ((ctx_data->state != CAM_ICP_CTX_STATE_FREE) &&
			(ICP_DEV_TYPE_TO_CLK_TYPE(ctx_data->
			icp_dev_acquire_info->dev_type) == clk_info->hw_type))
			cam_icp_ctx_clk_info_init(ctx_data);
		mutex_unlock(&ctx_data->ctx_mutex);
	}

	if ((!ipe0_dev_intf) || (!bps_dev_intf)) {
		CAM_ERR(CAM_ICP, "dev intfs are wrong, failed to update clk");
		return -EINVAL;
	}

	if (clk_info->hw_type == ICP_CLK_HW_BPS) {
		dev_intf = bps_dev_intf;
		id = CAM_ICP_BPS_CMD_DISABLE_CLK;
	} else if (clk_info->hw_type == ICP_CLK_HW_IPE) {
		dev_intf = ipe0_dev_intf;
		id = CAM_ICP_IPE_CMD_DISABLE_CLK;
	} else {
		CAM_ERR(CAM_ICP, "Error");
		return 0;
	}

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

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

	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));

	return 0;
}

static void cam_icp_timer_cb(unsigned long data)
{
	unsigned long flags;
	struct crm_workq_task *task;
	struct clk_work_data *task_data;
	struct cam_req_mgr_timer *timer = (struct cam_req_mgr_timer *)data;

	spin_lock_irqsave(&icp_hw_mgr.hw_mgr_lock, flags);
	task = cam_req_mgr_workq_get_task(icp_hw_mgr.msg_work);
	if (!task) {
		CAM_ERR(CAM_ICP, "no empty task");
		spin_unlock_irqrestore(&icp_hw_mgr.hw_mgr_lock, flags);
		return;
	}

	task_data = (struct clk_work_data *)task->payload;
	task_data->data = timer->parent;
	task_data->type = ICP_WORKQ_TASK_MSG_TYPE;
	task->process_cb = cam_icp_deinit_idle_clk;
	cam_req_mgr_workq_enqueue_task(task, &icp_hw_mgr,
		CRM_TASK_PRIORITY_0);
	spin_unlock_irqrestore(&icp_hw_mgr.hw_mgr_lock, flags);
}

static int cam_icp_clk_info_init(struct cam_icp_hw_mgr *hw_mgr,
	struct cam_icp_hw_ctx_data *ctx_data)
{
@@ -237,21 +338,36 @@ static int cam_icp_clk_info_init(struct cam_icp_hw_mgr *hw_mgr,
		hw_mgr->clk_info[i].over_clked = 0;
		hw_mgr->clk_info[i].uncompressed_bw = CAM_CPAS_DEFAULT_AXI_BW;
		hw_mgr->clk_info[i].compressed_bw = CAM_CPAS_DEFAULT_AXI_BW;
		hw_mgr->clk_info[i].hw_type = i;
	}
	hw_mgr->icp_default_clk = ICP_CLK_SVS_HZ;

	return 0;
}

static int cam_icp_ctx_clk_info_init(struct cam_icp_hw_ctx_data *ctx_data)
static int cam_icp_timer_start(struct cam_icp_hw_mgr *hw_mgr)
{
	ctx_data->clk_info.curr_fc = 0;
	ctx_data->clk_info.base_clk = 0;
	ctx_data->clk_info.uncompressed_bw = 0;
	ctx_data->clk_info.compressed_bw = 0;
	cam_icp_supported_clk_rates(&icp_hw_mgr, ctx_data);
	int rc = 0;
	int i;

	return 0;
	for (i = 0; i < ICP_CLK_HW_MAX; i++)  {
		if (!hw_mgr->clk_info[i].watch_dog) {
			rc = crm_timer_init(&hw_mgr->clk_info[i].watch_dog,
				3000, &hw_mgr->clk_info[i], &cam_icp_timer_cb);
			if (rc)
				CAM_ERR(CAM_ICP, "Failed to start timer %d", i);
		}
	}

	return rc;
}

static void cam_icp_timer_stop(struct cam_icp_hw_mgr *hw_mgr)
{
	if (!hw_mgr->bps_ctxt_cnt)
		crm_timer_exit(&hw_mgr->clk_info[ICP_CLK_HW_BPS].watch_dog);
	else if (!hw_mgr->ipe_ctxt_cnt)
		crm_timer_exit(&hw_mgr->clk_info[ICP_CLK_HW_IPE].watch_dog);
}

static uint32_t cam_icp_mgr_calc_base_clk(uint32_t frame_cycles,
@@ -335,7 +451,6 @@ static bool cam_icp_update_clk_busy(struct cam_icp_hw_mgr *hw_mgr,
	 *      no need to update the clock
	 */
	mutex_lock(&hw_mgr->hw_mgr_mutex);
	ctx_data->clk_info.curr_fc = clk_info->frame_cycles;
	ctx_data->clk_info.base_clk = base_clk;
	hw_mgr_clk_info->over_clked = 0;
	if (clk_info->frame_cycles > ctx_data->clk_info.curr_fc) {
@@ -360,6 +475,7 @@ static bool cam_icp_update_clk_busy(struct cam_icp_hw_mgr *hw_mgr,
			rc = true;
		}
	}
	ctx_data->clk_info.curr_fc = clk_info->frame_cycles;
	mutex_unlock(&hw_mgr->hw_mgr_mutex);

	return rc;
@@ -552,10 +668,15 @@ static bool cam_icp_check_clk_update(struct cam_icp_hw_mgr *hw_mgr,
	uint64_t req_id;
	struct cam_icp_clk_info *hw_mgr_clk_info;

	if (ctx_data->icp_dev_acquire_info->dev_type == CAM_ICP_RES_TYPE_BPS)
	if (ctx_data->icp_dev_acquire_info->dev_type == CAM_ICP_RES_TYPE_BPS) {
		crm_timer_reset(hw_mgr->clk_info[ICP_CLK_HW_BPS].watch_dog);
		hw_mgr_clk_info = &hw_mgr->clk_info[ICP_CLK_HW_BPS];
	else
		CAM_DBG(CAM_ICP, "Reset bps timer");
	} else {
		crm_timer_reset(hw_mgr->clk_info[ICP_CLK_HW_IPE].watch_dog);
		hw_mgr_clk_info = &hw_mgr->clk_info[ICP_CLK_HW_IPE];
		CAM_DBG(CAM_ICP, "Reset ipe timer");
	}

	if (icp_hw_mgr.icp_debug_clk)
		return cam_icp_debug_clk_update(hw_mgr_clk_info);
@@ -1009,6 +1130,7 @@ static int cam_icp_mgr_handle_frame_process(uint32_t *msg_ptr, int flag)
	struct hfi_msg_ipebps_async_ack *ioconfig_ack = NULL;
	struct hfi_frame_process_info *hfi_frame_process;
	struct cam_hw_done_event_data buf_data;
	uint32_t clk_type;

	ioconfig_ack = (struct hfi_msg_ipebps_async_ack *)msg_ptr;
	request_id = ioconfig_ack->user_data2;
@@ -1020,6 +1142,10 @@ static int cam_icp_mgr_handle_frame_process(uint32_t *msg_ptr, int flag)
	CAM_DBG(CAM_ICP, "ctx : %pK, request_id :%lld",
		(void *)ctx_data->context_priv, request_id);

	clk_type = ICP_DEV_TYPE_TO_CLK_TYPE(ctx_data->icp_dev_acquire_info->
		dev_type);
	crm_timer_reset(icp_hw_mgr.clk_info[clk_type].watch_dog);

	mutex_lock(&ctx_data->ctx_mutex);
	if (ctx_data->state != CAM_ICP_CTX_STATE_ACQUIRED) {
		mutex_unlock(&ctx_data->ctx_mutex);
@@ -2754,6 +2880,9 @@ static int cam_icp_mgr_release_hw(void *hw_mgr_priv, void *release_hw_args)
	}
	mutex_unlock(&hw_mgr->hw_mgr_mutex);

	if (!hw_mgr->bps_ctxt_cnt || !hw_mgr->ipe_ctxt_cnt)
		cam_icp_timer_stop(hw_mgr);

	return rc;
}

@@ -3043,6 +3172,10 @@ static int cam_icp_mgr_acquire_hw(void *hw_mgr_priv, void *acquire_hw_args)
			goto ubwc_cfg_failed;
		}
	}

	if (!hw_mgr->bps_ctxt_cnt || !hw_mgr->ipe_ctxt_cnt)
		cam_icp_timer_start(hw_mgr);

	rc = cam_icp_mgr_ipe_bps_resume(hw_mgr, ctx_data);
	if (rc) {
		mutex_unlock(&hw_mgr->hw_mgr_mutex);
Loading