{
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);
* 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 {
}
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;
{
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);
}
*/
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);
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);
}
}
/* 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;
}
/* 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)
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
*/
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;
{
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);
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);
}
out:
- pm_runtime_mark_last_busy(dev);
- pm_runtime_put_sync_autosuspend(dev);
return IRQ_HANDLED;
}
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);
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);
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);
#include <linux/slab.h>
#include <asm/unaligned.h>
#include <linux/crc-itu-t.h>
+#include <linux/pm_runtime.h>
#include "cyapa.h"
}
static int cyapa_gen5_set_power_mode(struct cyapa *cyapa,
- u8 power_mode, u16 sleep_time)
+ u8 power_mode, u16 sleep_time, bool is_suspend)
{
struct device *dev = &cyapa->client->dev;
u8 power_state;
if (cyapa->state != CYAPA_STATE_GEN5_APP)
return 0;
- /* Dump all the report data before do power mode commmands. */
- cyapa_empty_pip_output_data(cyapa, NULL, NULL, NULL);
-
if (PIP_DEV_GET_PWR_STATE(cyapa) == UNINIT_PWR_MODE) {
/*
* Assume TP in deep sleep mode when driver is loaded,
* is suspending which may cause interrupt line unable to be
* asserted again.
*/
- cyapa_empty_pip_output_data(cyapa, NULL, NULL, NULL);
- cyapa_gen5_disable_pip_report(cyapa);
+ if (is_suspend)
+ cyapa_gen5_disable_pip_report(cyapa);
PIP_DEV_SET_PWR_STATE(cyapa,
cyapa_sleep_time_to_pwr_cmd(sleep_time));
* the device state is required.
*/
error = cyapa_gen5_set_power_mode(cyapa,
- PWR_MODE_FULL_ACTIVE, 0);
+ PWR_MODE_FULL_ACTIVE, 0, false);
if (error)
dev_warn(dev, "%s: failed to set power active mode.\n",
__func__);
/*
* Device wake event from deep sleep mode for touch.
* This interrupt event is used to wake system up.
+ *
+ * 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);
return 0;
} else if (report_id != PIP_TOUCH_REPORT_ID &&
report_id != PIP_BTN_REPORT_ID &&