msm: kgsl: Add target specific touch wakeup function

This is needed because gmu and rgmu targets have their own
different power up sequences.

Change-Id: I98f6d24938bfd5968e041c5b680b42750f87dd2e
Signed-off-by: Harshdeep Dhatt <hdhatt@codeaurora.org>
This commit is contained in:
Harshdeep Dhatt 2020-05-20 22:07:40 -06:00
commit f7954ed2e5
4 changed files with 112 additions and 13 deletions

View file

@ -321,23 +321,10 @@ void adreno_fault_detect_stop(struct adreno_device *adreno_dev)
adreno_dev->fast_hang_detect = 0;
}
/*
* A workqueue callback responsible for actually turning on the GPU after a
* 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)
static void adreno_touch_wakeup(struct adreno_device *adreno_dev)
{
struct adreno_device *adreno_dev = container_of(work,
struct adreno_device, input_work);
struct kgsl_device *device = KGSL_DEVICE(adreno_dev);
mutex_lock(&device->mutex);
device->flags |= KGSL_FLAG_WAKE_ON_TOUCH;
/*
* Don't schedule adreno_start in a high priority workqueue, we are
* already in a workqueue which should be sufficient
@ -352,6 +339,29 @@ static void adreno_input_work(struct work_struct *work)
*/
mod_timer(&device->idle_timer,
jiffies + msecs_to_jiffies(adreno_wake_timeout));
}
/*
* A workqueue callback responsible for actually turning on the GPU after a
* 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)
{
struct adreno_device *adreno_dev = container_of(work,
struct adreno_device, input_work);
struct kgsl_device *device = KGSL_DEVICE(adreno_dev);
const struct adreno_power_ops *ops = ADRENO_POWER_OPS(adreno_dev);
mutex_lock(&device->mutex);
device->flags |= KGSL_FLAG_WAKE_ON_TOUCH;
ops->touch_wakeup(adreno_dev);
mutex_unlock(&device->mutex);
}
@ -377,6 +387,11 @@ static void adreno_input_event(struct input_handle *handle, unsigned int type,
if (device->flags & KGSL_FLAG_WAKE_ON_TOUCH)
return;
if (gmu_core_isenabled(device)) {
schedule_work(&adreno_dev->input_work);
return;
}
/*
* If the device is in nap, kick the idle timer to make sure that we
* don't go into slumber before the first render. If the device is
@ -3841,6 +3856,7 @@ const struct adreno_power_ops adreno_power_operations = {
.active_count_put = adreno_pwrctrl_active_count_put,
.pm_suspend = adreno_suspend,
.pm_resume = adreno_resume,
.touch_wakeup = adreno_touch_wakeup,
};
static const struct of_device_id adreno_gmu_match[] = {

View file

@ -357,6 +357,10 @@ struct adreno_power_ops {
int (*pm_suspend)(struct adreno_device *adreno_dev);
/** @pm_resume: Target specific function to resume the driver */
void (*pm_resume)(struct adreno_device *adreno_dev);
/**
* @touch_wakeup: Target specific function to start gpu on touch event
*/
void (*touch_wakeup)(struct adreno_device *adreno_dev);
};
/**

View file

@ -3113,6 +3113,44 @@ static void a6xx_gmu_pm_resume(struct adreno_device *adreno_dev)
clear_bit(GMU_PRIV_PM_SUSPEND, &gmu->flags);
}
static void a6xx_gmu_touch_wakeup(struct adreno_device *adreno_dev)
{
struct kgsl_device *device = KGSL_DEVICE(adreno_dev);
struct a6xx_gmu_device *gmu = to_a6xx_gmu(adreno_dev);
int ret;
/* Do not wake up a suspended device through touch event */
if (test_bit(GMU_PRIV_PM_SUSPEND, &gmu->flags))
return;
if (test_bit(GMU_PRIV_GPU_STARTED, &gmu->flags))
goto done;
ret = a6xx_gmu_boot(adreno_dev);
if (ret)
return;
ret = a6xx_gpu_boot(adreno_dev);
if (ret)
return;
kgsl_pwrscale_wake(device);
set_bit(GMU_PRIV_GPU_STARTED, &gmu->flags);
device->state = KGSL_STATE_ACTIVE;
done:
/*
* When waking up from a touch event we want to stay active long enough
* for the user to send a draw command. The default idle timer timeout
* is shorter than we want so go ahead and push the idle timer out
* further for this special case
*/
mod_timer(&device->idle_timer, jiffies +
msecs_to_jiffies(adreno_wake_timeout));
}
const struct adreno_power_ops a6xx_gmu_power_ops = {
.first_open = a6xx_gmu_first_open,
.last_close = a6xx_gmu_last_close,
@ -3120,6 +3158,7 @@ const struct adreno_power_ops a6xx_gmu_power_ops = {
.active_count_put = a6xx_gmu_active_count_put,
.pm_suspend = a6xx_gmu_pm_suspend,
.pm_resume = a6xx_gmu_pm_resume,
.touch_wakeup = a6xx_gmu_touch_wakeup,
};
int a6xx_gmu_device_probe(struct platform_device *pdev,

View file

@ -881,6 +881,45 @@ static int a6xx_boot(struct adreno_device *adreno_dev)
return 0;
}
static void a6xx_rgmu_touch_wakeup(struct adreno_device *adreno_dev)
{
struct kgsl_device *device = KGSL_DEVICE(adreno_dev);
struct a6xx_rgmu_device *rgmu = to_a6xx_rgmu(adreno_dev);
int ret;
/* Do not wake up a suspended device through touch event */
if (test_bit(RGMU_PRIV_PM_SUSPEND, &rgmu->flags))
return;
if (test_bit(RGMU_PRIV_GPU_STARTED, &rgmu->flags))
goto done;
ret = a6xx_rgmu_boot(adreno_dev);
if (ret)
return;
ret = a6xx_gpu_boot(adreno_dev);
if (ret)
return;
kgsl_pwrscale_wake(device);
set_bit(RGMU_PRIV_GPU_STARTED, &rgmu->flags);
device->state = KGSL_STATE_ACTIVE;
done:
/*
* When waking up from a touch event we want to stay active long enough
* for the user to send a draw command. The default idle timer timeout
* is shorter than we want so go ahead and push the idle timer out
* further for this special case
*/
mod_timer(&device->idle_timer, jiffies +
msecs_to_jiffies(adreno_wake_timeout));
}
static int a6xx_first_boot(struct adreno_device *adreno_dev)
{
struct kgsl_device *device = KGSL_DEVICE(adreno_dev);
@ -1204,6 +1243,7 @@ const struct adreno_power_ops a6xx_rgmu_power_ops = {
.active_count_put = a6xx_rgmu_active_count_put,
.pm_suspend = a6xx_rgmu_pm_suspend,
.pm_resume = a6xx_rgmu_pm_resume,
.touch_wakeup = a6xx_rgmu_touch_wakeup,
};
int a6xx_rgmu_device_probe(struct platform_device *pdev,