aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/hid/i2c-hid/i2c-hid.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/hid/i2c-hid/i2c-hid.c')
-rw-r--r--drivers/hid/i2c-hid/i2c-hid.c105
1 files changed, 40 insertions, 65 deletions
diff --git a/drivers/hid/i2c-hid/i2c-hid.c b/drivers/hid/i2c-hid/i2c-hid.c
index ea3c3546cef7..8daa8ce64ebb 100644
--- a/drivers/hid/i2c-hid/i2c-hid.c
+++ b/drivers/hid/i2c-hid/i2c-hid.c
@@ -508,66 +508,6 @@ static int i2c_hid_get_report_length(struct hid_report *report)
report->device->report_enum[report->type].numbered + 2;
}
-static void i2c_hid_init_report(struct hid_report *report, u8 *buffer,
- size_t bufsize)
-{
- struct hid_device *hid = report->device;
- struct i2c_client *client = hid->driver_data;
- struct i2c_hid *ihid = i2c_get_clientdata(client);
- unsigned int size, ret_size;
-
- size = i2c_hid_get_report_length(report);
- if (i2c_hid_get_report(client,
- report->type == HID_FEATURE_REPORT ? 0x03 : 0x01,
- report->id, buffer, size))
- return;
-
- i2c_hid_dbg(ihid, "report (len=%d): %*ph\n", size, size, buffer);
-
- ret_size = buffer[0] | (buffer[1] << 8);
-
- if (ret_size != size) {
- dev_err(&client->dev, "error in %s size:%d / ret_size:%d\n",
- __func__, size, ret_size);
- return;
- }
-
- /* hid->driver_lock is held as we are in probe function,
- * we just need to setup the input fields, so using
- * hid_report_raw_event is safe. */
- hid_report_raw_event(hid, report->type, buffer + 2, size - 2, 1);
-}
-
-/*
- * Initialize all reports
- */
-static void i2c_hid_init_reports(struct hid_device *hid)
-{
- struct hid_report *report;
- struct i2c_client *client = hid->driver_data;
- struct i2c_hid *ihid = i2c_get_clientdata(client);
- u8 *inbuf = kzalloc(ihid->bufsize, GFP_KERNEL);
-
- if (!inbuf) {
- dev_err(&client->dev, "can not retrieve initial reports\n");
- return;
- }
-
- /*
- * The device must be powered on while we fetch initial reports
- * from it.
- */
- pm_runtime_get_sync(&client->dev);
-
- list_for_each_entry(report,
- &hid->report_enum[HID_FEATURE_REPORT].report_list, list)
- i2c_hid_init_report(report, inbuf, ihid->bufsize);
-
- pm_runtime_put(&client->dev);
-
- kfree(inbuf);
-}
-
/*
* Traverse the supplied list of reports and find the longest
*/
@@ -789,9 +729,6 @@ static int i2c_hid_start(struct hid_device *hid)
return ret;
}
- if (!(hid->quirks & HID_QUIRK_NO_INIT_REPORTS))
- i2c_hid_init_reports(hid);
-
return 0;
}
@@ -994,6 +931,11 @@ static int i2c_hid_of_probe(struct i2c_client *client,
}
pdata->hid_descriptor_address = val;
+ ret = of_property_read_u32(dev->of_node, "post-power-on-delay-ms",
+ &val);
+ if (!ret)
+ pdata->post_power_delay_ms = val;
+
return 0;
}
@@ -1053,6 +995,24 @@ static int i2c_hid_probe(struct i2c_client *client,
ihid->pdata = *platform_data;
}
+ ihid->pdata.supply = devm_regulator_get(&client->dev, "vdd");
+ if (IS_ERR(ihid->pdata.supply)) {
+ ret = PTR_ERR(ihid->pdata.supply);
+ if (ret != -EPROBE_DEFER)
+ dev_err(&client->dev, "Failed to get regulator: %d\n",
+ ret);
+ goto err;
+ }
+
+ ret = regulator_enable(ihid->pdata.supply);
+ if (ret < 0) {
+ dev_err(&client->dev, "Failed to enable regulator: %d\n",
+ ret);
+ goto err;
+ }
+ if (ihid->pdata.post_power_delay_ms)
+ msleep(ihid->pdata.post_power_delay_ms);
+
i2c_set_clientdata(client, ihid);
ihid->client = client;
@@ -1068,7 +1028,7 @@ static int i2c_hid_probe(struct i2c_client *client,
* real computation later. */
ret = i2c_hid_alloc_buffers(ihid, HID_MIN_BUFFER_SIZE);
if (ret < 0)
- goto err;
+ goto err_regulator;
pm_runtime_get_noresume(&client->dev);
pm_runtime_set_active(&client->dev);
@@ -1125,6 +1085,9 @@ err_pm:
pm_runtime_put_noidle(&client->dev);
pm_runtime_disable(&client->dev);
+err_regulator:
+ regulator_disable(ihid->pdata.supply);
+
err:
i2c_hid_free_buffers(ihid);
kfree(ihid);
@@ -1149,6 +1112,8 @@ static int i2c_hid_remove(struct i2c_client *client)
if (ihid->bufsize)
i2c_hid_free_buffers(ihid);
+ regulator_disable(ihid->pdata.supply);
+
kfree(ihid);
return 0;
@@ -1199,6 +1164,10 @@ static int i2c_hid_suspend(struct device *dev)
else
hid_warn(hid, "Failed to enable irq wake: %d\n",
wake_status);
+ } else {
+ ret = regulator_disable(ihid->pdata.supply);
+ if (ret < 0)
+ hid_warn(hid, "Failed to disable supply: %d\n", ret);
}
return 0;
@@ -1212,7 +1181,13 @@ static int i2c_hid_resume(struct device *dev)
struct hid_device *hid = ihid->hid;
int wake_status;
- if (device_may_wakeup(&client->dev) && ihid->irq_wake_enabled) {
+ if (!device_may_wakeup(&client->dev)) {
+ ret = regulator_enable(ihid->pdata.supply);
+ if (ret < 0)
+ hid_warn(hid, "Failed to enable supply: %d\n", ret);
+ if (ihid->pdata.post_power_delay_ms)
+ msleep(ihid->pdata.post_power_delay_ms);
+ } else if (ihid->irq_wake_enabled) {
wake_status = disable_irq_wake(client->irq);
if (!wake_status)
ihid->irq_wake_enabled = false;