diff options
author | Kris Huang <huang_kris@projectara.com> | 2016-08-05 12:59:08 +0800 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@google.com> | 2016-08-05 20:14:48 +0200 |
commit | 9141ad8773f4f6ebb8cd9fa376d9497fa7e73374 (patch) | |
tree | 15fa558bdc02b4be42e1bbb4d99f5a52a7e9915f /drivers/staging/greybus/light.c | |
parent | 8f3972f78f3ac52833fb781cbb689af39fc8b0f1 (diff) | |
download | linux-9141ad8773f4f6ebb8cd9fa376d9497fa7e73374.tar.bz2 |
greybus: lights: Add runtime pm support
Modify Lights greybus driver to support runtime PM framework.
The suspend and resume function have been tested with gpbridge-test
image by sysfs. Lights functions work well on suspend/resume.
Testing Done: Compiled and verified on EVT2 and gpbridge-test module
with device class daughter board.
Signed-off-by: Kris Huang <huang_kris@projectara.com>
Reviewed-by: Viresh Kumar <viresh.kumar@linaro.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@google.com>
Diffstat (limited to 'drivers/staging/greybus/light.c')
-rw-r--r-- | drivers/staging/greybus/light.c | 116 |
1 files changed, 94 insertions, 22 deletions
diff --git a/drivers/staging/greybus/light.c b/drivers/staging/greybus/light.c index 3d42a5dafee9..fb41b0b1a98c 100644 --- a/drivers/staging/greybus/light.c +++ b/drivers/staging/greybus/light.c @@ -117,17 +117,27 @@ static int __gb_lights_flash_intensity_set(struct gb_channel *channel, u32 intensity) { struct gb_connection *connection = get_conn_from_channel(channel); + struct gb_bundle *bundle = connection->bundle; struct gb_lights_set_flash_intensity_request req; + int ret; if (channel->releasing) return -ESHUTDOWN; + ret = gb_pm_runtime_get_sync(bundle); + if (ret < 0) + return ret; + req.light_id = channel->light->id; req.channel_id = channel->id; req.intensity_uA = cpu_to_le32(intensity); - return gb_operation_sync(connection, GB_LIGHTS_TYPE_SET_FLASH_INTENSITY, - &req, sizeof(req), NULL, 0); + ret = gb_operation_sync(connection, GB_LIGHTS_TYPE_SET_FLASH_INTENSITY, + &req, sizeof(req), NULL, 0); + + gb_pm_runtime_put_autosuspend(bundle); + + return ret; } static int __gb_lights_flash_brightness_set(struct gb_channel *channel) @@ -321,32 +331,52 @@ static int channel_attr_groups_set(struct gb_channel *channel, static int gb_lights_fade_set(struct gb_channel *channel) { struct gb_connection *connection = get_conn_from_channel(channel); + struct gb_bundle *bundle = connection->bundle; struct gb_lights_set_fade_request req; + int ret; if (channel->releasing) return -ESHUTDOWN; + ret = gb_pm_runtime_get_sync(bundle); + if (ret < 0) + return ret; + req.light_id = channel->light->id; req.channel_id = channel->id; req.fade_in = channel->fade_in; req.fade_out = channel->fade_out; - return gb_operation_sync(connection, GB_LIGHTS_TYPE_SET_FADE, - &req, sizeof(req), NULL, 0); + ret = gb_operation_sync(connection, GB_LIGHTS_TYPE_SET_FADE, + &req, sizeof(req), NULL, 0); + + gb_pm_runtime_put_autosuspend(bundle); + + return ret; } static int gb_lights_color_set(struct gb_channel *channel, u32 color) { struct gb_connection *connection = get_conn_from_channel(channel); + struct gb_bundle *bundle = connection->bundle; struct gb_lights_set_color_request req; + int ret; if (channel->releasing) return -ESHUTDOWN; + ret = gb_pm_runtime_get_sync(bundle); + if (ret < 0) + return ret; + req.light_id = channel->light->id; req.channel_id = channel->id; req.color = cpu_to_le32(color); - return gb_operation_sync(connection, GB_LIGHTS_TYPE_SET_COLOR, - &req, sizeof(req), NULL, 0); + ret = gb_operation_sync(connection, GB_LIGHTS_TYPE_SET_COLOR, + &req, sizeof(req), NULL, 0); + + gb_pm_runtime_put_autosuspend(bundle); + + return ret; } #else /* LED_HAVE_GROUPS */ static int channel_attr_groups_set(struct gb_channel *channel, @@ -360,13 +390,23 @@ static int __gb_lights_led_brightness_set(struct gb_channel *channel) { struct gb_lights_set_brightness_request req; struct gb_connection *connection = get_conn_from_channel(channel); + struct gb_bundle *bundle = connection->bundle; + int ret; + + ret = gb_pm_runtime_get_sync(bundle); + if (ret < 0) + return ret; req.light_id = channel->light->id; req.channel_id = channel->id; req.brightness = (u8)channel->led->brightness; - return gb_operation_sync(connection, GB_LIGHTS_TYPE_SET_BRIGHTNESS, - &req, sizeof(req), NULL, 0); + ret = gb_operation_sync(connection, GB_LIGHTS_TYPE_SET_BRIGHTNESS, + &req, sizeof(req), NULL, 0); + + gb_pm_runtime_put_autosuspend(bundle); + + return ret; } static int __gb_lights_brightness_set(struct gb_channel *channel) @@ -441,18 +481,28 @@ static int gb_blink_set(struct led_classdev *cdev, unsigned long *delay_on, { struct gb_channel *channel = get_channel_from_cdev(cdev); struct gb_connection *connection = get_conn_from_channel(channel); + struct gb_bundle *bundle = connection->bundle; struct gb_lights_blink_request req; + int ret; if (channel->releasing) return -ESHUTDOWN; + ret = gb_pm_runtime_get_sync(bundle); + if (ret < 0) + return ret; + req.light_id = channel->light->id; req.channel_id = channel->id; req.time_on_ms = cpu_to_le16(*delay_on); req.time_off_ms = cpu_to_le16(*delay_off); - return gb_operation_sync(connection, GB_LIGHTS_TYPE_SET_BLINK, &req, - sizeof(req), NULL, 0); + ret = gb_operation_sync(connection, GB_LIGHTS_TYPE_SET_BLINK, &req, + sizeof(req), NULL, 0); + + gb_pm_runtime_put_autosuspend(bundle); + + return ret; } static void gb_lights_led_operations_set(struct gb_channel *channel, @@ -592,23 +642,29 @@ static int gb_lights_flash_strobe_set(struct led_classdev_flash *fcdev, struct gb_channel *channel = container_of(fcdev, struct gb_channel, fled); struct gb_connection *connection = get_conn_from_channel(channel); + struct gb_bundle *bundle = connection->bundle; struct gb_lights_set_flash_strobe_request req; int ret; if (channel->releasing) return -ESHUTDOWN; + ret = gb_pm_runtime_get_sync(bundle); + if (ret < 0) + return ret; + req.light_id = channel->light->id; req.channel_id = channel->id; req.state = state ? 1 : 0; ret = gb_operation_sync(connection, GB_LIGHTS_TYPE_SET_FLASH_STROBE, &req, sizeof(req), NULL, 0); - if (ret < 0) - return ret; - channel->strobe_state = state; + if (!ret) + channel->strobe_state = state; - return 0; + gb_pm_runtime_put_autosuspend(bundle); + + return ret; } static int gb_lights_flash_strobe_get(struct led_classdev_flash *fcdev, @@ -627,23 +683,29 @@ static int gb_lights_flash_timeout_set(struct led_classdev_flash *fcdev, struct gb_channel *channel = container_of(fcdev, struct gb_channel, fled); struct gb_connection *connection = get_conn_from_channel(channel); + struct gb_bundle *bundle = connection->bundle; struct gb_lights_set_flash_timeout_request req; int ret; if (channel->releasing) return -ESHUTDOWN; + ret = gb_pm_runtime_get_sync(bundle); + if (ret < 0) + return ret; + req.light_id = channel->light->id; req.channel_id = channel->id; req.timeout_us = cpu_to_le32(timeout); ret = gb_operation_sync(connection, GB_LIGHTS_TYPE_SET_FLASH_TIMEOUT, &req, sizeof(req), NULL, 0); - if (ret < 0) - return ret; - fcdev->timeout.val = timeout; + if (!ret) + fcdev->timeout.val = timeout; - return 0; + gb_pm_runtime_put_autosuspend(bundle); + + return ret; } static int gb_lights_flash_fault_get(struct led_classdev_flash *fcdev, @@ -652,6 +714,7 @@ static int gb_lights_flash_fault_get(struct led_classdev_flash *fcdev, struct gb_channel *channel = container_of(fcdev, struct gb_channel, fled); struct gb_connection *connection = get_conn_from_channel(channel); + struct gb_bundle *bundle = connection->bundle; struct gb_lights_get_flash_fault_request req; struct gb_lights_get_flash_fault_response resp; int ret; @@ -659,17 +722,21 @@ static int gb_lights_flash_fault_get(struct led_classdev_flash *fcdev, if (channel->releasing) return -ESHUTDOWN; + ret = gb_pm_runtime_get_sync(bundle); + if (ret < 0) + return ret; + req.light_id = channel->light->id; req.channel_id = channel->id; ret = gb_operation_sync(connection, GB_LIGHTS_TYPE_GET_FLASH_FAULT, &req, sizeof(req), &resp, sizeof(resp)); - if (ret < 0) - return ret; + if (!ret) + *fault = le32_to_cpu(resp.fault); - *fault = le32_to_cpu(resp.fault); + gb_pm_runtime_put_autosuspend(bundle); - return 0; + return ret; } static const struct led_flash_ops gb_lights_flash_ops = { @@ -1258,6 +1325,8 @@ static int gb_lights_probe(struct gb_bundle *bundle, if (ret < 0) goto error_connection_disable; + gb_pm_runtime_put_autosuspend(bundle); + return 0; error_connection_disable: @@ -1273,6 +1342,9 @@ static void gb_lights_disconnect(struct gb_bundle *bundle) { struct gb_lights *glights = greybus_get_drvdata(bundle); + if (gb_pm_runtime_get_sync(bundle)) + gb_pm_runtime_get_noresume(bundle); + gb_connection_disable(glights->connection); gb_connection_destroy(glights->connection); |