Skip to content

Commit c216843

Browse files
author
Jiri Kosina
committed
Merge branch 'for-6.10/i2c-hid' into for-linus
- PM fixes for STM and Weida Tech devices (Kenny Levinsen)
2 parents 88a8049 + d2b34fa commit c216843

File tree

1 file changed

+27
-17
lines changed

1 file changed

+27
-17
lines changed

drivers/hid/i2c-hid/i2c-hid-core.c

Lines changed: 27 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -163,6 +163,24 @@ static u32 i2c_hid_lookup_quirk(const u16 idVendor, const u16 idProduct)
163163
return quirks;
164164
}
165165

166+
static int i2c_hid_probe_address(struct i2c_hid *ihid)
167+
{
168+
int ret;
169+
170+
/*
171+
* Some STM-based devices need 400µs after a rising clock edge to wake
172+
* from deep sleep, in which case the first read will fail. Try after a
173+
* short sleep to see if the device came alive on the bus. Certain
174+
* Weida Tech devices also need this.
175+
*/
176+
ret = i2c_smbus_read_byte(ihid->client);
177+
if (ret < 0) {
178+
usleep_range(400, 500);
179+
ret = i2c_smbus_read_byte(ihid->client);
180+
}
181+
return ret < 0 ? ret : 0;
182+
}
183+
166184
static int i2c_hid_xfer(struct i2c_hid *ihid,
167185
u8 *send_buf, int send_len, u8 *recv_buf, int recv_len)
168186
{
@@ -384,26 +402,11 @@ static int i2c_hid_set_power(struct i2c_hid *ihid, int power_state)
384402

385403
i2c_hid_dbg(ihid, "%s\n", __func__);
386404

387-
/*
388-
* Some devices require to send a command to wakeup before power on.
389-
* The call will get a return value (EREMOTEIO) but device will be
390-
* triggered and activated. After that, it goes like a normal device.
391-
*/
392-
if (power_state == I2C_HID_PWR_ON) {
393-
ret = i2c_hid_set_power_command(ihid, I2C_HID_PWR_ON);
394-
395-
/* Device was already activated */
396-
if (!ret)
397-
goto set_pwr_exit;
398-
}
399-
400405
ret = i2c_hid_set_power_command(ihid, power_state);
401406
if (ret)
402407
dev_err(&ihid->client->dev,
403408
"failed to change power setting.\n");
404409

405-
set_pwr_exit:
406-
407410
/*
408411
* The HID over I2C specification states that if a DEVICE needs time
409412
* after the PWR_ON request, it should utilise CLOCK stretching.
@@ -959,6 +962,14 @@ static int i2c_hid_core_resume(struct i2c_hid *ihid)
959962

960963
enable_irq(client->irq);
961964

965+
/* Make sure the device is awake on the bus */
966+
ret = i2c_hid_probe_address(ihid);
967+
if (ret < 0) {
968+
dev_err(&client->dev, "nothing at address after resume: %d\n",
969+
ret);
970+
return -ENXIO;
971+
}
972+
962973
/* Instead of resetting device, simply powers the device on. This
963974
* solves "incomplete reports" on Raydium devices 2386:3118 and
964975
* 2386:4B33 and fixes various SIS touchscreens no longer sending
@@ -992,8 +1003,7 @@ static int __i2c_hid_core_probe(struct i2c_hid *ihid)
9921003
struct hid_device *hid = ihid->hid;
9931004
int ret;
9941005

995-
/* Make sure there is something at this address */
996-
ret = i2c_smbus_read_byte(client);
1006+
ret = i2c_hid_probe_address(ihid);
9971007
if (ret < 0) {
9981008
i2c_hid_dbg(ihid, "nothing at this address: %d\n", ret);
9991009
return -ENXIO;

0 commit comments

Comments
 (0)