static int gb_lights_flash_timeout_set(struct led_classdev_flash *fcdev, u32 timeout) { 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) fcdev->timeout.val = timeout; gb_pm_runtime_put_autosuspend(bundle); return ret; }
static int gb_lights_flash_fault_get(struct led_classdev_flash *fcdev, u32 *fault) { 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; 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) *fault = le32_to_cpu(resp.fault); gb_pm_runtime_put_autosuspend(bundle); return ret; }
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; 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_flash_strobe_set(struct led_classdev_flash *fcdev, bool state) { 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) channel->strobe_state = state; gb_pm_runtime_put_autosuspend(bundle); return ret; }
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); 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_blink_set(struct led_classdev *cdev, unsigned long *delay_on, unsigned long *delay_off) { 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; bool old_active; int ret; if (channel->releasing) return -ESHUTDOWN; mutex_lock(&channel->lock); ret = gb_pm_runtime_get_sync(bundle); if (ret < 0) goto out_unlock; old_active = channel->active; 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); ret = gb_operation_sync(connection, GB_LIGHTS_TYPE_SET_BLINK, &req, sizeof(req), NULL, 0); if (ret < 0) goto out_pm_put; if (delay_on) channel->active = true; else channel->active = false; /* we need to keep module alive when turning to active state */ if (!old_active && channel->active) goto out_unlock; /* * on the other hand if going to inactive we still hold a reference and * need to put it, so we could go to suspend. */ if (old_active && !channel->active) gb_pm_runtime_put_autosuspend(bundle); out_pm_put: gb_pm_runtime_put_autosuspend(bundle); out_unlock: mutex_unlock(&channel->lock); return ret; }
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); gb_lights_release(glights); }
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; bool old_active; int ret; mutex_lock(&channel->lock); ret = gb_pm_runtime_get_sync(bundle); if (ret < 0) goto out_unlock; old_active = channel->active; req.light_id = channel->light->id; req.channel_id = channel->id; req.brightness = (u8)channel->led->brightness; ret = gb_operation_sync(connection, GB_LIGHTS_TYPE_SET_BRIGHTNESS, &req, sizeof(req), NULL, 0); if (ret < 0) goto out_pm_put; if (channel->led->brightness) channel->active = true; else channel->active = false; /* we need to keep module alive when turning to active state */ if (!old_active && channel->active) goto out_unlock; /* * on the other hand if going to inactive we still hold a reference and * need to put it, so we could go to suspend. */ if (old_active && !channel->active) gb_pm_runtime_put_autosuspend(bundle); out_pm_put: gb_pm_runtime_put_autosuspend(bundle); out_unlock: mutex_unlock(&channel->lock); return ret; }
static void gb_vibrator_disconnect(struct gb_bundle *bundle) { struct gb_vibrator_device *vib = greybus_get_drvdata(bundle); int ret; ret = gb_pm_runtime_get_sync(bundle); if (ret) gb_pm_runtime_get_noresume(bundle); if (cancel_delayed_work_sync(&vib->delayed_work)) turn_off(vib); device_unregister(vib->dev); ida_simple_remove(&minors, vib->minor); gb_connection_disable(vib->connection); gb_connection_destroy(vib->connection); kfree(vib); }
static int turn_on(struct gb_vibrator_device *vib, u16 timeout_ms) { struct gb_bundle *bundle = vib->connection->bundle; int ret; ret = gb_pm_runtime_get_sync(bundle); if (ret) return ret; /* Vibrator was switched ON earlier */ if (cancel_delayed_work_sync(&vib->delayed_work)) turn_off(vib); ret = gb_operation_sync(vib->connection, GB_VIBRATOR_TYPE_ON, NULL, 0, NULL, 0); if (ret) { gb_pm_runtime_put_autosuspend(bundle); return ret; } schedule_delayed_work(&vib->delayed_work, msecs_to_jiffies(timeout_ms)); return 0; }
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); ret = gb_operation_sync(connection, GB_LIGHTS_TYPE_SET_COLOR, &req, sizeof(req), NULL, 0); gb_pm_runtime_put_autosuspend(bundle); return ret; }