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

Commit b69a9475 authored by Kyle Yan's avatar Kyle Yan Committed by Gerrit - the friendly Code Review server
Browse files

Merge "drm/msm/sde: fix sde rsc state machine" into msm-4.9

parents fbee9ad6 a65b0f14
Loading
Loading
Loading
Loading
+88 −14
Original line number Diff line number Diff line
@@ -48,6 +48,8 @@
#define MAX_BUFFER_SIZE 256

#define TRY_CMD_MODE_SWITCH		0xFFFF
#define TRY_CLK_MODE_SWITCH		0xFFFE
#define STATE_UPDATE_NOT_ALLOWED	0xFFFD

static struct sde_rsc_priv *rsc_prv_list[MAX_RSC_COUNT];

@@ -237,24 +239,50 @@ static u32 sde_rsc_timer_calculate(struct sde_rsc_priv *rsc,
static int sde_rsc_switch_to_idle(struct sde_rsc_priv *rsc)
{
	struct sde_rsc_client *client;
	int rc = 0;
	int rc = STATE_UPDATE_NOT_ALLOWED;
	bool idle_switch = true;

	list_for_each_entry(client, &rsc->client_list, list)
		if (client->current_state != SDE_RSC_IDLE_STATE)
		if (client->current_state != SDE_RSC_IDLE_STATE) {
			idle_switch = false;
			break;
		}

	if (!idle_switch) {
		/**
		 * following code needs to run the loop through each
		 * client because they might be in different order
		 * sorting is not possible; only preference is available
		 */

		/* first check if any vid client active */
		list_for_each_entry(client, &rsc->client_list, list)
			if (client->current_state == SDE_RSC_VID_STATE)
				return rc;

		/* now try cmd state switch */
		list_for_each_entry(client, &rsc->client_list, list)
			if (client->current_state == SDE_RSC_CMD_STATE)
				return TRY_CMD_MODE_SWITCH;

	if (rsc->hw_ops.state_update)
		/* now try clk state switch */
		list_for_each_entry(client, &rsc->client_list, list)
			if (client->current_state == SDE_RSC_CLK_STATE)
				return TRY_CLK_MODE_SWITCH;

	} else if (rsc->hw_ops.state_update) {
		rc = rsc->hw_ops.state_update(rsc, SDE_RSC_IDLE_STATE);
	}

	return rc;
}

static bool sde_rsc_switch_to_cmd(struct sde_rsc_priv *rsc,
static int sde_rsc_switch_to_cmd(struct sde_rsc_priv *rsc,
	struct sde_rsc_cmd_config *config,
	struct sde_rsc_client *caller_client, bool wait_req)
{
	struct sde_rsc_client *client;
	int rc = 0;
	int rc = STATE_UPDATE_NOT_ALLOWED;

	if (!rsc->primary_client) {
		pr_err("primary client not available for cmd state switch\n");
@@ -276,6 +304,12 @@ static bool sde_rsc_switch_to_cmd(struct sde_rsc_priv *rsc,
		if (client->current_state == SDE_RSC_VID_STATE)
			goto end;

	/* no need to enable solver again */
	if (rsc->current_state == SDE_RSC_CLK_STATE) {
		rc = 0;
		goto end;
	}

	if (rsc->hw_ops.state_update)
		rc = rsc->hw_ops.state_update(rsc, SDE_RSC_CMD_STATE);

@@ -287,6 +321,28 @@ static bool sde_rsc_switch_to_cmd(struct sde_rsc_priv *rsc,
	return rc;
}

static bool sde_rsc_switch_to_clk(struct sde_rsc_priv *rsc)
{
	struct sde_rsc_client *client;
	int rc = STATE_UPDATE_NOT_ALLOWED;

	list_for_each_entry(client, &rsc->client_list, list)
		if ((client->current_state == SDE_RSC_VID_STATE) ||
		    (client->current_state == SDE_RSC_CMD_STATE))
			goto end;

	/* no need to enable the solver again */
	if (rsc->current_state == SDE_RSC_CMD_STATE) {
		rc = 0;
		goto end;
	}

	if (rsc->hw_ops.state_update)
		rc = rsc->hw_ops.state_update(rsc, SDE_RSC_CMD_STATE);
end:
	return rc;
}

static bool sde_rsc_switch_to_vid(struct sde_rsc_priv *rsc,
	struct sde_rsc_cmd_config *config,
	struct sde_rsc_client *caller_client, bool wait_req)
@@ -310,7 +366,7 @@ static bool sde_rsc_switch_to_vid(struct sde_rsc_priv *rsc,

/**
 * sde_rsc_client_state_update() - rsc client state update
 * Video mode and command mode are supported as modes. A client need to
 * Video mode, cmd mode and clk state are suppoed as modes. A client need to
 * set this property during panel config time. A switching client can set the
 * property to change the state
 *
@@ -350,8 +406,7 @@ int sde_rsc_client_state_update(struct sde_rsc_client *caller_client,
		pr_err("invalid master component binding\n");
		rc = -EINVAL;
		goto end;
	} else if ((rsc->current_state == state) &&
				(state != SDE_RSC_CMD_UPDATE_STATE)) {
	} else if ((rsc->current_state == state) && !config) {
		pr_debug("no state change: %d\n", state);
		goto end;
	}
@@ -360,7 +415,9 @@ int sde_rsc_client_state_update(struct sde_rsc_client *caller_client,
		__builtin_return_address(0), rsc->current_state,
		caller_client->name, state);

	wait_requested = (rsc->current_state != SDE_RSC_IDLE_STATE);
	/* only switch state needs vsync wait */
	wait_requested = (rsc->current_state == SDE_RSC_VID_STATE) ||
			(rsc->current_state == SDE_RSC_CMD_STATE);

	if (rsc->power_collapse)
		sde_power_resource_enable(&rsc->phandle, rsc->pclient, true);
@@ -368,14 +425,23 @@ int sde_rsc_client_state_update(struct sde_rsc_client *caller_client,
	switch (state) {
	case SDE_RSC_IDLE_STATE:
		rc = sde_rsc_switch_to_idle(rsc);

		/* video state client might be exiting; try cmd state switch */
		if (rc == TRY_CMD_MODE_SWITCH)
		if (rc == TRY_CMD_MODE_SWITCH) {
			rc = sde_rsc_switch_to_cmd(rsc, NULL,
					rsc->primary_client, wait_requested);
			if (!rc)
				state = SDE_RSC_CMD_STATE;

		/* cmd state client might be exiting; try clk state switch */
		} else if (rc == TRY_CLK_MODE_SWITCH) {
			rc = sde_rsc_switch_to_clk(rsc);
			if (!rc)
				state = SDE_RSC_CLK_STATE;
		}
		break;

	case SDE_RSC_CMD_STATE:
	case SDE_RSC_CMD_UPDATE_STATE:
		rc = sde_rsc_switch_to_cmd(rsc, config, caller_client,
								wait_requested);
		break;
@@ -385,19 +451,27 @@ int sde_rsc_client_state_update(struct sde_rsc_client *caller_client,
								wait_requested);
		break;

	case SDE_RSC_CLK_STATE:
		rc = sde_rsc_switch_to_clk(rsc);
		break;

	default:
		pr_err("invalid state handling %d\n", state);
		break;
	}

	if (rc) {
	if (rc == STATE_UPDATE_NOT_ALLOWED) {
		rc = 0;
		goto clk_disable;
	} else if (rc) {
		pr_err("state update failed rc:%d\n", rc);
		goto end;
		goto clk_disable;
	}

	pr_debug("state switch successfully complete: %d\n", state);
	rsc->current_state = state;

clk_disable:
	if (rsc->power_collapse)
		sde_power_resource_enable(&rsc->phandle, rsc->pclient, false);
end:
+8 −9
Original line number Diff line number Diff line
@@ -60,23 +60,22 @@ enum rsc_vsync_req {

/**
 * sde_rsc_state: sde rsc state information
 * SDE_RSC_MODE_IDLE: A client requests for idle state when there is no
 * SDE_RSC_IDLE_STATE: A client requests for idle state when there is no
 *                    pixel or cmd transfer expected. An idle vote from
 *                    all clients lead to power collapse state.
 * SDE_RSC_MODE_CMD:  A client requests for cmd state when it wants to
 * SDE_RSC_CLK_STATE:  A client requests for clk state when it wants to
 *                    only avoid mode-2 entry/exit. For ex: V4L2 driver,
 *                    sde power handle, etc.
 * SDE_RSC_CMD_STATE:  A client requests for cmd state when it wants to
 *                    enable the solver mode.
 * SDE_RSC_MODE_CMD_UPDATE: A clients requests for cmd_update state when
 *                    it wants to update the backoff time during solver
 *                    enable state. Inline-rotation is one good example
 *                    use case. It increases the prefill lines by 128 lines.
 * SDE_RSC_MODE_VID:  A client requests for vid state it wants to avoid
 * SDE_RSC_VID_STATE:  A client requests for vid state it wants to avoid
 *                    solver enable because client is fetching data from
 *                    continuously.
 */
enum sde_rsc_state {
	SDE_RSC_IDLE_STATE,
	SDE_RSC_CLK_STATE,
	SDE_RSC_CMD_STATE,
	SDE_RSC_CMD_UPDATE_STATE,
	SDE_RSC_VID_STATE,
};

@@ -261,7 +260,7 @@ void sde_rsc_client_destroy(struct sde_rsc_client *client);

/**
 * sde_rsc_client_state_update() - rsc client state update
 * Video mode and command mode are supported as modes. A client need to
 * Video mode, cmd mode and clk state are supported as modes. A client need to
 * set this property during panel time. A switching client can set the
 * property to change the state
 *