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

Commit 5b9b4846 authored by Narendra Muppalla's avatar Narendra Muppalla
Browse files

drm/msm/sde: add support to scale data bus



Current driver has support to vote for only one
rate in the data bus. Add support to scale the
vote for the data bus.

Change-Id: I7fbef0437c7e6f0581275c4bb2c302b41f7918ef
Signed-off-by: default avatarIngrid Gallardo <ingridg@codeaurora.org>
Signed-off-by: default avatarNarendra Muppalla <NarendraM@codeaurora.org>
parent f6ea99ce
Loading
Loading
Loading
Loading
+76 −6
Original line number Diff line number Diff line
@@ -847,6 +847,68 @@ void sde_power_resource_deinit(struct platform_device *pdev,
		sde_rsc_client_destroy(phandle->rsc_client);
}


int sde_power_scale_reg_bus(struct sde_power_handle *phandle,
	struct sde_power_client *pclient, u32 usecase_ndx, bool skip_lock)
{
	struct sde_power_client *client;
	int rc = 0;
	u32 max_usecase_ndx = VOTE_INDEX_DISABLE;

	if (!skip_lock) {
		mutex_lock(&phandle->phandle_lock);

		if (WARN_ON(pclient->refcount == 0)) {
			/*
			 * This is not expected, clients calling without skip
			 * lock are outside the power resource enable, which
			 * means that they should have enabled the power
			 * resource before trying to scale.
			 */
			rc = -EINVAL;
			goto exit;
		}
	}

	pr_debug("%pS: current idx:%d requested:%d client:%d\n",
		__builtin_return_address(0), pclient->usecase_ndx,
		usecase_ndx, pclient->id);

	pclient->usecase_ndx = usecase_ndx;

	list_for_each_entry(client, &phandle->power_client_clist, list) {
		if (client->usecase_ndx < VOTE_INDEX_MAX &&
		    client->usecase_ndx > max_usecase_ndx)
			max_usecase_ndx = client->usecase_ndx;
	}

	rc = sde_power_reg_bus_update(phandle->reg_bus_hdl,
						max_usecase_ndx);
	if (rc)
		pr_err("failed to set reg bus vote rc=%d\n", rc);

exit:
	if (!skip_lock)
		mutex_unlock(&phandle->phandle_lock);

	return rc;
}

static inline bool _resource_changed(u32 current_usecase_ndx,
		u32 max_usecase_ndx)
{
	WARN_ON((current_usecase_ndx >= VOTE_INDEX_MAX)
		|| (max_usecase_ndx >= VOTE_INDEX_MAX));

	if (((current_usecase_ndx >= VOTE_INDEX_LOW) && /* enabled */
		(max_usecase_ndx == VOTE_INDEX_DISABLE)) || /* max disabled */
		((current_usecase_ndx == VOTE_INDEX_DISABLE) && /* disabled */
		(max_usecase_ndx >= VOTE_INDEX_LOW))) /* max enabled */
		return true;

	return false;
}

int sde_power_resource_enable(struct sde_power_handle *phandle,
	struct sde_power_client *pclient, bool enable)
{
@@ -880,7 +942,15 @@ int sde_power_resource_enable(struct sde_power_handle *phandle,
			max_usecase_ndx = client->usecase_ndx;
	}

	if (phandle->current_usecase_ndx != max_usecase_ndx) {
	/*
	 * Check if we need to enable/disable the power resource, we won't
	 * only-scale up/down the AHB vote in this API; if a client wants to
	 * bump up the AHB clock above the LOW (default) level, it needs to
	 * call 'sde_power_scale_reg_bus' with the desired vote after the power
	 * resource was enabled.
	 */
	if (_resource_changed(phandle->current_usecase_ndx,
			max_usecase_ndx)) {
		changed = true;
		prev_usecase_ndx = phandle->current_usecase_ndx;
		phandle->current_usecase_ndx = max_usecase_ndx;
@@ -916,8 +986,8 @@ int sde_power_resource_enable(struct sde_power_handle *phandle,
			goto vreg_err;
		}

		rc = sde_power_reg_bus_update(phandle->reg_bus_hdl,
							max_usecase_ndx);
		rc = sde_power_scale_reg_bus(phandle, pclient,
				max_usecase_ndx, true);
		if (rc) {
			pr_err("failed to set reg bus vote rc=%d\n", rc);
			goto reg_bus_hdl_err;
@@ -948,8 +1018,8 @@ int sde_power_resource_enable(struct sde_power_handle *phandle,

		msm_dss_enable_clk(mp->clk_config, mp->num_clk, enable);

		sde_power_reg_bus_update(phandle->reg_bus_hdl,
							max_usecase_ndx);
		sde_power_scale_reg_bus(phandle, pclient,
				max_usecase_ndx, true);

		msm_dss_enable_vreg(mp->vreg_config, mp->num_vreg, enable);

@@ -970,7 +1040,7 @@ int sde_power_resource_enable(struct sde_power_handle *phandle,
clk_err:
	sde_power_rsc_update(phandle, false);
rsc_err:
	sde_power_reg_bus_update(phandle->reg_bus_hdl, prev_usecase_ndx);
	sde_power_scale_reg_bus(phandle, pclient, max_usecase_ndx, true);
reg_bus_hdl_err:
	msm_dss_enable_vreg(mp->vreg_config, mp->num_vreg, 0);
vreg_err:
+17 −0
Original line number Diff line number Diff line
@@ -43,11 +43,15 @@
 * mdss_bus_vote_type: register bus vote type
 * VOTE_INDEX_DISABLE: removes the client vote
 * VOTE_INDEX_LOW: keeps the lowest vote for register bus
 * VOTE_INDEX_MEDIUM: keeps medium vote for register bus
 * VOTE_INDEX_HIGH: keeps the highest vote for register bus
 * VOTE_INDEX_MAX: invalid
 */
enum mdss_bus_vote_type {
	VOTE_INDEX_DISABLE,
	VOTE_INDEX_LOW,
	VOTE_INDEX_MEDIUM,
	VOTE_INDEX_HIGH,
	VOTE_INDEX_MAX,
};

@@ -227,6 +231,19 @@ void sde_power_client_destroy(struct sde_power_handle *phandle,
int sde_power_resource_enable(struct sde_power_handle *pdata,
	struct sde_power_client *pclient, bool enable);

/**
 * sde_power_scale_reg_bus() - Scale the registers bus for the specified client
 * @phandle:  power handle containing the resources
 * @pclient: client information to scale its vote
 * @usecase_ndx: new use case to scale the reg bus
 * @skip_lock: will skip holding the power rsrc mutex during the call, this is
 *		for internal callers that already hold this required lock.
 *
 * Return: error code.
 */
int sde_power_scale_reg_bus(struct sde_power_handle *phandle,
	struct sde_power_client *pclient, u32 usecase_ndx, bool skip_lock);

/**
 * sde_power_resource_is_enabled() - return true if power resource is enabled
 * @pdata:  power handle containing the resources