Merge branch 'for-6.10/i2c-hid' into for-linus
[linux-2.6-block.git] / drivers / hid / i2c-hid / i2c-hid-core.c
index d965382196c69e87cd79d1aad49deeab7da1bba5..632eaf9e11a6b679b0c1733167d8b00940a5d657 100644 (file)
@@ -163,6 +163,24 @@ static u32 i2c_hid_lookup_quirk(const u16 idVendor, const u16 idProduct)
        return quirks;
 }
 
+static int i2c_hid_probe_address(struct i2c_hid *ihid)
+{
+       int ret;
+
+       /*
+        * Some STM-based devices need 400µs after a rising clock edge to wake
+        * from deep sleep, in which case the first read will fail. Try after a
+        * short sleep to see if the device came alive on the bus. Certain
+        * Weida Tech devices also need this.
+        */
+       ret = i2c_smbus_read_byte(ihid->client);
+       if (ret < 0) {
+               usleep_range(400, 500);
+               ret = i2c_smbus_read_byte(ihid->client);
+       }
+       return ret < 0 ? ret : 0;
+}
+
 static int i2c_hid_xfer(struct i2c_hid *ihid,
                        u8 *send_buf, int send_len, u8 *recv_buf, int recv_len)
 {
@@ -384,26 +402,11 @@ static int i2c_hid_set_power(struct i2c_hid *ihid, int power_state)
 
        i2c_hid_dbg(ihid, "%s\n", __func__);
 
-       /*
-        * Some devices require to send a command to wakeup before power on.
-        * The call will get a return value (EREMOTEIO) but device will be
-        * triggered and activated. After that, it goes like a normal device.
-        */
-       if (power_state == I2C_HID_PWR_ON) {
-               ret = i2c_hid_set_power_command(ihid, I2C_HID_PWR_ON);
-
-               /* Device was already activated */
-               if (!ret)
-                       goto set_pwr_exit;
-       }
-
        ret = i2c_hid_set_power_command(ihid, power_state);
        if (ret)
                dev_err(&ihid->client->dev,
                        "failed to change power setting.\n");
 
-set_pwr_exit:
-
        /*
         * The HID over I2C specification states that if a DEVICE needs time
         * after the PWR_ON request, it should utilise CLOCK stretching.
@@ -959,6 +962,14 @@ static int i2c_hid_core_resume(struct i2c_hid *ihid)
 
        enable_irq(client->irq);
 
+       /* Make sure the device is awake on the bus */
+       ret = i2c_hid_probe_address(ihid);
+       if (ret < 0) {
+               dev_err(&client->dev, "nothing at address after resume: %d\n",
+                       ret);
+               return -ENXIO;
+       }
+
        /* Instead of resetting device, simply powers the device on. This
         * solves "incomplete reports" on Raydium devices 2386:3118 and
         * 2386:4B33 and fixes various SIS touchscreens no longer sending
@@ -992,8 +1003,7 @@ static int __i2c_hid_core_probe(struct i2c_hid *ihid)
        struct hid_device *hid = ihid->hid;
        int ret;
 
-       /* Make sure there is something at this address */
-       ret = i2c_smbus_read_byte(client);
+       ret = i2c_hid_probe_address(ihid);
        if (ret < 0) {
                i2c_hid_dbg(ihid, "nothing at this address: %d\n", ret);
                return -ENXIO;