Skip to content

Commit

Permalink
HID: i2c-hid: Add a small delay after sleep command for Raydium touch…
Browse files Browse the repository at this point in the history
…panel

Raydium touchpanel (2386:4B33) sometimes does not work in desktop session
although it works in display manager.

During user logging, the display manager exits, close the HID device,
then the device gets runtime suspended and powered off. The desktop
session begins shortly after, opens the HID device, then the device gets
runtime resumed and powered on.

If the trasition from display manager to desktop sesesion is fast, the
touchpanel cannot switch from powered off to powered on in short
timeframe. So add a small delay to workaround the issue.

Signed-off-by: Kai-Heng Feng <kai.heng.feng@canonical.com>
Reviewed-by: Benjamin Tissoires <benjamin.tissoires@redhat.com>
Signed-off-by: Jiri Kosina <jkosina@suse.cz>
  • Loading branch information
Kai-Heng Feng authored and Jiri Kosina committed Oct 26, 2018
1 parent f112743 commit 00b790e
Show file tree
Hide file tree
Showing 2 changed files with 22 additions and 0 deletions.
3 changes: 3 additions & 0 deletions drivers/hid/hid-ids.h
Original file line number Diff line number Diff line change
Expand Up @@ -927,6 +927,9 @@
#define USB_DEVICE_ID_QUANTA_OPTICAL_TOUCH_3003 0x3003
#define USB_DEVICE_ID_QUANTA_OPTICAL_TOUCH_3008 0x3008

#define I2C_VENDOR_ID_RAYDIUM 0x2386
#define I2C_PRODUCT_ID_RAYDIUM_4B33 0x4b33

#define USB_VENDOR_ID_RAZER 0x1532
#define USB_DEVICE_ID_RAZER_BLADE_14 0x011D

Expand Down
19 changes: 19 additions & 0 deletions drivers/hid/i2c-hid/i2c-hid-core.c
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,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_NO_RUNTIME_PM BIT(2)
#define I2C_HID_QUIRK_DELAY_AFTER_SLEEP BIT(3)

/* flags */
#define I2C_HID_STARTED 0
Expand Down Expand Up @@ -158,6 +159,8 @@ struct i2c_hid {

bool irq_wake_enabled;
struct mutex reset_lock;

unsigned long sleep_delay;
};

static const struct i2c_hid_quirks {
Expand All @@ -172,6 +175,8 @@ static const struct i2c_hid_quirks {
{ I2C_VENDOR_ID_HANTICK, I2C_PRODUCT_ID_HANTICK_5288,
I2C_HID_QUIRK_NO_IRQ_AFTER_RESET |
I2C_HID_QUIRK_NO_RUNTIME_PM },
{ I2C_VENDOR_ID_RAYDIUM, I2C_PRODUCT_ID_RAYDIUM_4B33,
I2C_HID_QUIRK_DELAY_AFTER_SLEEP },
{ 0, 0 }
};

Expand Down Expand Up @@ -387,6 +392,7 @@ static int i2c_hid_set_power(struct i2c_client *client, int power_state)
{
struct i2c_hid *ihid = i2c_get_clientdata(client);
int ret;
unsigned long now, delay;

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

Expand All @@ -404,9 +410,22 @@ static int i2c_hid_set_power(struct i2c_client *client, int power_state)
goto set_pwr_exit;
}

if (ihid->quirks & I2C_HID_QUIRK_DELAY_AFTER_SLEEP &&
power_state == I2C_HID_PWR_ON) {
now = jiffies;
if (time_after(ihid->sleep_delay, now)) {
delay = jiffies_to_usecs(ihid->sleep_delay - now);
usleep_range(delay, delay + 1);
}
}

ret = __i2c_hid_command(client, &hid_set_power_cmd, power_state,
0, NULL, 0, NULL, 0);

if (ihid->quirks & I2C_HID_QUIRK_DELAY_AFTER_SLEEP &&
power_state == I2C_HID_PWR_SLEEP)
ihid->sleep_delay = jiffies + msecs_to_jiffies(20);

if (ret)
dev_err(&client->dev, "failed to change power setting.\n");

Expand Down

0 comments on commit 00b790e

Please sign in to comment.