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

Commit b4dd2aa8 authored by Lucille Sylvester's avatar Lucille Sylvester Committed by Gerrit - the friendly Code Review server
Browse files

msm: kgsl: Use a consistent API to change power state



Provide a simple API to change power state.  No need for
the driver to deal with power resources in detail outside of
the power specific files.  Just request the appropriate state
change and check to see if it took effect in cases where that
matters.

Change-Id: I80e92d48599339490e98337b319f784617245de4
Signed-off-by: default avatarLucille Sylvester <lsylvest@codeaurora.org>
Signed-off-by: default avatarTarun Karra <tkarra@codeaurora.org>
parent 855db97a
Loading
Loading
Loading
Loading
+13 −11
Original line number Diff line number Diff line
@@ -122,9 +122,10 @@ static unsigned int _wake_timeout = 100;

/*
 * A workqueue callback responsible for actually turning on the GPU after a
 * touch event. kgsl_pwrctrl_wake() is used without any active_count protection
 * to avoid the need to maintain state.  Either somebody will start using the
 * GPU or the idle timer will fire and put the GPU back into slumber
 * touch event. kgsl_pwrctrl_change_state(ACTIVE) is used without any
 * active_count protection to avoid the need to maintain state.  Either
 * somebody will start using the GPU or the idle timer will fire and put the
 * GPU back into slumber.
 */
static void adreno_input_work(struct work_struct *work)
{
@@ -140,7 +141,7 @@ static void adreno_input_work(struct work_struct *work)
	 * Don't schedule adreno_start in a high priority workqueue, we are
	 * already in a workqueue which should be sufficient
	 */
	kgsl_pwrctrl_wake(device, 0);
	kgsl_pwrctrl_change_state(device, KGSL_STATE_ACTIVE);

	/*
	 * When waking up from a touch event we want to stay active long enough
@@ -1700,7 +1701,7 @@ static int adreno_init(struct kgsl_device *device)
	/* Make a high priority workqueue for starting the GPU */
	adreno_wq = alloc_workqueue("adreno", 0, 1);

	kgsl_pwrctrl_set_state(device, KGSL_STATE_INIT);
	kgsl_pwrctrl_change_state(device, KGSL_STATE_INIT);
	/*
	 * initialization only needs to be done once initially until
	 * device is shutdown
@@ -1736,7 +1737,7 @@ static int adreno_init(struct kgsl_device *device)
		BUG_ON(1);
	}

	kgsl_pwrctrl_set_state(device, KGSL_STATE_INIT);
	kgsl_pwrctrl_change_state(device, KGSL_STATE_INIT);
	/*
	 * Check if firmware supports the sync lock PM4 packets needed
	 * for IOMMUv1
@@ -1814,7 +1815,7 @@ static int _adreno_start(struct adreno_device *adreno_dev)

	kgsl_cffdump_open(device);

	kgsl_pwrctrl_set_state(device, KGSL_STATE_INIT);
	kgsl_pwrctrl_change_state(device, KGSL_STATE_INIT);

	regulator_left_on = (regulator_is_enabled(device->pwrctrl.gpu_reg) ||
				(device->pwrctrl.gpu_cx &&
@@ -1887,7 +1888,7 @@ error_mmu_off:
error_clk_off:
	kgsl_pwrctrl_disable(device);
	/* set the state back to original state */
	kgsl_pwrctrl_set_state(device, state);
	kgsl_pwrctrl_change_state(device, state);

	return status;
}
@@ -2043,7 +2044,7 @@ int adreno_reset(struct kgsl_device *device)
	 */

	if (atomic_read(&device->active_cnt))
		kgsl_pwrctrl_set_state(device, KGSL_STATE_ACTIVE);
		kgsl_pwrctrl_change_state(device, KGSL_STATE_ACTIVE);

	/* Set the page table back to the default page table */
	kgsl_mmu_setstate(&device->mmu, device->mmu.defaultpagetable,
@@ -2328,7 +2329,7 @@ static ssize_t _ft_hang_intr_status_store(struct device *dev,
		switch (device->state) {
		case KGSL_STATE_NAP:
		case KGSL_STATE_SLEEP:
			kgsl_pwrctrl_wake(device, 0);
			kgsl_pwrctrl_change_state(device, KGSL_STATE_ACTIVE);
		case KGSL_STATE_ACTIVE:
			adreno_dev->gpudev->irq_control(adreno_dev, 1);
		/*
@@ -2611,7 +2612,8 @@ static int adreno_setproperty(struct kgsl_device_private *dev_priv,

				kgsl_pwrscale_enable(device);
			} else {
				kgsl_pwrctrl_wake(device, 0);
				kgsl_pwrctrl_change_state(device,
							KGSL_STATE_ACTIVE);
				device->pwrctrl.ctrl_flags = KGSL_PWR_ON;
				adreno_dev->fast_hang_detect = 0;
				if (adreno_dev->gpudev->fault_detect_stop)
+7 −66
Original line number Diff line number Diff line
@@ -611,61 +611,9 @@ static int kgsl_suspend_device(struct kgsl_device *device, pm_message_t state)
	KGSL_PWR_WARN(device, "suspend start\n");

	kgsl_mutex_lock(&device->mutex, &device->mutex_owner);
	kgsl_pwrctrl_request_state(device, KGSL_STATE_SUSPEND);

	/* Tell the device to drain the submission queue */
	device->ftbl->drain(device);

	/* Wait for the active count to hit zero */
	status = kgsl_active_count_wait(device, 0);
	if (status)
		goto end;

	/*
	 * An interrupt could have snuck in and requested NAP in
	 * the meantime, make sure we're on the SUSPEND path.
	 */
	kgsl_pwrctrl_request_state(device, KGSL_STATE_SUSPEND);

	/* Don't let the timer wake us during suspended sleep. */
	del_timer_sync(&device->idle_timer);
	switch (device->state) {
		case KGSL_STATE_INIT:
			break;
		case KGSL_STATE_ACTIVE:
		case KGSL_STATE_NAP:
		case KGSL_STATE_SLEEP:
			/* make sure power is on to stop the device */
			kgsl_pwrctrl_enable(device);
			/* Get the completion ready to be waited upon. */
			INIT_COMPLETION(device->hwaccess_gate);
			device->ftbl->suspend_context(device);
			device->ftbl->stop(device);
			pm_qos_update_request(&device->pwrctrl.pm_qos_req_dma,
						PM_QOS_DEFAULT_VALUE);
			kgsl_pwrctrl_set_state(device, KGSL_STATE_SUSPEND);
			break;
		case KGSL_STATE_SLUMBER:
			INIT_COMPLETION(device->hwaccess_gate);
			kgsl_pwrctrl_set_state(device, KGSL_STATE_SUSPEND);
			break;
		default:
			KGSL_PWR_ERR(device, "suspend fail, device %d\n",
					device->id);
			goto end;
	}
	kgsl_pwrctrl_request_state(device, KGSL_STATE_NONE);
	kgsl_pwrscale_sleep(device);
	status = 0;

end:
	if (status) {
		/* On failure, re-resume normal activity */
		if (device->ftbl->resume)
			device->ftbl->resume(device);
	}

	status = kgsl_pwrctrl_change_state(device, KGSL_STATE_SUSPEND);
	kgsl_mutex_unlock(&device->mutex, &device->mutex_owner);

	KGSL_PWR_WARN(device, "suspend end\n");
	return status;
}
@@ -678,8 +626,7 @@ static int kgsl_resume_device(struct kgsl_device *device)
	KGSL_PWR_WARN(device, "resume start\n");
	kgsl_mutex_lock(&device->mutex, &device->mutex_owner);
	if (device->state == KGSL_STATE_SUSPEND) {
		kgsl_pwrctrl_set_state(device, KGSL_STATE_SLUMBER);
		complete_all(&device->hwaccess_gate);
		kgsl_pwrctrl_change_state(device, KGSL_STATE_SLUMBER);
	} else if (device->state != KGSL_STATE_INIT) {
		/*
		 * This is an error situation,so wait for the device
@@ -689,16 +636,10 @@ static int kgsl_resume_device(struct kgsl_device *device)
		 */
		if (device->state == KGSL_STATE_ACTIVE)
			device->ftbl->idle(device);
		kgsl_pwrctrl_request_state(device, KGSL_STATE_SLUMBER);
		kgsl_pwrctrl_sleep(device);
		kgsl_pwrctrl_change_state(device, KGSL_STATE_SLUMBER);
		KGSL_PWR_ERR(device,
			"resume invoked without a suspend\n");
	}
	kgsl_pwrctrl_request_state(device, KGSL_STATE_NONE);

	/* Call the GPU specific resume function */
	if (device->ftbl->resume)
		device->ftbl->resume(device);

	kgsl_mutex_unlock(&device->mutex, &device->mutex_owner);
	KGSL_PWR_WARN(device, "resume end\n");
@@ -915,7 +856,7 @@ static int kgsl_close_device(struct kgsl_device *device)
		/* Force power on to do the stop */
		kgsl_pwrctrl_enable(device);
		result = device->ftbl->stop(device);
		kgsl_pwrctrl_set_state(device, KGSL_STATE_INIT);
		kgsl_pwrctrl_change_state(device, KGSL_STATE_INIT);
	}
	return result;

@@ -1017,7 +958,7 @@ static int kgsl_open_device(struct kgsl_device *device)
		 * we start suspend or FT.
		 */
		complete_all(&device->hwaccess_gate);
		kgsl_pwrctrl_set_state(device, KGSL_STATE_ACTIVE);
		kgsl_pwrctrl_change_state(device, KGSL_STATE_ACTIVE);
		kgsl_active_count_put(device);
	}
	device->open_count++;
@@ -1089,7 +1030,7 @@ err_stop:
		/* make sure power is on to stop the device */
		kgsl_pwrctrl_enable(device);
		device->ftbl->stop(device);
		kgsl_pwrctrl_set_state(device, KGSL_STATE_INIT);
		kgsl_pwrctrl_change_state(device, KGSL_STATE_INIT);
		atomic_dec(&device->active_cnt);
	}
err_freedevpriv:
+5 −2
Original line number Diff line number Diff line
@@ -628,11 +628,14 @@ int kgsl_cff_dump_enable_set(void *data, u64 val)
		if (!device->cff_dump_enable) {
			device->cff_dump_enable = 1;
			/*
			 * put device to slumber so that we ensure that the
			 * force device to slumber so that we ensure that the
			 * start opcode in CFF is present
			 */
			kgsl_mutex_lock(&device->mutex, &device->mutex_owner);
			ret = kgsl_pwrctrl_slumber(device);
			ret = kgsl_pwrctrl_change_state(device,
				KGSL_STATE_SUSPEND);
			ret |= kgsl_pwrctrl_change_state(device,
				KGSL_STATE_SLUMBER);
			if (ret)
				device->cff_dump_enable = 0;
			kgsl_mutex_unlock(&device->mutex, &device->mutex_owner);
+136 −91
Original line number Diff line number Diff line
@@ -82,6 +82,10 @@ static void kgsl_pwrctrl_clk(struct kgsl_device *device, int state,
					int requested_state);
static void kgsl_pwrctrl_axi(struct kgsl_device *device, int state);
static void kgsl_pwrctrl_pwrrail(struct kgsl_device *device, int state);
static void kgsl_pwrctrl_set_state(struct kgsl_device *device,
				unsigned int state);
static void kgsl_pwrctrl_request_state(struct kgsl_device *device,
				unsigned int state);

/*
 * Given a requested power level do bounds checking on the constraints and
@@ -1151,7 +1155,8 @@ void kgsl_idle_check(struct work_struct *work)
		   || device->state ==  KGSL_STATE_NAP) {

		if (!atomic_read(&device->active_cnt))
			kgsl_pwrctrl_sleep(device);
			kgsl_pwrctrl_change_state(device,
					device->requested_state);

		kgsl_pwrctrl_request_state(device, KGSL_STATE_NONE);
		if (device->state == KGSL_STATE_ACTIVE)
@@ -1206,6 +1211,73 @@ void kgsl_pre_hwaccess(struct kgsl_device *device)
}
EXPORT_SYMBOL(kgsl_pre_hwaccess);

/**
 * _init() - Get the GPU ready to start, but don't turn anything on
 * @device - Pointer to the kgsl_device struct
 */
static int _init(struct kgsl_device *device)
{
	kgsl_pwrctrl_set_state(device, KGSL_STATE_INIT);
	return 0;
}

/**
 * _wake() - Power up the GPU from a slumber/sleep state
 * @device - Pointer to the kgsl_device struct
 *
 * Resume the GPU from a lower power state to ACTIVE.
 */
static int _wake(struct kgsl_device *device)
{
	int status = 0;

	switch (device->state) {
	case KGSL_STATE_SUSPEND:
		complete_all(&device->hwaccess_gate);
		/* Call the GPU specific resume function */
		device->ftbl->resume(device);
	case KGSL_STATE_SLUMBER:
		status = device->ftbl->start(device,
				device->pwrctrl.superfast);
		device->pwrctrl.superfast = false;

		if (status) {
			kgsl_pwrctrl_request_state(device, KGSL_STATE_NONE);
			KGSL_DRV_ERR(device, "start failed %d\n", status);
			break;
		}
		/* fall through */
	case KGSL_STATE_SLEEP:
		kgsl_pwrctrl_axi(device, KGSL_PWRFLAGS_ON);
		kgsl_pwrscale_wake(device);
		/* fall through */
	case KGSL_STATE_NAP:
		/* Turn on the core clocks */
		kgsl_pwrctrl_clk(device, KGSL_PWRFLAGS_ON, KGSL_STATE_ACTIVE);
		/* Enable state before turning on irq */
		kgsl_pwrctrl_set_state(device, KGSL_STATE_ACTIVE);
		kgsl_pwrctrl_irq(device, KGSL_PWRFLAGS_ON);
		mod_timer(&device->idle_timer, jiffies +
				device->pwrctrl.interval_timeout);
		pm_qos_update_request(&device->pwrctrl.pm_qos_req_dma,
				device->pwrctrl.pm_qos_latency);
	case KGSL_STATE_ACTIVE:
		kgsl_pwrctrl_request_state(device, KGSL_STATE_NONE);
		break;
	case KGSL_STATE_INIT:
		kgsl_pwrctrl_set_state(device, KGSL_STATE_ACTIVE);
		kgsl_pwrctrl_request_state(device, KGSL_STATE_NONE);
		break;
	default:
		KGSL_PWR_WARN(device, "unhandled state %s\n",
				kgsl_pwrstate_to_str(device->state));
		kgsl_pwrctrl_request_state(device, KGSL_STATE_NONE);
		status = -EINVAL;
		break;
	}
	return status;
}

static int
_nap(struct kgsl_device *device)
{
@@ -1294,6 +1366,11 @@ _slumber(struct kgsl_device *device)
		break;
	case KGSL_STATE_SLUMBER:
		break;
	case KGSL_STATE_SUSPEND:
		complete_all(&device->hwaccess_gate);
		device->ftbl->resume(device);
		kgsl_pwrctrl_set_state(device, KGSL_STATE_SLUMBER);
		break;
	default:
		KGSL_PWR_WARN(device, "unhandled state %s\n",
				kgsl_pwrstate_to_str(device->state));
@@ -1302,123 +1379,91 @@ _slumber(struct kgsl_device *device)
	return 0;
}

/******************************************************************/
/* Caller must hold the device mutex. */
int kgsl_pwrctrl_sleep(struct kgsl_device *device)
{
	int status = 0;
	KGSL_PWR_INFO(device, "sleep device %d\n", device->id);

	/* Work through the legal state transitions */
	switch (device->requested_state) {
	case KGSL_STATE_NAP:
		status = _nap(device);
		break;
	case KGSL_STATE_SLEEP:
		status = _sleep(device);
		break;
	case KGSL_STATE_SLUMBER:
		status = _slumber(device);
		break;
	default:
		KGSL_PWR_INFO(device, "bad state request 0x%x\n",
				device->requested_state);
		kgsl_pwrctrl_request_state(device, KGSL_STATE_NONE);
		status = -EINVAL;
		break;
	}
	return status;
}
EXPORT_SYMBOL(kgsl_pwrctrl_sleep);

/*
 * kgsl_pwrctrl_slumber() - Put device into slumber if it is not in suspend
 * _suspend() - Put device into suspend
 * @device: Device pointer
 *
 * Return 0 on success else error code
 */
int kgsl_pwrctrl_slumber(struct kgsl_device *device)
int _suspend(struct kgsl_device *device)
{
	int ret = 0;

	if (KGSL_STATE_SLUMBER == device->state ||
		KGSL_STATE_SUSPEND == device->state)
		return ret;
	if (KGSL_STATE_SUSPEND == device->requested_state)
	if (KGSL_STATE_SUSPEND == device->state)
		return ret;

	/* drain to prevent from more commands being submitted */
	device->ftbl->drain(device);
	/* wait for active count so device can be put in slumber */
	ret = kgsl_active_count_wait(device, 0);
	if (ret) {
		device->ftbl->resume(device);
		return ret;
	}
	if (ret)
		goto err;

	ret = device->ftbl->idle(device);
	if (ret) {
		device->ftbl->resume(device);
	if (ret)
		goto err;

	ret = _slumber(device);
	if (ret)
		goto err;

	kgsl_pwrctrl_set_state(device, KGSL_STATE_SUSPEND);
	return ret;
	}
	/* resume since we drained earlier */

err:
	device->ftbl->resume(device);
	kgsl_pwrctrl_request_state(device, KGSL_STATE_SLUMBER);
	ret = kgsl_pwrctrl_sleep(device);
	KGSL_PWR_ERR(device, "device failed to SUSPEND %d\n", ret);
	return ret;
}
EXPORT_SYMBOL(kgsl_pwrctrl_slumber);

/**
 * kgsl_pwrctrl_wake() - Power up the GPU from a slumber/sleep state
 * @device - Pointer to the kgsl_device struct
 * @priority - Boolean flag to indicate that the GPU start should be run in the
 * higher priority thread
/*
 * kgsl_pwrctrl_change_state() changes the GPU state to the input
 * @device: Pointer to a KGSL device
 * @state: desired KGSL state
 *
 * Resume the GPU from a lower power state to ACTIVE.  The caller to this
 * fucntion must host the kgsl_device mutex.
 * Caller must hold the device mutex. If the requested state change
 * is valid, execute it.  Otherwise return an error code explaining
 * why the change has not taken place.  Also print an error if an
 * unexpected state change failure occurs.  For example, a change to
 * NAP may be rejected because the GPU is busy, this is not an error.
 * A change to SUSPEND should go through no matter what, so if it
 * fails an additional error message will be printed to dmesg.
 */
int kgsl_pwrctrl_wake(struct kgsl_device *device, int priority)
int kgsl_pwrctrl_change_state(struct kgsl_device *device, int state)
{
	int status = 0;
	kgsl_pwrctrl_request_state(device, state);

	kgsl_pwrctrl_request_state(device, KGSL_STATE_ACTIVE);
	switch (device->state) {
	case KGSL_STATE_SLUMBER:
		status = device->ftbl->start(device, priority);

		if (status) {
			kgsl_pwrctrl_request_state(device, KGSL_STATE_NONE);
			KGSL_DRV_ERR(device, "start failed %d\n", status);
	/* Work through the legal state transitions */
	switch (device->requested_state) {
	case KGSL_STATE_INIT:
		status = _init(device);
		break;
		}
		/* fall through */
	case KGSL_STATE_SLEEP:
		kgsl_pwrctrl_axi(device, KGSL_PWRFLAGS_ON);
		kgsl_pwrscale_wake(device);
		/* fall through */
	case KGSL_STATE_NAP:
		/* Turn on the core clocks */
		kgsl_pwrctrl_clk(device, KGSL_PWRFLAGS_ON, KGSL_STATE_ACTIVE);
		/* Enable state before turning on irq */
		kgsl_pwrctrl_set_state(device, KGSL_STATE_ACTIVE);
		kgsl_pwrctrl_irq(device, KGSL_PWRFLAGS_ON);
		mod_timer(&device->idle_timer, jiffies +
				device->pwrctrl.interval_timeout);
		pm_qos_update_request(&device->pwrctrl.pm_qos_req_dma,
				device->pwrctrl.pm_qos_latency);
	case KGSL_STATE_ACTIVE:
		kgsl_pwrctrl_request_state(device, KGSL_STATE_NONE);
		status = _wake(device);
		break;
	case KGSL_STATE_NAP:
		status = _nap(device);
		break;
	case KGSL_STATE_SLEEP:
		status = _sleep(device);
		break;
	case KGSL_STATE_SLUMBER:
		status = _slumber(device);
		break;
	case KGSL_STATE_SUSPEND:
		status = _suspend(device);
		break;
	default:
		KGSL_PWR_WARN(device, "unhandled state %s\n",
				kgsl_pwrstate_to_str(device->state));
		KGSL_PWR_INFO(device, "bad state request 0x%x\n",
				device->requested_state);
		kgsl_pwrctrl_request_state(device, KGSL_STATE_NONE);
		status = -EINVAL;
		break;
	}
	return status;
}
EXPORT_SYMBOL(kgsl_pwrctrl_wake);
EXPORT_SYMBOL(kgsl_pwrctrl_change_state);

void kgsl_pwrctrl_enable(struct kgsl_device *device)
{
@@ -1450,21 +1495,21 @@ void kgsl_pwrctrl_disable(struct kgsl_device *device)
}
EXPORT_SYMBOL(kgsl_pwrctrl_disable);

void kgsl_pwrctrl_set_state(struct kgsl_device *device, unsigned int state)
static void kgsl_pwrctrl_set_state(struct kgsl_device *device,
				unsigned int state)
{
	trace_kgsl_pwr_set_state(device, state);
	device->state = state;
	device->requested_state = KGSL_STATE_NONE;
}
EXPORT_SYMBOL(kgsl_pwrctrl_set_state);

void kgsl_pwrctrl_request_state(struct kgsl_device *device, unsigned int state)
static void kgsl_pwrctrl_request_state(struct kgsl_device *device,
				unsigned int state)
{
	if (state != KGSL_STATE_NONE && state != device->requested_state)
		trace_kgsl_pwr_request_state(device, state);
	device->requested_state = state;
}
EXPORT_SYMBOL(kgsl_pwrctrl_request_state);

const char *kgsl_pwrstate_to_str(unsigned int state)
{
@@ -1513,8 +1558,8 @@ int kgsl_active_count_get(struct kgsl_device *device)
		kgsl_mutex_unlock(&device->mutex, &device->mutex_owner);
		wait_for_completion(&device->hwaccess_gate);
		kgsl_mutex_lock(&device->mutex, &device->mutex_owner);

		ret = kgsl_pwrctrl_wake(device, 1);
		device->pwrctrl.superfast = true;
		ret = kgsl_pwrctrl_change_state(device, KGSL_STATE_ACTIVE);
	}
	if (ret == 0)
		atomic_inc(&device->active_cnt);
+4 −7
Original line number Diff line number Diff line
@@ -79,6 +79,8 @@ struct kgsl_pwr_constraint {
 * @bus_index - default bus index into the bus_ib table
 * @bus_ib - the set of unique ib requests needed for the bus calculation
 * @constraint - currently active power constraint
 * @superfast - Boolean flag to indicate that the GPU start should be run in the
 * higher priority thread
 */

struct kgsl_pwrctrl {
@@ -109,6 +111,7 @@ struct kgsl_pwrctrl {
	unsigned int bus_index[KGSL_MAX_PWRLEVELS];
	uint64_t bus_ib[KGSL_MAX_PWRLEVELS];
	struct kgsl_pwr_constraint constraint;
	bool superfast;
};

void kgsl_pwrctrl_irq(struct kgsl_device *device, int state);
@@ -117,8 +120,6 @@ void kgsl_pwrctrl_close(struct kgsl_device *device);
void kgsl_timer(unsigned long data);
void kgsl_idle_check(struct work_struct *work);
void kgsl_pre_hwaccess(struct kgsl_device *device);
int kgsl_pwrctrl_sleep(struct kgsl_device *device);
int kgsl_pwrctrl_wake(struct kgsl_device *device, int priority);
void kgsl_pwrctrl_pwrlevel_change(struct kgsl_device *device,
	unsigned int level);
void kgsl_pwrctrl_buslevel_update(struct kgsl_device *device,
@@ -128,6 +129,7 @@ void kgsl_pwrctrl_uninit_sysfs(struct kgsl_device *device);
void kgsl_pwrctrl_enable(struct kgsl_device *device);
void kgsl_pwrctrl_disable(struct kgsl_device *device);
bool kgsl_pwrctrl_isenabled(struct kgsl_device *device);
int kgsl_pwrctrl_change_state(struct kgsl_device *device, int state);

static inline unsigned long kgsl_get_clkrate(struct clk *clk)
{
@@ -146,13 +148,8 @@ kgsl_pwrctrl_active_freq(struct kgsl_pwrctrl *pwr)
	return pwr->pwrlevels[pwr->active_pwrlevel].gpu_freq;
}

void kgsl_pwrctrl_set_state(struct kgsl_device *device, unsigned int state);
void kgsl_pwrctrl_request_state(struct kgsl_device *device, unsigned int state);

int __must_check kgsl_active_count_get(struct kgsl_device *device);
void kgsl_active_count_put(struct kgsl_device *device);
int kgsl_active_count_wait(struct kgsl_device *device, int count);
int kgsl_pwrctrl_slumber(struct kgsl_device *device);
void kgsl_pwrctrl_busy_time(struct kgsl_device *device, u64 time, u64 busy);

#endif /* __KGSL_PWRCTRL_H */