|
@@ -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);
|
|
|
|