Commit a254a9da authored by Linus Torvalds's avatar Linus Torvalds

Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/hid/hid

Pull HID fixes from Jiri Kosina:

 - memory leak fix for hid-elo driver (Dongliang Mu)

 - fix for hangs on newer AMD platforms with amd_sfh-driven hardware
   (Basavaraj Natikar )

 - locking fix in i2c-hid (Daniel Thompson)

 - a few device-ID specific quirks

* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/hid/hid:
  HID: amd_sfh: Add interrupt handler to process interrupts
  HID: amd_sfh: Add functionality to clear interrupts
  HID: amd_sfh: Disable the interrupt for all command
  HID: amd_sfh: Correct the structure field name
  HID: amd_sfh: Handle amd_sfh work buffer in PM ops
  HID:Add support for UGTABLET WP5540
  HID: amd_sfh: Add illuminance mask to limit ALS max value
  HID: amd_sfh: Increase sensor command timeout
  HID: i2c-hid: goodix: Fix a lockdep splat
  HID: elo: fix memory leak in elo_probe
  HID: apple: Set the tilde quirk flag on the Wellspring 5 and later
parents 705d84a3 7f016b35
...@@ -37,11 +37,11 @@ static int amd_sfh_wait_response_v2(struct amd_mp2_dev *mp2, u8 sid, u32 sensor_ ...@@ -37,11 +37,11 @@ static int amd_sfh_wait_response_v2(struct amd_mp2_dev *mp2, u8 sid, u32 sensor_
{ {
union cmd_response cmd_resp; union cmd_response cmd_resp;
/* Get response with status within a max of 800 ms timeout */ /* Get response with status within a max of 1600 ms timeout */
if (!readl_poll_timeout(mp2->mmio + AMD_P2C_MSG(0), cmd_resp.resp, if (!readl_poll_timeout(mp2->mmio + AMD_P2C_MSG(0), cmd_resp.resp,
(cmd_resp.response_v2.response == sensor_sts && (cmd_resp.response_v2.response == sensor_sts &&
cmd_resp.response_v2.status == 0 && (sid == 0xff || cmd_resp.response_v2.status == 0 && (sid == 0xff ||
cmd_resp.response_v2.sensor_id == sid)), 500, 800000)) cmd_resp.response_v2.sensor_id == sid)), 500, 1600000))
return cmd_resp.response_v2.response; return cmd_resp.response_v2.response;
return SENSOR_DISABLED; return SENSOR_DISABLED;
...@@ -53,6 +53,7 @@ static void amd_start_sensor_v2(struct amd_mp2_dev *privdata, struct amd_mp2_sen ...@@ -53,6 +53,7 @@ static void amd_start_sensor_v2(struct amd_mp2_dev *privdata, struct amd_mp2_sen
cmd_base.ul = 0; cmd_base.ul = 0;
cmd_base.cmd_v2.cmd_id = ENABLE_SENSOR; cmd_base.cmd_v2.cmd_id = ENABLE_SENSOR;
cmd_base.cmd_v2.intr_disable = 1;
cmd_base.cmd_v2.period = info.period; cmd_base.cmd_v2.period = info.period;
cmd_base.cmd_v2.sensor_id = info.sensor_idx; cmd_base.cmd_v2.sensor_id = info.sensor_idx;
cmd_base.cmd_v2.length = 16; cmd_base.cmd_v2.length = 16;
...@@ -70,6 +71,7 @@ static void amd_stop_sensor_v2(struct amd_mp2_dev *privdata, u16 sensor_idx) ...@@ -70,6 +71,7 @@ static void amd_stop_sensor_v2(struct amd_mp2_dev *privdata, u16 sensor_idx)
cmd_base.ul = 0; cmd_base.ul = 0;
cmd_base.cmd_v2.cmd_id = DISABLE_SENSOR; cmd_base.cmd_v2.cmd_id = DISABLE_SENSOR;
cmd_base.cmd_v2.intr_disable = 1;
cmd_base.cmd_v2.period = 0; cmd_base.cmd_v2.period = 0;
cmd_base.cmd_v2.sensor_id = sensor_idx; cmd_base.cmd_v2.sensor_id = sensor_idx;
cmd_base.cmd_v2.length = 16; cmd_base.cmd_v2.length = 16;
...@@ -83,12 +85,51 @@ static void amd_stop_all_sensor_v2(struct amd_mp2_dev *privdata) ...@@ -83,12 +85,51 @@ static void amd_stop_all_sensor_v2(struct amd_mp2_dev *privdata)
union sfh_cmd_base cmd_base; union sfh_cmd_base cmd_base;
cmd_base.cmd_v2.cmd_id = STOP_ALL_SENSORS; cmd_base.cmd_v2.cmd_id = STOP_ALL_SENSORS;
cmd_base.cmd_v2.intr_disable = 1;
cmd_base.cmd_v2.period = 0; cmd_base.cmd_v2.period = 0;
cmd_base.cmd_v2.sensor_id = 0; cmd_base.cmd_v2.sensor_id = 0;
writel(cmd_base.ul, privdata->mmio + AMD_C2P_MSG0); writel(cmd_base.ul, privdata->mmio + AMD_C2P_MSG0);
} }
static void amd_sfh_clear_intr_v2(struct amd_mp2_dev *privdata)
{
if (readl(privdata->mmio + AMD_P2C_MSG(4))) {
writel(0, privdata->mmio + AMD_P2C_MSG(4));
writel(0xf, privdata->mmio + AMD_P2C_MSG(5));
}
}
static void amd_sfh_clear_intr(struct amd_mp2_dev *privdata)
{
if (privdata->mp2_ops->clear_intr)
privdata->mp2_ops->clear_intr(privdata);
}
static irqreturn_t amd_sfh_irq_handler(int irq, void *data)
{
amd_sfh_clear_intr(data);
return IRQ_HANDLED;
}
static int amd_sfh_irq_init_v2(struct amd_mp2_dev *privdata)
{
int rc;
pci_intx(privdata->pdev, true);
rc = devm_request_irq(&privdata->pdev->dev, privdata->pdev->irq,
amd_sfh_irq_handler, 0, DRIVER_NAME, privdata);
if (rc) {
dev_err(&privdata->pdev->dev, "failed to request irq %d err=%d\n",
privdata->pdev->irq, rc);
return rc;
}
return 0;
}
void amd_start_sensor(struct amd_mp2_dev *privdata, struct amd_mp2_sensor_info info) void amd_start_sensor(struct amd_mp2_dev *privdata, struct amd_mp2_sensor_info info)
{ {
union sfh_cmd_param cmd_param; union sfh_cmd_param cmd_param;
...@@ -193,6 +234,8 @@ static void amd_mp2_pci_remove(void *privdata) ...@@ -193,6 +234,8 @@ static void amd_mp2_pci_remove(void *privdata)
struct amd_mp2_dev *mp2 = privdata; struct amd_mp2_dev *mp2 = privdata;
amd_sfh_hid_client_deinit(privdata); amd_sfh_hid_client_deinit(privdata);
mp2->mp2_ops->stop_all(mp2); mp2->mp2_ops->stop_all(mp2);
pci_intx(mp2->pdev, false);
amd_sfh_clear_intr(mp2);
} }
static const struct amd_mp2_ops amd_sfh_ops_v2 = { static const struct amd_mp2_ops amd_sfh_ops_v2 = {
...@@ -200,6 +243,8 @@ static const struct amd_mp2_ops amd_sfh_ops_v2 = { ...@@ -200,6 +243,8 @@ static const struct amd_mp2_ops amd_sfh_ops_v2 = {
.stop = amd_stop_sensor_v2, .stop = amd_stop_sensor_v2,
.stop_all = amd_stop_all_sensor_v2, .stop_all = amd_stop_all_sensor_v2,
.response = amd_sfh_wait_response_v2, .response = amd_sfh_wait_response_v2,
.clear_intr = amd_sfh_clear_intr_v2,
.init_intr = amd_sfh_irq_init_v2,
}; };
static const struct amd_mp2_ops amd_sfh_ops = { static const struct amd_mp2_ops amd_sfh_ops = {
...@@ -225,6 +270,14 @@ static void mp2_select_ops(struct amd_mp2_dev *privdata) ...@@ -225,6 +270,14 @@ static void mp2_select_ops(struct amd_mp2_dev *privdata)
} }
} }
static int amd_sfh_irq_init(struct amd_mp2_dev *privdata)
{
if (privdata->mp2_ops->init_intr)
return privdata->mp2_ops->init_intr(privdata);
return 0;
}
static int amd_mp2_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id) static int amd_mp2_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id)
{ {
struct amd_mp2_dev *privdata; struct amd_mp2_dev *privdata;
...@@ -261,9 +314,20 @@ static int amd_mp2_pci_probe(struct pci_dev *pdev, const struct pci_device_id *i ...@@ -261,9 +314,20 @@ static int amd_mp2_pci_probe(struct pci_dev *pdev, const struct pci_device_id *i
mp2_select_ops(privdata); mp2_select_ops(privdata);
rc = amd_sfh_irq_init(privdata);
if (rc) {
dev_err(&pdev->dev, "amd_sfh_irq_init failed\n");
return rc;
}
rc = amd_sfh_hid_client_init(privdata); rc = amd_sfh_hid_client_init(privdata);
if (rc) if (rc) {
amd_sfh_clear_intr(privdata);
dev_err(&pdev->dev, "amd_sfh_hid_client_init failed\n");
return rc; return rc;
}
amd_sfh_clear_intr(privdata);
return devm_add_action_or_reset(&pdev->dev, amd_mp2_pci_remove, privdata); return devm_add_action_or_reset(&pdev->dev, amd_mp2_pci_remove, privdata);
} }
...@@ -290,6 +354,9 @@ static int __maybe_unused amd_mp2_pci_resume(struct device *dev) ...@@ -290,6 +354,9 @@ static int __maybe_unused amd_mp2_pci_resume(struct device *dev)
} }
} }
schedule_delayed_work(&cl_data->work_buffer, msecs_to_jiffies(AMD_SFH_IDLE_LOOP));
amd_sfh_clear_intr(mp2);
return 0; return 0;
} }
...@@ -312,6 +379,9 @@ static int __maybe_unused amd_mp2_pci_suspend(struct device *dev) ...@@ -312,6 +379,9 @@ static int __maybe_unused amd_mp2_pci_suspend(struct device *dev)
} }
} }
cancel_delayed_work_sync(&cl_data->work_buffer);
amd_sfh_clear_intr(mp2);
return 0; return 0;
} }
......
...@@ -49,7 +49,7 @@ union sfh_cmd_base { ...@@ -49,7 +49,7 @@ union sfh_cmd_base {
} s; } s;
struct { struct {
u32 cmd_id : 4; u32 cmd_id : 4;
u32 intr_enable : 1; u32 intr_disable : 1;
u32 rsvd1 : 3; u32 rsvd1 : 3;
u32 length : 7; u32 length : 7;
u32 mem_type : 1; u32 mem_type : 1;
...@@ -141,5 +141,7 @@ struct amd_mp2_ops { ...@@ -141,5 +141,7 @@ struct amd_mp2_ops {
void (*stop)(struct amd_mp2_dev *privdata, u16 sensor_idx); void (*stop)(struct amd_mp2_dev *privdata, u16 sensor_idx);
void (*stop_all)(struct amd_mp2_dev *privdata); void (*stop_all)(struct amd_mp2_dev *privdata);
int (*response)(struct amd_mp2_dev *mp2, u8 sid, u32 sensor_sts); int (*response)(struct amd_mp2_dev *mp2, u8 sid, u32 sensor_sts);
void (*clear_intr)(struct amd_mp2_dev *privdata);
int (*init_intr)(struct amd_mp2_dev *privdata);
}; };
#endif #endif
...@@ -27,6 +27,7 @@ ...@@ -27,6 +27,7 @@
#define HID_USAGE_SENSOR_STATE_READY_ENUM 0x02 #define HID_USAGE_SENSOR_STATE_READY_ENUM 0x02
#define HID_USAGE_SENSOR_STATE_INITIALIZING_ENUM 0x05 #define HID_USAGE_SENSOR_STATE_INITIALIZING_ENUM 0x05
#define HID_USAGE_SENSOR_EVENT_DATA_UPDATED_ENUM 0x04 #define HID_USAGE_SENSOR_EVENT_DATA_UPDATED_ENUM 0x04
#define ILLUMINANCE_MASK GENMASK(14, 0)
int get_report_descriptor(int sensor_idx, u8 *rep_desc) int get_report_descriptor(int sensor_idx, u8 *rep_desc)
{ {
...@@ -246,7 +247,8 @@ u8 get_input_report(u8 current_index, int sensor_idx, int report_id, struct amd_ ...@@ -246,7 +247,8 @@ u8 get_input_report(u8 current_index, int sensor_idx, int report_id, struct amd_
get_common_inputs(&als_input.common_property, report_id); get_common_inputs(&als_input.common_property, report_id);
/* For ALS ,V2 Platforms uses C2P_MSG5 register instead of DRAM access method */ /* For ALS ,V2 Platforms uses C2P_MSG5 register instead of DRAM access method */
if (supported_input == V2_STATUS) if (supported_input == V2_STATUS)
als_input.illuminance_value = (int)readl(privdata->mmio + AMD_C2P_MSG(5)); als_input.illuminance_value =
readl(privdata->mmio + AMD_C2P_MSG(5)) & ILLUMINANCE_MASK;
else else
als_input.illuminance_value = als_input.illuminance_value =
(int)sensor_virt_addr[0] / AMD_SFH_FW_MULTIPLIER; (int)sensor_virt_addr[0] / AMD_SFH_FW_MULTIPLIER;
......
...@@ -691,49 +691,49 @@ static const struct hid_device_id apple_devices[] = { ...@@ -691,49 +691,49 @@ static const struct hid_device_id apple_devices[] = {
{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING5_ANSI), { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING5_ANSI),
.driver_data = APPLE_HAS_FN }, .driver_data = APPLE_HAS_FN },
{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING5_ISO), { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING5_ISO),
.driver_data = APPLE_HAS_FN }, .driver_data = APPLE_HAS_FN | APPLE_ISO_TILDE_QUIRK },
{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING5_JIS), { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING5_JIS),
.driver_data = APPLE_HAS_FN | APPLE_RDESC_JIS }, .driver_data = APPLE_HAS_FN | APPLE_RDESC_JIS },
{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING6_ANSI), { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING6_ANSI),
.driver_data = APPLE_HAS_FN }, .driver_data = APPLE_HAS_FN },
{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING6_ISO), { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING6_ISO),
.driver_data = APPLE_HAS_FN }, .driver_data = APPLE_HAS_FN | APPLE_ISO_TILDE_QUIRK },
{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING6_JIS), { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING6_JIS),
.driver_data = APPLE_HAS_FN | APPLE_RDESC_JIS }, .driver_data = APPLE_HAS_FN | APPLE_RDESC_JIS },
{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING6A_ANSI), { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING6A_ANSI),
.driver_data = APPLE_HAS_FN }, .driver_data = APPLE_HAS_FN },
{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING6A_ISO), { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING6A_ISO),
.driver_data = APPLE_HAS_FN }, .driver_data = APPLE_HAS_FN | APPLE_ISO_TILDE_QUIRK },
{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING6A_JIS), { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING6A_JIS),
.driver_data = APPLE_HAS_FN | APPLE_RDESC_JIS }, .driver_data = APPLE_HAS_FN | APPLE_RDESC_JIS },
{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING5A_ANSI), { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING5A_ANSI),
.driver_data = APPLE_HAS_FN }, .driver_data = APPLE_HAS_FN },
{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING5A_ISO), { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING5A_ISO),
.driver_data = APPLE_HAS_FN }, .driver_data = APPLE_HAS_FN | APPLE_ISO_TILDE_QUIRK },
{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING5A_JIS), { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING5A_JIS),
.driver_data = APPLE_HAS_FN | APPLE_RDESC_JIS }, .driver_data = APPLE_HAS_FN | APPLE_RDESC_JIS },
{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING7_ANSI), { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING7_ANSI),
.driver_data = APPLE_HAS_FN }, .driver_data = APPLE_HAS_FN },
{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING7_ISO), { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING7_ISO),
.driver_data = APPLE_HAS_FN }, .driver_data = APPLE_HAS_FN | APPLE_ISO_TILDE_QUIRK },
{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING7_JIS), { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING7_JIS),
.driver_data = APPLE_HAS_FN | APPLE_RDESC_JIS }, .driver_data = APPLE_HAS_FN | APPLE_RDESC_JIS },
{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING7A_ANSI), { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING7A_ANSI),
.driver_data = APPLE_HAS_FN }, .driver_data = APPLE_HAS_FN },
{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING7A_ISO), { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING7A_ISO),
.driver_data = APPLE_HAS_FN }, .driver_data = APPLE_HAS_FN | APPLE_ISO_TILDE_QUIRK },
{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING7A_JIS), { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING7A_JIS),
.driver_data = APPLE_HAS_FN | APPLE_RDESC_JIS }, .driver_data = APPLE_HAS_FN | APPLE_RDESC_JIS },
{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING8_ANSI), { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING8_ANSI),
.driver_data = APPLE_HAS_FN }, .driver_data = APPLE_HAS_FN },
{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING8_ISO), { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING8_ISO),
.driver_data = APPLE_HAS_FN }, .driver_data = APPLE_HAS_FN | APPLE_ISO_TILDE_QUIRK },
{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING8_JIS), { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING8_JIS),
.driver_data = APPLE_HAS_FN | APPLE_RDESC_JIS }, .driver_data = APPLE_HAS_FN | APPLE_RDESC_JIS },
{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING9_ANSI), { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING9_ANSI),
.driver_data = APPLE_HAS_FN }, .driver_data = APPLE_HAS_FN },
{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING9_ISO), { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING9_ISO),
.driver_data = APPLE_HAS_FN }, .driver_data = APPLE_HAS_FN | APPLE_ISO_TILDE_QUIRK },
{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING9_JIS), { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING9_JIS),
.driver_data = APPLE_HAS_FN | APPLE_RDESC_JIS }, .driver_data = APPLE_HAS_FN | APPLE_RDESC_JIS },
{ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_2009_ANSI), { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_2009_ANSI),
......
...@@ -262,6 +262,7 @@ static int elo_probe(struct hid_device *hdev, const struct hid_device_id *id) ...@@ -262,6 +262,7 @@ static int elo_probe(struct hid_device *hdev, const struct hid_device_id *id)
return 0; return 0;
err_free: err_free:
usb_put_dev(udev);
kfree(priv); kfree(priv);
return ret; return ret;
} }
......
...@@ -1370,6 +1370,7 @@ ...@@ -1370,6 +1370,7 @@
#define USB_VENDOR_ID_UGTIZER 0x2179 #define USB_VENDOR_ID_UGTIZER 0x2179
#define USB_DEVICE_ID_UGTIZER_TABLET_GP0610 0x0053 #define USB_DEVICE_ID_UGTIZER_TABLET_GP0610 0x0053
#define USB_DEVICE_ID_UGTIZER_TABLET_GT5040 0x0077 #define USB_DEVICE_ID_UGTIZER_TABLET_GT5040 0x0077
#define USB_DEVICE_ID_UGTIZER_TABLET_WP5540 0x0004
#define USB_VENDOR_ID_VIEWSONIC 0x0543 #define USB_VENDOR_ID_VIEWSONIC 0x0543
#define USB_DEVICE_ID_VIEWSONIC_PD1011 0xe621 #define USB_DEVICE_ID_VIEWSONIC_PD1011 0xe621
......
...@@ -187,6 +187,7 @@ static const struct hid_device_id hid_quirks[] = { ...@@ -187,6 +187,7 @@ static const struct hid_device_id hid_quirks[] = {
{ HID_USB_DEVICE(USB_VENDOR_ID_TURBOX, USB_DEVICE_ID_TURBOX_KEYBOARD), HID_QUIRK_NOGET }, { HID_USB_DEVICE(USB_VENDOR_ID_TURBOX, USB_DEVICE_ID_TURBOX_KEYBOARD), HID_QUIRK_NOGET },
{ HID_USB_DEVICE(USB_VENDOR_ID_UCLOGIC, USB_DEVICE_ID_UCLOGIC_TABLET_KNA5), HID_QUIRK_MULTI_INPUT }, { HID_USB_DEVICE(USB_VENDOR_ID_UCLOGIC, USB_DEVICE_ID_UCLOGIC_TABLET_KNA5), HID_QUIRK_MULTI_INPUT },
{ HID_USB_DEVICE(USB_VENDOR_ID_UCLOGIC, USB_DEVICE_ID_UCLOGIC_TABLET_TWA60), HID_QUIRK_MULTI_INPUT }, { HID_USB_DEVICE(USB_VENDOR_ID_UCLOGIC, USB_DEVICE_ID_UCLOGIC_TABLET_TWA60), HID_QUIRK_MULTI_INPUT },
{ HID_USB_DEVICE(USB_VENDOR_ID_UGTIZER, USB_DEVICE_ID_UGTIZER_TABLET_WP5540), HID_QUIRK_MULTI_INPUT },
{ HID_USB_DEVICE(USB_VENDOR_ID_WALTOP, USB_DEVICE_ID_WALTOP_MEDIA_TABLET_10_6_INCH), HID_QUIRK_MULTI_INPUT }, { HID_USB_DEVICE(USB_VENDOR_ID_WALTOP, USB_DEVICE_ID_WALTOP_MEDIA_TABLET_10_6_INCH), HID_QUIRK_MULTI_INPUT },
{ HID_USB_DEVICE(USB_VENDOR_ID_WALTOP, USB_DEVICE_ID_WALTOP_MEDIA_TABLET_14_1_INCH), HID_QUIRK_MULTI_INPUT }, { HID_USB_DEVICE(USB_VENDOR_ID_WALTOP, USB_DEVICE_ID_WALTOP_MEDIA_TABLET_14_1_INCH), HID_QUIRK_MULTI_INPUT },
{ HID_USB_DEVICE(USB_VENDOR_ID_WALTOP, USB_DEVICE_ID_WALTOP_SIRIUS_BATTERY_FREE_TABLET), HID_QUIRK_MULTI_INPUT }, { HID_USB_DEVICE(USB_VENDOR_ID_WALTOP, USB_DEVICE_ID_WALTOP_SIRIUS_BATTERY_FREE_TABLET), HID_QUIRK_MULTI_INPUT },
......
...@@ -27,7 +27,6 @@ struct i2c_hid_of_goodix { ...@@ -27,7 +27,6 @@ struct i2c_hid_of_goodix {
struct regulator *vdd; struct regulator *vdd;
struct notifier_block nb; struct notifier_block nb;
struct mutex regulator_mutex;
struct gpio_desc *reset_gpio; struct gpio_desc *reset_gpio;
const struct goodix_i2c_hid_timing_data *timings; const struct goodix_i2c_hid_timing_data *timings;
}; };
...@@ -67,8 +66,6 @@ static int ihid_goodix_vdd_notify(struct notifier_block *nb, ...@@ -67,8 +66,6 @@ static int ihid_goodix_vdd_notify(struct notifier_block *nb,
container_of(nb, struct i2c_hid_of_goodix, nb); container_of(nb, struct i2c_hid_of_goodix, nb);
int ret = NOTIFY_OK; int ret = NOTIFY_OK;
mutex_lock(&ihid_goodix->regulator_mutex);
switch (event) { switch (event) {
case REGULATOR_EVENT_PRE_DISABLE: case REGULATOR_EVENT_PRE_DISABLE:
gpiod_set_value_cansleep(ihid_goodix->reset_gpio, 1); gpiod_set_value_cansleep(ihid_goodix->reset_gpio, 1);
...@@ -87,8 +84,6 @@ static int ihid_goodix_vdd_notify(struct notifier_block *nb, ...@@ -87,8 +84,6 @@ static int ihid_goodix_vdd_notify(struct notifier_block *nb,
break; break;
} }
mutex_unlock(&ihid_goodix->regulator_mutex);
return ret; return ret;
} }
...@@ -102,8 +97,6 @@ static int i2c_hid_of_goodix_probe(struct i2c_client *client, ...@@ -102,8 +97,6 @@ static int i2c_hid_of_goodix_probe(struct i2c_client *client,
if (!ihid_goodix) if (!ihid_goodix)
return -ENOMEM; return -ENOMEM;
mutex_init(&ihid_goodix->regulator_mutex);
ihid_goodix->ops.power_up = goodix_i2c_hid_power_up; ihid_goodix->ops.power_up = goodix_i2c_hid_power_up;
ihid_goodix->ops.power_down = goodix_i2c_hid_power_down; ihid_goodix->ops.power_down = goodix_i2c_hid_power_down;
...@@ -130,25 +123,28 @@ static int i2c_hid_of_goodix_probe(struct i2c_client *client, ...@@ -130,25 +123,28 @@ static int i2c_hid_of_goodix_probe(struct i2c_client *client,
* long. Holding the controller in reset apparently draws extra * long. Holding the controller in reset apparently draws extra
* power. * power.
*/ */
mutex_lock(&ihid_goodix->regulator_mutex);
ihid_goodix->nb.notifier_call = ihid_goodix_vdd_notify; ihid_goodix->nb.notifier_call = ihid_goodix_vdd_notify;
ret = devm_regulator_register_notifier(ihid_goodix->vdd, &ihid_goodix->nb); ret = devm_regulator_register_notifier(ihid_goodix->vdd, &ihid_goodix->nb);
if (ret) { if (ret)
mutex_unlock(&ihid_goodix->regulator_mutex);
return dev_err_probe(&client->dev, ret, return dev_err_probe(&client->dev, ret,
"regulator notifier request failed\n"); "regulator notifier request failed\n");
}
/* /*
* If someone else is holding the regulator on (or the regulator is * If someone else is holding the regulator on (or the regulator is
* an always-on one) we might never be told to deassert reset. Do it * an always-on one) we might never be told to deassert reset. Do it
* now. Here we'll assume that someone else might have _just * now... and temporarily bump the regulator reference count just to
* barely_ turned the regulator on so we'll do the full * make sure it is impossible for this to race with our own notifier!
* "post_power_delay" just in case. * We also assume that someone else might have _just barely_ turned
* the regulator on so we'll do the full "post_power_delay" just in
* case.
*/ */
if (ihid_goodix->reset_gpio && regulator_is_enabled(ihid_goodix->vdd)) if (ihid_goodix->reset_gpio && regulator_is_enabled(ihid_goodix->vdd)) {
ret = regulator_enable(ihid_goodix->vdd);
if (ret)
return ret;
goodix_i2c_hid_deassert_reset(ihid_goodix, true); goodix_i2c_hid_deassert_reset(ihid_goodix, true);
mutex_unlock(&ihid_goodix->regulator_mutex); regulator_disable(ihid_goodix->vdd);
}
return i2c_hid_core_probe(client, &ihid_goodix->ops, 0x0001, 0); return i2c_hid_core_probe(client, &ihid_goodix->ops, 0x0001, 0);
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment