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 #include #include -#include +#include +#include +#include +#include #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);