mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2024-10-28 23:24:50 +00:00
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>
This commit is contained in:
parent
8f3972f78f
commit
9141ad8773
1 changed files with 94 additions and 22 deletions
|
@ -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);
|
||||
|
||||
|
|
Loading…
Reference in a new issue