HID: i2c-hid: disable runtime PM operations on hantick touchpad
authorAnisse Astier <[email protected]>
Wed, 12 Sep 2018 13:07:05 +0000 (15:07 +0200)
committerJiri Kosina <[email protected]>
Fri, 14 Sep 2018 08:00:22 +0000 (10:00 +0200)
This hantick HTIX5288 touchpad can quickly fall in a wrong state if
there are too many open/close operations. This will either make it stop
reporting any input, or will shift all the input reads by a few bytes,
making it impossible to decode.

Here, we never release the probed touchpad runtime pm while the driver
is loaded, which should disable all runtime pm suspend/resumes.

This fast repetition of sleep/wakeup is also more likely to happen when
using runtime PM, which is why the quirk is done there, and not for all
power downs, which would include suspend or module removal.

Signed-off-by: Anisse Astier <[email protected]>
Cc: [email protected]
Acked-by: Benjamin Tissoires <[email protected]>
Reviewed-by: Hans de Goede <[email protected]>
Tested-by: Philip Müller <[email protected]>
Signed-off-by: Jiri Kosina <[email protected]>
drivers/hid/i2c-hid/i2c-hid.c

index f3076659361abcb0567804c298af25e278de8fa9..a8610f5bf6f519752df35cfe0502ca9fc8b25381 100644 (file)
@@ -48,6 +48,7 @@
 #define I2C_HID_QUIRK_SET_PWR_WAKEUP_DEV       BIT(0)
 #define I2C_HID_QUIRK_NO_IRQ_AFTER_RESET       BIT(1)
 #define I2C_HID_QUIRK_RESEND_REPORT_DESCR      BIT(2)
+#define I2C_HID_QUIRK_NO_RUNTIME_PM            BIT(3)
 
 /* flags */
 #define I2C_HID_STARTED                0
@@ -169,7 +170,8 @@ static const struct i2c_hid_quirks {
        { USB_VENDOR_ID_WEIDA, USB_DEVICE_ID_WEIDA_8755,
                I2C_HID_QUIRK_SET_PWR_WAKEUP_DEV },
        { I2C_VENDOR_ID_HANTICK, I2C_PRODUCT_ID_HANTICK_5288,
-               I2C_HID_QUIRK_NO_IRQ_AFTER_RESET },
+               I2C_HID_QUIRK_NO_IRQ_AFTER_RESET |
+               I2C_HID_QUIRK_NO_RUNTIME_PM },
        { USB_VENDOR_ID_SIS_TOUCH, USB_DEVICE_ID_SIS10FB_TOUCH,
                I2C_HID_QUIRK_RESEND_REPORT_DESCR },
        { 0, 0 }
@@ -1105,7 +1107,9 @@ static int i2c_hid_probe(struct i2c_client *client,
                goto err_mem_free;
        }
 
-       pm_runtime_put(&client->dev);
+       if (!(ihid->quirks & I2C_HID_QUIRK_NO_RUNTIME_PM))
+               pm_runtime_put(&client->dev);
+
        return 0;
 
 err_mem_free:
@@ -1130,7 +1134,8 @@ static int i2c_hid_remove(struct i2c_client *client)
        struct i2c_hid *ihid = i2c_get_clientdata(client);
        struct hid_device *hid;
 
-       pm_runtime_get_sync(&client->dev);
+       if (!(ihid->quirks & I2C_HID_QUIRK_NO_RUNTIME_PM))
+               pm_runtime_get_sync(&client->dev);
        pm_runtime_disable(&client->dev);
        pm_runtime_set_suspended(&client->dev);
        pm_runtime_put_noidle(&client->dev);