diff options
author | Dudley Du <dudl@cypress.com> | 2015-07-21 03:09:59 +0300 |
---|---|---|
committer | Dmitry Torokhov <dmitry.torokhov@gmail.com> | 2015-07-24 03:34:05 +0300 |
commit | 757cae5a6f0ac1c61ce149a066377a15d1ed881f (patch) | |
tree | 3c74924b8e411e147153571445fec3ee2a7e7ccc /drivers/input/mouse/cyapa.c | |
parent | 945525ee607471630d07c309e036ae4a53abe37f (diff) | |
download | linux-757cae5a6f0ac1c61ce149a066377a15d1ed881f.tar.xz |
Input: cyapa - fully support runtime suspend power management
Fix the the runtime suspend power management not working issue when system
starts up and before user touches the trackpad device.
TEST=test on Chromebook.
Signed-off-by: Dudley Du <dudl@cypress.com>
Signed-off-by: Dmitry Torokhov <dmitry.torokhov@gmail.com>
Diffstat (limited to 'drivers/input/mouse/cyapa.c')
-rw-r--r-- | drivers/input/mouse/cyapa.c | 73 |
1 files changed, 51 insertions, 22 deletions
diff --git a/drivers/input/mouse/cyapa.c b/drivers/input/mouse/cyapa.c index 2541fbb43533..5c08eeba6162 100644 --- a/drivers/input/mouse/cyapa.c +++ b/drivers/input/mouse/cyapa.c @@ -367,6 +367,7 @@ static int cyapa_open(struct input_dev *input) { struct cyapa *cyapa = input_get_drvdata(input); struct i2c_client *client = cyapa->client; + struct device *dev = &client->dev; int error; error = mutex_lock_interruptible(&cyapa->state_sync_lock); @@ -380,10 +381,9 @@ static int cyapa_open(struct input_dev *input) * when in operational mode. */ error = cyapa->ops->set_power_mode(cyapa, - PWR_MODE_FULL_ACTIVE, 0); + PWR_MODE_FULL_ACTIVE, 0, false); if (error) { - dev_warn(&client->dev, - "set active power failed: %d\n", error); + dev_warn(dev, "set active power failed: %d\n", error); goto out; } } else { @@ -395,10 +395,14 @@ static int cyapa_open(struct input_dev *input) } enable_irq(client->irq); - if (!pm_runtime_enabled(&client->dev)) { - pm_runtime_set_active(&client->dev); - pm_runtime_enable(&client->dev); + if (!pm_runtime_enabled(dev)) { + pm_runtime_set_active(dev); + pm_runtime_enable(dev); } + + pm_runtime_get_sync(dev); + pm_runtime_mark_last_busy(dev); + pm_runtime_put_sync_autosuspend(dev); out: mutex_unlock(&cyapa->state_sync_lock); return error; @@ -408,16 +412,17 @@ static void cyapa_close(struct input_dev *input) { struct cyapa *cyapa = input_get_drvdata(input); struct i2c_client *client = cyapa->client; + struct device *dev = &cyapa->client->dev; mutex_lock(&cyapa->state_sync_lock); disable_irq(client->irq); - if (pm_runtime_enabled(&client->dev)) - pm_runtime_disable(&client->dev); - pm_runtime_set_suspended(&client->dev); + if (pm_runtime_enabled(dev)) + pm_runtime_disable(dev); + pm_runtime_set_suspended(dev); if (cyapa->operational) - cyapa->ops->set_power_mode(cyapa, PWR_MODE_OFF, 0); + cyapa->ops->set_power_mode(cyapa, PWR_MODE_OFF, 0, false); mutex_unlock(&cyapa->state_sync_lock); } @@ -527,7 +532,7 @@ static void cyapa_enable_irq_for_cmd(struct cyapa *cyapa) */ if (!input || cyapa->operational) cyapa->ops->set_power_mode(cyapa, - PWR_MODE_FULL_ACTIVE, 0); + PWR_MODE_FULL_ACTIVE, 0, false); /* Gen3 always using polling mode for command. */ if (cyapa->gen >= CYAPA_GEN5) enable_irq(cyapa->client->irq); @@ -542,7 +547,8 @@ static void cyapa_disable_irq_for_cmd(struct cyapa *cyapa) if (cyapa->gen >= CYAPA_GEN5) disable_irq(cyapa->client->irq); if (!input || cyapa->operational) - cyapa->ops->set_power_mode(cyapa, PWR_MODE_OFF, 0); + cyapa->ops->set_power_mode(cyapa, + PWR_MODE_OFF, 0, false); } } @@ -609,7 +615,7 @@ static int cyapa_initialize(struct cyapa *cyapa) /* Power down the device until we need it. */ if (cyapa->operational) - cyapa->ops->set_power_mode(cyapa, PWR_MODE_OFF, 0); + cyapa->ops->set_power_mode(cyapa, PWR_MODE_OFF, 0, false); return 0; } @@ -625,7 +631,8 @@ static int cyapa_reinitialize(struct cyapa *cyapa) /* Avoid command failures when TP was in OFF state. */ if (cyapa->operational) - cyapa->ops->set_power_mode(cyapa, PWR_MODE_FULL_ACTIVE, 0); + cyapa->ops->set_power_mode(cyapa, + PWR_MODE_FULL_ACTIVE, 0, false); error = cyapa_detect(cyapa); if (error) @@ -644,7 +651,8 @@ out: if (!input || !input->users) { /* Reset to power OFF state to save power when no user open. */ if (cyapa->operational) - cyapa->ops->set_power_mode(cyapa, PWR_MODE_OFF, 0); + cyapa->ops->set_power_mode(cyapa, + PWR_MODE_OFF, 0, false); } else if (!error && cyapa->operational) { /* * Make sure only enable runtime PM when device is @@ -652,6 +660,10 @@ out: */ pm_runtime_set_active(dev); pm_runtime_enable(dev); + + pm_runtime_get_sync(dev); + pm_runtime_mark_last_busy(dev); + pm_runtime_put_sync_autosuspend(dev); } return error; @@ -661,8 +673,8 @@ static irqreturn_t cyapa_irq(int irq, void *dev_id) { struct cyapa *cyapa = dev_id; struct device *dev = &cyapa->client->dev; + int error; - pm_runtime_get_sync(dev); if (device_may_wakeup(dev)) pm_wakeup_event(dev, 0); @@ -681,7 +693,24 @@ static irqreturn_t cyapa_irq(int irq, void *dev_id) goto out; } - if (!cyapa->operational || cyapa->ops->irq_handler(cyapa)) { + if (cyapa->operational) { + error = cyapa->ops->irq_handler(cyapa); + + /* + * Apply runtime power management to touch report event + * except the events caused by the command responses. + * Note: + * It will introduce about 20~40 ms additional delay + * time in receiving for first valid touch report data. + * The time is used to execute device runtime resume + * process. + */ + pm_runtime_get_sync(dev); + pm_runtime_mark_last_busy(dev); + pm_runtime_put_sync_autosuspend(dev); + } + + if (!cyapa->operational || error) { if (!mutex_trylock(&cyapa->state_sync_lock)) { cyapa->ops->sort_empty_output_data(cyapa, NULL, NULL, NULL); @@ -693,8 +722,6 @@ static irqreturn_t cyapa_irq(int irq, void *dev_id) } out: - pm_runtime_mark_last_busy(dev); - pm_runtime_put_sync_autosuspend(dev); return IRQ_HANDLED; } @@ -1335,7 +1362,7 @@ static int __maybe_unused cyapa_suspend(struct device *dev) power_mode = device_may_wakeup(dev) ? cyapa->suspend_power_mode : PWR_MODE_OFF; error = cyapa->ops->set_power_mode(cyapa, power_mode, - cyapa->suspend_sleep_time); + cyapa->suspend_sleep_time, true); if (error) dev_err(dev, "suspend set power mode failed: %d\n", error); @@ -1389,7 +1416,8 @@ static int __maybe_unused cyapa_runtime_suspend(struct device *dev) error = cyapa->ops->set_power_mode(cyapa, cyapa->runtime_suspend_power_mode, - cyapa->runtime_suspend_sleep_time); + cyapa->runtime_suspend_sleep_time, + false); if (error) dev_warn(dev, "runtime suspend failed: %d\n", error); @@ -1401,7 +1429,8 @@ static int __maybe_unused cyapa_runtime_resume(struct device *dev) struct cyapa *cyapa = dev_get_drvdata(dev); int error; - error = cyapa->ops->set_power_mode(cyapa, PWR_MODE_FULL_ACTIVE, 0); + error = cyapa->ops->set_power_mode(cyapa, + PWR_MODE_FULL_ACTIVE, 0, false); if (error) dev_warn(dev, "runtime resume failed: %d\n", error); |