Commit 43c85a09 authored by Philip Yang's avatar Philip Yang Committed by Greg Kroah-Hartman

greybus: HID: Add runtime pm support

Modify HID greybus driver to support runtime PM framework.
The suspend and resume fucntion have been test with tutorial-hid,
e-ink-display and gpbridge-test image by sysfs resume, all HID
buttons work well on suspend/resume.

Testing Done: Compiled and verified on EVT2, DB3.5, GPB test module
              with daughter board, Red module.
Signed-off-by: default avatarPhilip Yang <yang_philip@projectara.com>
Reviewed-by: default avatarDavid Lin <dtwlin@google.com>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@google.com>
parent 68793c4c
...@@ -18,6 +18,7 @@ ...@@ -18,6 +18,7 @@
/* Greybus HID device's structure */ /* Greybus HID device's structure */
struct gb_hid { struct gb_hid {
struct gb_bundle *bundle;
struct gb_connection *connection; struct gb_connection *connection;
struct hid_device *hid; struct hid_device *hid;
...@@ -44,26 +45,55 @@ static int gb_hid_get_desc(struct gb_hid *ghid) ...@@ -44,26 +45,55 @@ static int gb_hid_get_desc(struct gb_hid *ghid)
static int gb_hid_get_report_desc(struct gb_hid *ghid, char *rdesc) static int gb_hid_get_report_desc(struct gb_hid *ghid, char *rdesc)
{ {
return gb_operation_sync(ghid->connection, GB_HID_TYPE_GET_REPORT_DESC, int ret;
ret = gb_pm_runtime_get_sync(ghid->bundle);
if (ret)
return ret;
ret = gb_operation_sync(ghid->connection, GB_HID_TYPE_GET_REPORT_DESC,
NULL, 0, rdesc, NULL, 0, rdesc,
le16_to_cpu(ghid->hdesc.wReportDescLength)); le16_to_cpu(ghid->hdesc.wReportDescLength));
gb_pm_runtime_put_autosuspend(ghid->bundle);
return ret;
} }
static int gb_hid_set_power(struct gb_hid *ghid, int type) static int gb_hid_set_power(struct gb_hid *ghid, int type)
{ {
return gb_operation_sync(ghid->connection, type, NULL, 0, NULL, 0); int ret;
ret = gb_pm_runtime_get_sync(ghid->bundle);
if (ret)
return ret;
ret = gb_operation_sync(ghid->connection, type, NULL, 0, NULL, 0);
gb_pm_runtime_put_autosuspend(ghid->bundle);
return ret;
} }
static int gb_hid_get_report(struct gb_hid *ghid, u8 report_type, u8 report_id, static int gb_hid_get_report(struct gb_hid *ghid, u8 report_type, u8 report_id,
unsigned char *buf, int len) unsigned char *buf, int len)
{ {
struct gb_hid_get_report_request request; struct gb_hid_get_report_request request;
int ret;
ret = gb_pm_runtime_get_sync(ghid->bundle);
if (ret)
return ret;
request.report_type = report_type; request.report_type = report_type;
request.report_id = report_id; request.report_id = report_id;
return gb_operation_sync(ghid->connection, GB_HID_TYPE_GET_REPORT, ret = gb_operation_sync(ghid->connection, GB_HID_TYPE_GET_REPORT,
&request, sizeof(request), buf, len); &request, sizeof(request), buf, len);
gb_pm_runtime_put_autosuspend(ghid->bundle);
return ret;
} }
static int gb_hid_set_report(struct gb_hid *ghid, u8 report_type, u8 report_id, static int gb_hid_set_report(struct gb_hid *ghid, u8 report_type, u8 report_id,
...@@ -73,11 +103,17 @@ static int gb_hid_set_report(struct gb_hid *ghid, u8 report_type, u8 report_id, ...@@ -73,11 +103,17 @@ static int gb_hid_set_report(struct gb_hid *ghid, u8 report_type, u8 report_id,
struct gb_operation *operation; struct gb_operation *operation;
int ret, size = sizeof(*request) + len - 1; int ret, size = sizeof(*request) + len - 1;
ret = gb_pm_runtime_get_sync(ghid->bundle);
if (ret)
return ret;
operation = gb_operation_create(ghid->connection, operation = gb_operation_create(ghid->connection,
GB_HID_TYPE_SET_REPORT, size, 0, GB_HID_TYPE_SET_REPORT, size, 0,
GFP_KERNEL); GFP_KERNEL);
if (!operation) if (!operation) {
gb_pm_runtime_put_autosuspend(ghid->bundle);
return -ENOMEM; return -ENOMEM;
}
request = operation->request->payload; request = operation->request->payload;
request->report_type = report_type; request->report_type = report_type;
...@@ -93,6 +129,7 @@ static int gb_hid_set_report(struct gb_hid *ghid, u8 report_type, u8 report_id, ...@@ -93,6 +129,7 @@ static int gb_hid_set_report(struct gb_hid *ghid, u8 report_type, u8 report_id,
} }
gb_operation_put(operation); gb_operation_put(operation);
gb_pm_runtime_put_autosuspend(ghid->bundle);
return ret; return ret;
} }
...@@ -458,6 +495,7 @@ static int gb_hid_probe(struct gb_bundle *bundle, ...@@ -458,6 +495,7 @@ static int gb_hid_probe(struct gb_bundle *bundle,
} }
ghid->hid = hid; ghid->hid = hid;
ghid->bundle = bundle;
greybus_set_drvdata(bundle, ghid); greybus_set_drvdata(bundle, ghid);
...@@ -475,6 +513,8 @@ static int gb_hid_probe(struct gb_bundle *bundle, ...@@ -475,6 +513,8 @@ static int gb_hid_probe(struct gb_bundle *bundle,
goto err_connection_disable; goto err_connection_disable;
} }
gb_pm_runtime_put_autosuspend(bundle);
return 0; return 0;
err_connection_disable: err_connection_disable:
...@@ -493,6 +533,9 @@ static void gb_hid_disconnect(struct gb_bundle *bundle) ...@@ -493,6 +533,9 @@ static void gb_hid_disconnect(struct gb_bundle *bundle)
{ {
struct gb_hid *ghid = greybus_get_drvdata(bundle); struct gb_hid *ghid = greybus_get_drvdata(bundle);
if (gb_pm_runtime_get_sync(bundle))
gb_pm_runtime_get_noresume(bundle);
hid_destroy_device(ghid->hid); hid_destroy_device(ghid->hid);
gb_connection_disable(ghid->connection); gb_connection_disable(ghid->connection);
gb_connection_destroy(ghid->connection); gb_connection_destroy(ghid->connection);
......
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