summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLinux Build Service Account <lnxbuild@localhost>2016-08-01 03:01:55 -0700
committerGerrit - the friendly Code Review server <code-review@localhost>2016-08-01 03:01:55 -0700
commit8560f5d5ea9d846a89c253934cb2d1cf4fac1e23 (patch)
treeac465cd75252db02e78efb2d956ecdb340145e19
parent45e9c3f685ce96d015e39003accbe66dce20aafe (diff)
parent6145f7f6717524be587bcc8ccd7490ed498cd2c8 (diff)
Merge "input: touchscreen: add touch to wake feature in ITEtech driver"
-rw-r--r--Documentation/devicetree/bindings/input/touchscreen/it7258_ts_i2c.txt39
-rw-r--r--Documentation/devicetree/bindings/vendor-prefixes.txt1
-rw-r--r--drivers/input/touchscreen/it7258_ts_i2c.c449
3 files changed, 417 insertions, 72 deletions
diff --git a/Documentation/devicetree/bindings/input/touchscreen/it7258_ts_i2c.txt b/Documentation/devicetree/bindings/input/touchscreen/it7258_ts_i2c.txt
new file mode 100644
index 000000000000..ac59a0950f8a
--- /dev/null
+++ b/Documentation/devicetree/bindings/input/touchscreen/it7258_ts_i2c.txt
@@ -0,0 +1,39 @@
+ITE Tech. touch controller
+
+The ITE Tech. touch controller is connected to host processor
+via i2c. The controller generates interrupts when the user
+touches the panel. The host controller is expected to read
+the touch coordinates over i2c and pass the coordinates to
+the rest of the system.
+
+Required properties:
+
+ - compatible : should be "ite,it7260_ts"
+ - reg : i2c slave address of the device
+ - interrupt-parent : parent of interrupt
+ - interrupts : touch sample interrupt to indicate presence or release
+ of fingers on the panel.
+ - ite,irq-gpio : irq gpio which is to provide interrupts to host,
+ same as "interrupts" node. It will also
+ contain active low or active high information.
+ - ite,reset-gpio : reset gpio to control the reset of chip
+
+Optional properties:
+ - avdd-supply : Analog power supply needed to power device
+ - vdd-supply : Power source required to pull up i2c bus
+ - ite,wakeup : boolean, use this to support touch-to-wake feature.
+
+Example:
+ i2c@f9927000 {
+ it7260@46 {
+ compatible = "ite,it7260_ts";
+ reg = <0x46>;
+ interrupt-parent = <&msmgpio>;
+ interrupts = <17 0x2>;
+ avdd-supply = <&pm8226_l19>;
+ vdd-supply = <&pm8226_lvs1>;
+ ite,reset-gpio = <&msmgpio 16 0x00>;
+ ite,irq-gpio = <&msmgpio 17 0x2008>;
+ ite,wakeup;
+ };
+ };
diff --git a/Documentation/devicetree/bindings/vendor-prefixes.txt b/Documentation/devicetree/bindings/vendor-prefixes.txt
index 8570e6a6bfa4..4097b7cd6454 100644
--- a/Documentation/devicetree/bindings/vendor-prefixes.txt
+++ b/Documentation/devicetree/bindings/vendor-prefixes.txt
@@ -120,6 +120,7 @@ intercontrol Inter Control Group
invensense InvenSense Inc.
isee ISEE 2007 S.L.
isil Intersil
+ite ITE Tech. Inc.
jedec JEDEC Solid State Technology Association
karo Ka-Ro electronics GmbH
keymile Keymile GmbH
diff --git a/drivers/input/touchscreen/it7258_ts_i2c.c b/drivers/input/touchscreen/it7258_ts_i2c.c
index 773ece9eb1d4..61028e1b1d88 100644
--- a/drivers/input/touchscreen/it7258_ts_i2c.c
+++ b/drivers/input/touchscreen/it7258_ts_i2c.c
@@ -22,12 +22,16 @@
#include <linux/firmware.h>
#include <linux/gpio.h>
#include <linux/slab.h>
-#include <linux/wakelock.h>
+#include <linux/regulator/consumer.h>
+#include <linux/of_gpio.h>
+#include <linux/fb.h>
+#include <linux/debugfs.h>
#define MAX_BUFFER_SIZE 144
#define DEVICE_NAME "IT7260"
#define SCREEN_X_RESOLUTION 320
#define SCREEN_Y_RESOLUTION 320
+#define DEBUGFS_DIR_NAME "ts_debug"
/* all commands writes go to this idx */
#define BUF_COMMAND 0x20
@@ -98,6 +102,11 @@
/* use this to include integers in commands */
#define CMD_UINT16(v) ((uint8_t)(v)) , ((uint8_t)((v) >> 8))
+/* Function declarations */
+static int fb_notifier_callback(struct notifier_block *self,
+ unsigned long event, void *data);
+static int IT7260_ts_resume(struct device *dev);
+static int IT7260_ts_suspend(struct device *dev);
struct FingerData {
uint8_t xLo;
@@ -128,24 +137,65 @@ struct PointData {
#define FD_PRESSURE_HIGH 0x08
#define FD_PRESSURE_HEAVY 0x0F
+#define IT_VTG_MIN_UV 1800000
+#define IT_VTG_MAX_UV 1800000
+#define IT_I2C_VTG_MIN_UV 2600000
+#define IT_I2C_VTG_MAX_UV 3300000
+
+struct IT7260_ts_platform_data {
+ u32 irqflags;
+ u32 irq_gpio;
+ u32 irq_gpio_flags;
+ u32 reset_gpio;
+ u32 reset_gpio_flags;
+ bool wakeup;
+};
+
struct IT7260_ts_data {
struct i2c_client *client;
struct input_dev *input_dev;
+ const struct IT7260_ts_platform_data *pdata;
+ struct regulator *vdd;
+ struct regulator *avdd;
+ bool device_needs_wakeup;
+ bool suspended;
+ struct work_struct work_pm_relax;
+#ifdef CONFIG_FB
+ struct notifier_block fb_notif;
+#endif
+ struct dentry *dir;
};
static int8_t fwUploadResult;
static int8_t calibrationWasSuccessful;
static bool devicePresent;
-static DEFINE_MUTEX(sleepModeMutex);
-static bool chipAwake;
static bool hadFingerDown;
-static bool isDeviceSuspend;
static struct input_dev *input_dev;
static struct IT7260_ts_data *gl_ts;
#define LOGE(...) pr_err(DEVICE_NAME ": " __VA_ARGS__)
#define LOGI(...) printk(DEVICE_NAME ": " __VA_ARGS__)
+static int IT7260_debug_suspend_set(void *_data, u64 val)
+{
+ if (val)
+ IT7260_ts_suspend(&gl_ts->client->dev);
+ else
+ IT7260_ts_resume(&gl_ts->client->dev);
+
+ return 0;
+}
+
+static int IT7260_debug_suspend_get(void *_data, u64 *val)
+{
+ *val = gl_ts->suspended;
+
+ return 0;
+}
+
+DEFINE_SIMPLE_ATTRIBUTE(debug_suspend_fops, IT7260_debug_suspend_get,
+ IT7260_debug_suspend_set, "%lld\n");
+
/* internal use func - does not make sure chip is ready before read */
static bool i2cReadNoReadyCheck(uint8_t bufferIndex, uint8_t *dataBuffer,
uint16_t dataLength)
@@ -397,6 +447,21 @@ static bool chipGetVersions(uint8_t *verFw, uint8_t *verCfg, bool logIt)
return ret;
}
+static int IT7260_ts_chipLowPowerMode(bool low)
+{
+ static const uint8_t cmdGoSleep[] = {CMD_PWR_CTL,
+ 0x00, PWR_CTL_SLEEP_MODE};
+ uint8_t dummy;
+
+ if (low)
+ i2cWriteNoReadyCheck(BUF_COMMAND, cmdGoSleep,
+ sizeof(cmdGoSleep));
+ else
+ i2cReadNoReadyCheck(BUF_QUERY, &dummy, sizeof(dummy));
+
+ return 0;
+}
+
static ssize_t sysfsUpgradeStore(struct device *dev,
struct device_attribute *attr, const char *buf, size_t count)
{
@@ -569,50 +634,39 @@ static ssize_t sysfsSleepShow(struct device *dev,
* leaking a byte of kernel data (by claiming to return a byte but not
* writing to buf. To fix this now we actually return the sleep status
*/
- if (!mutex_lock_interruptible(&sleepModeMutex)) {
- *buf = chipAwake ? '1' : '0';
- mutex_unlock(&sleepModeMutex);
- return 1;
- } else {
- return -EINTR;
- }
+ *buf = gl_ts->suspended ? '1' : '0';
+ return 1;
}
static ssize_t sysfsSleepStore(struct device *dev,
struct device_attribute *attr, const char *buf, size_t count)
{
- static const uint8_t cmdGoSleep[] = {CMD_PWR_CTL,
- 0x00, PWR_CTL_SLEEP_MODE};
- int goToSleepVal, ret;
- bool goToWake;
- uint8_t dummy;
+ int go_to_sleep, ret;
ret = kstrtoint(buf, 10, &goToSleepVal);
- /* convert to bool of proper polarity */
- goToWake = !goToSleepVal;
-
- if (!mutex_lock_interruptible(&sleepModeMutex)) {
- if ((chipAwake && goToWake) || (!chipAwake && !goToWake))
- LOGE("duplicate request to %s chip\n",
- goToWake ? "wake" : "sleep");
- else if (goToWake) {
- i2cReadNoReadyCheck(BUF_QUERY, &dummy, sizeof(dummy));
- enable_irq(gl_ts->client->irq);
- LOGI("touch is going to wake!\n");
- } else {
- disable_irq(gl_ts->client->irq);
- i2cWriteNoReadyCheck(BUF_COMMAND, cmdGoSleep,
- sizeof(cmdGoSleep));
- LOGI("touch is going to sleep...\n");
- }
- chipAwake = goToWake;
- mutex_unlock(&sleepModeMutex);
- return count;
+
+ /* (gl_ts->suspended == true && goToSleepVal > 0) means
+ * device is already suspended and you want it to be in sleep,
+ * (gl_ts->suspended == false && goToSleepVal == 0) means
+ * device is already active and you also want it to be active.
+ */
+ if ((gl_ts->suspended && go_to_sleep > 0) ||
+ (!gl_ts->suspended && go_to_sleep == 0))
+ dev_err(dev, "duplicate request to %s chip\n",
+ go_to_sleep ? "sleep" : "wake");
+ else if (go_to_sleep) {
+ disable_irq(gl_ts->client->irq);
+ IT7260_ts_chipLowPowerMode(true);
+ dev_dbg(dev, "touch is going to sleep...\n");
} else {
- return -EINTR;
+ IT7260_ts_chipLowPowerMode(false);
+ enable_irq(gl_ts->client->irq);
+ dev_dbg(dev, "touch is going to wake!\n");
}
-}
+ gl_ts->suspended = go_to_sleep;
+ return count;
+}
static DEVICE_ATTR(status, S_IRUGO|S_IWUSR|S_IWGRP,
sysfsStatusShow, sysfsStatusStore);
@@ -667,6 +721,13 @@ void sendCalibrationCmd(void)
}
EXPORT_SYMBOL(sendCalibrationCmd);
+static void IT7260_ts_release_all(void)
+{
+ input_report_key(gl_ts->input_dev, BTN_TOUCH, 0);
+ input_mt_sync(gl_ts->input_dev);
+ input_sync(gl_ts->input_dev);
+}
+
static void readFingerData(uint16_t *xP, uint16_t *yP, uint8_t *pressureP,
const struct FingerData *fd)
{
@@ -684,60 +745,79 @@ static void readFingerData(uint16_t *xP, uint16_t *yP, uint8_t *pressureP,
*pressureP = fd->pressure & FD_PRESSURE_BITS;
}
-static void readTouchDataPoint(void)
+static irqreturn_t IT7260_ts_threaded_handler(int irq, void *devid)
{
struct PointData pointData;
uint8_t devStatus;
uint8_t pressure = FD_PRESSURE_NONE;
uint16_t x, y;
+ /* This code adds the touch-to-wake functioanlity to the ITE tech
+ * driver. When the device is in suspend driver, it sends the
+ * KEY_WAKEUP event to wake the device. The pm_stay_awake() call
+ * tells the pm core to stay awake until the CPU cores up already. The
+ * schedule_work() call schedule a work that tells the pm core to relax
+ * once the CPU cores are up.
+ */
+ if (gl_ts->device_needs_wakeup) {
+ pm_stay_awake(&gl_ts->client->dev);
+ gl_ts->device_needs_wakeup = false;
+ input_report_key(gl_ts->input_dev, KEY_WAKEUP, 1);
+ input_sync(gl_ts->input_dev);
+ input_report_key(gl_ts->input_dev, KEY_WAKEUP, 0);
+ input_sync(gl_ts->input_dev);
+ schedule_work(&gl_ts->work_pm_relax);
+ }
+
/* verify there is point data to read & it is readable and valid */
i2cReadNoReadyCheck(BUF_QUERY, &devStatus, sizeof(devStatus));
if (!((devStatus & PT_INFO_BITS) & PT_INFO_YES)) {
- pr_err("readTouchDataPoint() called when no data available (0x%02X)\n",
- devStatus);
- return;
+ return IRQ_HANDLED;
}
if (!i2cReadNoReadyCheck(BUF_POINT_INFO, (void *)&pointData,
sizeof(pointData))) {
- pr_err("readTouchDataPoint() failed to read point data buffer\n");
- return;
+ dev_err(&gl_ts->client->dev,
+ "readTouchDataPoint() failed to read point data buffer\n");
+ return IRQ_HANDLED;
}
if ((pointData.flags & PD_FLAGS_DATA_TYPE_BITS) !=
PD_FLAGS_DATA_TYPE_TOUCH) {
- pr_err("readTouchDataPoint() dropping non-point data of type 0x%02X\n",
+ dev_err(&gl_ts->client->dev,
+ "readTouchDataPoint() dropping non-point data of type 0x%02X\n",
pointData.flags);
- return;
+ return IRQ_HANDLED;
}
if ((pointData.flags & PD_FLAGS_HAVE_FINGERS) & 1)
readFingerData(&x, &y, &pressure, pointData.fd);
if (pressure >= FD_PRESSURE_LIGHT) {
-
if (!hadFingerDown)
hadFingerDown = true;
readFingerData(&x, &y, &pressure, pointData.fd);
- input_report_abs(gl_ts->input_dev, ABS_X, x);
- input_report_abs(gl_ts->input_dev, ABS_Y, y);
input_report_key(gl_ts->input_dev, BTN_TOUCH, 1);
+ input_report_abs(gl_ts->input_dev, ABS_MT_POSITION_X, x);
+ input_report_abs(gl_ts->input_dev, ABS_MT_POSITION_Y, y);
+ input_mt_sync(gl_ts->input_dev);
input_sync(gl_ts->input_dev);
+
} else if (hadFingerDown) {
hadFingerDown = false;
input_report_key(gl_ts->input_dev, BTN_TOUCH, 0);
+ input_mt_sync(gl_ts->input_dev);
input_sync(gl_ts->input_dev);
}
+ return IRQ_HANDLED;
}
-static irqreturn_t IT7260_ts_threaded_handler(int irq, void *devid)
+static void IT7260_ts_work_func(struct work_struct *work)
{
- readTouchDataPoint();
- return IRQ_HANDLED;
+ pm_relax(&gl_ts->client->dev);
}
static bool chipIdentifyIT7260(void)
@@ -782,9 +862,11 @@ static int IT7260_ts_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
static const uint8_t cmdStart[] = {CMD_UNKNOWN_7};
- struct IT7260_i2c_platform_data *pdata;
+ struct IT7260_ts_platform_data *pdata;
uint8_t rsp[2];
int ret = -1;
+ int rc;
+ struct dentry *temp;
if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) {
LOGE("need I2C_FUNC_I2C\n");
@@ -805,13 +887,100 @@ static int IT7260_ts_probe(struct i2c_client *client,
gl_ts->client = client;
i2c_set_clientdata(client, gl_ts);
- pdata = client->dev.platform_data;
+ if (client->dev.platform_data == NULL)
+ return -ENODEV;
+
+ if (client->dev.of_node) {
+ pdata = devm_kzalloc(&client->dev, sizeof(*pdata), GFP_KERNEL);
+ if (!pdata)
+ return -ENOMEM;
+ } else
+ pdata = client->dev.platform_data;
+
+ if (!pdata)
+ return -ENOMEM;
+
+ gl_ts->pdata = pdata;
if (sysfs_create_group(&(client->dev.kobj), &it7260_attrstatus_group)) {
dev_err(&client->dev, "failed to register sysfs #1\n");
goto err_sysfs_grp_create_1;
}
+ gl_ts->vdd = regulator_get(&gl_ts->client->dev, "vdd");
+ if (IS_ERR(gl_ts->vdd)) {
+ dev_err(&gl_ts->client->dev,
+ "Regulator get failed vdd\n");
+ gl_ts->vdd = NULL;
+ } else {
+ rc = regulator_set_voltage(gl_ts->vdd,
+ IT_VTG_MIN_UV, IT_VTG_MAX_UV);
+ if (rc)
+ dev_err(&gl_ts->client->dev,
+ "Regulator set_vtg failed vdd\n");
+ }
+
+ gl_ts->avdd = regulator_get(&gl_ts->client->dev, "avdd");
+ if (IS_ERR(gl_ts->avdd)) {
+ dev_err(&gl_ts->client->dev,
+ "Regulator get failed avdd\n");
+ gl_ts->avdd = NULL;
+ } else {
+ rc = regulator_set_voltage(gl_ts->avdd, IT_I2C_VTG_MIN_UV,
+ IT_I2C_VTG_MAX_UV);
+ if (rc)
+ dev_err(&gl_ts->client->dev,
+ "Regulator get failed avdd\n");
+ }
+
+ if (gl_ts->vdd) {
+ rc = regulator_enable(gl_ts->vdd);
+ if (rc) {
+ dev_err(&gl_ts->client->dev,
+ "Regulator vdd enable failed rc=%d\n", rc);
+ return rc;
+ }
+ }
+
+ if (gl_ts->avdd) {
+ rc = regulator_enable(gl_ts->avdd);
+ if (rc) {
+ dev_err(&gl_ts->client->dev,
+ "Regulator avdd enable failed rc=%d\n", rc);
+ return rc;
+ }
+ }
+
+ /* reset gpio info */
+ pdata->reset_gpio = of_get_named_gpio_flags(client->dev.of_node,
+ "ite,reset-gpio", 0,
+ &pdata->reset_gpio_flags);
+ if (gpio_is_valid(pdata->reset_gpio)) {
+ if (gpio_request(pdata->reset_gpio, "ite_reset_gpio"))
+ dev_err(&gl_ts->client->dev,
+ "gpio_request failed for reset GPIO\n");
+ if (gpio_direction_output(pdata->reset_gpio, 0))
+ dev_err(&gl_ts->client->dev,
+ "gpio_direction_output for reset GPIO\n");
+ dev_dbg(&gl_ts->client->dev, "Reset GPIO %d\n",
+ pdata->reset_gpio);
+ } else {
+ return pdata->reset_gpio;
+ }
+
+ /* irq gpio info */
+ pdata->irq_gpio = of_get_named_gpio_flags(client->dev.of_node,
+ "ite,irq-gpio", 0, &pdata->irq_gpio_flags);
+ if (gpio_is_valid(pdata->irq_gpio)) {
+ dev_dbg(&gl_ts->client->dev, "IRQ GPIO %d, IRQ # %d\n",
+ pdata->irq_gpio, gpio_to_irq(pdata->irq_gpio));
+ } else {
+ return pdata->irq_gpio;
+ }
+
+ pdata->wakeup = of_property_read_bool(client->dev.of_node,
+ "ite,wakeup");
+
if (!chipIdentifyIT7260()) {
LOGI("chipIdentifyIT7260 FAIL");
goto err_ident_fail_or_input_alloc;
@@ -836,10 +1005,18 @@ static int IT7260_ts_probe(struct i2c_client *client,
set_bit(INPUT_PROP_DIRECT,input_dev->propbit);
set_bit(BTN_TOUCH, input_dev->keybit);
set_bit(KEY_SLEEP,input_dev->keybit);
- set_bit(KEY_WAKEUP,input_dev->keybit);
set_bit(KEY_POWER,input_dev->keybit);
- input_set_abs_params(input_dev, ABS_X, 0, SCREEN_X_RESOLUTION, 0, 0);
- input_set_abs_params(input_dev, ABS_Y, 0, SCREEN_Y_RESOLUTION, 0, 0);
+ input_set_abs_params(input_dev, ABS_MT_POSITION_X, 0,
+ SCREEN_X_RESOLUTION, 0, 0);
+ input_set_abs_params(input_dev, ABS_MT_POSITION_Y, 0,
+ SCREEN_Y_RESOLUTION, 0, 0);
+ input_set_drvdata(gl_ts->input_dev, gl_ts);
+
+ if (pdata->wakeup) {
+ set_bit(KEY_WAKEUP, gl_ts->input_dev->keybit);
+ INIT_WORK(&gl_ts->work_pm_relax, IT7260_ts_work_func);
+ device_init_wakeup(&client->dev, pdata->wakeup);
+ }
if (input_register_device(input_dev)) {
LOGE("failed to register input device\n");
@@ -856,6 +1033,15 @@ static int IT7260_ts_probe(struct i2c_client *client,
dev_err(&client->dev, "failed to register sysfs #2\n");
goto err_sysfs_grp_create_2;
}
+
+#if defined(CONFIG_FB)
+ gl_ts->fb_notif.notifier_call = fb_notifier_callback;
+
+ ret = fb_register_client(&gl_ts->fb_notif);
+ if (ret)
+ dev_err(&client->dev, "Unable to register fb_notifier: %d\n",
+ ret);
+#endif
devicePresent = true;
@@ -864,8 +1050,36 @@ static int IT7260_ts_probe(struct i2c_client *client,
i2cReadNoReadyCheck(BUF_RESPONSE, rsp, sizeof(rsp));
mdelay(10);
+ gl_ts->dir = debugfs_create_dir(DEBUGFS_DIR_NAME, NULL);
+ if (gl_ts->dir == NULL || IS_ERR(gl_ts->dir)) {
+ dev_err(&client->dev,
+ "%s: Failed to create debugfs directory, rc = %ld\n",
+ __func__, PTR_ERR(gl_ts->dir));
+ ret = PTR_ERR(gl_ts->dir);
+ goto err_create_debugfs_dir;
+ }
+
+ temp = debugfs_create_file("suspend", S_IRUSR | S_IWUSR, gl_ts->dir,
+ gl_ts, &debug_suspend_fops);
+ if (temp == NULL || IS_ERR(temp)) {
+ dev_err(&client->dev,
+ "%s: Failed to create suspend debugfs file, rc = %ld\n",
+ __func__, PTR_ERR(temp));
+ ret = PTR_ERR(temp);
+ goto err_create_debugfs_file;
+ }
+
return 0;
+err_create_debugfs_file:
+ debugfs_remove_recursive(gl_ts->dir);
+err_create_debugfs_dir:
+#if defined(CONFIG_FB)
+ if (fb_unregister_client(&gl_ts->fb_notif))
+ dev_err(&client->dev, "Error occurred while unregistering fb_notifier.\n");
+#endif
+ sysfs_remove_group(&(client->dev.kobj), &it7260_attr_group);
+
err_sysfs_grp_create_2:
free_irq(client->irq, gl_ts);
@@ -874,6 +1088,10 @@ err_irq_reg:
input_dev = NULL;
err_input_register:
+ if (pdata->wakeup) {
+ cancel_work_sync(&gl_ts->work_pm_relax);
+ device_init_wakeup(&client->dev, false);
+ }
if (input_dev)
input_free_device(input_dev);
@@ -889,10 +1107,108 @@ err_out:
static int IT7260_ts_remove(struct i2c_client *client)
{
+ debugfs_remove_recursive(gl_ts->dir);
+#if defined(CONFIG_FB)
+ if (fb_unregister_client(&gl_ts->fb_notif))
+ dev_err(&client->dev, "Error occurred while unregistering fb_notifier.\n");
+#endif
+ sysfs_remove_group(&(client->dev.kobj), &it7260_attr_group);
+ if (gl_ts->pdata->wakeup) {
+ cancel_work_sync(&gl_ts->work_pm_relax);
+ device_init_wakeup(&client->dev, false);
+ }
devicePresent = false;
return 0;
}
+#if defined(CONFIG_FB)
+static int fb_notifier_callback(struct notifier_block *self,
+ unsigned long event, void *data)
+{
+ struct fb_event *evdata = data;
+ int *blank;
+
+ if (evdata && evdata->data && gl_ts && gl_ts->client) {
+ if (event == FB_EVENT_BLANK) {
+ blank = evdata->data;
+ if (*blank == FB_BLANK_UNBLANK)
+ IT7260_ts_resume(&(gl_ts->client->dev));
+ else if (*blank == FB_BLANK_POWERDOWN ||
+ *blank == FB_BLANK_VSYNC_SUSPEND)
+ IT7260_ts_suspend(&(gl_ts->client->dev));
+ }
+ }
+
+ return 0;
+}
+#endif
+
+#ifdef CONFIG_PM
+static int IT7260_ts_resume(struct device *dev)
+{
+ if (!gl_ts->suspended) {
+ dev_info(dev, "Already in resume state\n");
+ return 0;
+ }
+
+ if (device_may_wakeup(dev)) {
+ if (gl_ts->device_needs_wakeup) {
+ gl_ts->device_needs_wakeup = false;
+ disable_irq_wake(gl_ts->client->irq);
+ }
+ return 0;
+ }
+
+ /* put the device in active power mode */
+ IT7260_ts_chipLowPowerMode(false);
+
+ enable_irq(gl_ts->client->irq);
+ gl_ts->suspended = false;
+ return 0;
+}
+
+static int IT7260_ts_suspend(struct device *dev)
+{
+ if (gl_ts->suspended) {
+ dev_info(dev, "Already in suspend state\n");
+ return 0;
+ }
+
+ if (device_may_wakeup(dev)) {
+ if (!gl_ts->device_needs_wakeup) {
+ gl_ts->device_needs_wakeup = true;
+ enable_irq_wake(gl_ts->client->irq);
+ }
+ return 0;
+ }
+
+ disable_irq(gl_ts->client->irq);
+
+ /* put the device in low power mode */
+ IT7260_ts_chipLowPowerMode(true);
+
+ IT7260_ts_release_all();
+ gl_ts->suspended = true;
+
+ return 0;
+}
+
+static const struct dev_pm_ops IT7260_ts_dev_pm_ops = {
+ .suspend = IT7260_ts_suspend,
+ .resume = IT7260_ts_resume,
+};
+#else
+static int IT7260_ts_resume(struct device *dev)
+{
+ return 0;
+}
+
+static int IT7260_ts_suspend(struct device *dev)
+{
+ return 0;
+}
+#endif
+
static const struct i2c_device_id IT7260_ts_id[] = {
{ DEVICE_NAME, 0},
{}
@@ -901,33 +1217,22 @@ static const struct i2c_device_id IT7260_ts_id[] = {
MODULE_DEVICE_TABLE(i2c, IT7260_ts_id);
static const struct of_device_id IT7260_match_table[] = {
- { .compatible = "ITE,IT7260_ts",},
+ { .compatible = "ite,it7260_ts",},
{},
};
-static int IT7260_ts_resume(struct i2c_client *i2cdev)
-{
- isDeviceSuspend = false;
- return 0;
-}
-
-static int IT7260_ts_suspend(struct i2c_client *i2cdev, pm_message_t pmesg)
-{
- isDeviceSuspend = true;
- return 0;
-}
-
static struct i2c_driver IT7260_ts_driver = {
.driver = {
.owner = THIS_MODULE,
.name = DEVICE_NAME,
.of_match_table = IT7260_match_table,
+#ifdef CONFIG_PM
+ .pm = &IT7260_ts_dev_pm_ops,
+#endif
},
.probe = IT7260_ts_probe,
.remove = IT7260_ts_remove,
.id_table = IT7260_ts_id,
- .resume = IT7260_ts_resume,
- .suspend = IT7260_ts_suspend,
};
module_i2c_driver(IT7260_ts_driver);