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

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
Loading
Loading
Loading
Loading
+47 −4
Original line number Diff line number Diff line
@@ -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);