]> git.karo-electronics.de Git - linux-beck.git/commitdiff
greybus: HID: Add runtime pm support
authorPhilip Yang <yang_philip@projectara.com>
Fri, 22 Jul 2016 21:48:14 +0000 (05:48 +0800)
committerGreg Kroah-Hartman <gregkh@google.com>
Fri, 22 Jul 2016 22:25:18 +0000 (15:25 -0700)
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: Philip Yang <yang_philip@projectara.com>
Reviewed-by: David Lin <dtwlin@google.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@google.com>
drivers/staging/greybus/hid.c

index ca0c94949c6bf3cceab395a4192bd1c16c56b58a..b558c811b7a1052e130b9a4908d4c56d29af6fd3 100644 (file)
@@ -18,6 +18,7 @@
 
 /* Greybus HID device's structure */
 struct gb_hid {
+       struct gb_bundle *bundle;
        struct gb_connection            *connection;
 
        struct hid_device               *hid;
@@ -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)
 {
-       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,
                                 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)
 {
-       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,
                             unsigned char *buf, int len)
 {
        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_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);
+
+       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,
@@ -73,11 +103,17 @@ static int gb_hid_set_report(struct gb_hid *ghid, u8 report_type, u8 report_id,
        struct gb_operation *operation;
        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,
                                        GB_HID_TYPE_SET_REPORT, size, 0,
                                        GFP_KERNEL);
-       if (!operation)
+       if (!operation) {
+               gb_pm_runtime_put_autosuspend(ghid->bundle);
                return -ENOMEM;
+       }
 
        request = operation->request->payload;
        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,
        }
 
        gb_operation_put(operation);
+       gb_pm_runtime_put_autosuspend(ghid->bundle);
 
        return ret;
 }
@@ -458,6 +495,7 @@ static int gb_hid_probe(struct gb_bundle *bundle,
        }
 
        ghid->hid = hid;
+       ghid->bundle = bundle;
 
        greybus_set_drvdata(bundle, ghid);
 
@@ -475,6 +513,8 @@ static int gb_hid_probe(struct gb_bundle *bundle,
                goto err_connection_disable;
        }
 
+       gb_pm_runtime_put_autosuspend(bundle);
+
        return 0;
 
 err_connection_disable:
@@ -493,6 +533,9 @@ static void gb_hid_disconnect(struct gb_bundle *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);
        gb_connection_disable(ghid->connection);
        gb_connection_destroy(ghid->connection);